如何在 has_and_belongs_to_many 关系中设置 rails 模型?
How do I set up the rails models in a has_and_belongs_to_many relationship?
我正在开发博客 rails 应用程序。我想让每个 post 都有很多标签,并且能够显示属于给定标签的所有 post。在 Rails Guide and I also tried this tutorial.
之后,我已经完成了 has_and_belongs_to_many
关系的设置
两次我都在设置模型后进入 rails 控制台,检查 table 的格式是否正确。我调用了 Post.new
和 Tag.new
。每个都在 table 中给我一个新的 instance/entry,但都没有显示用于引用另一个的列。不应该有一个吗?如果没有,我应该如何构建我的种子数据?
到目前为止,我只在处理 belongs_to 和 has_many 关系。如果有人在 has_and_belongs_to_many
上有 link 到更好的 explanation/tutorial,我也将不胜感激,我的搜索结果还没有很清楚。
这是我的代码:
post.rb:
class Post < ActiveRecord::Base
has_and_belongs_to_many :tags
belongs_to :categories
end
tag.rb:
class Tag < ActiveRecord::Base
has_and_belongs_to_many :posts
end
longnumber_create_posts.rb:
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :name
t.string :content
t.datetime :pub_time
t.integer :category_id
t.timestamps null: false
end
end
end
lognumber_create_tags.rb:
class CreateTags < ActiveRecord::Migration
def change
create_table :tags do |t|
t.string :name
t.timestamps null: false
end
end
end
longnumber_create_posts_and_tags.rb:
class CreatePostsAndTags < ActiveRecord::Migration
def change
create_table :posts_tags, id: false do |t|
t.belongs_to :post, index: true
t.belongs_to :tag, index: true
end
end
end
schema.rb:
ActiveRecord::Schema.define(version: 20151123235501) do
create_table "posts", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "posts_tags", id: false, force: :cascade do |t|
t.integer "post_id"
t.integer "tag_id"
end
add_index "posts_tags", ["post_id"], name: "index_posts_tags_on_post_id"
add_index "posts_tags", ["tag_id"], name: "index_posts_tags_on_tag_id"
create_table "tags", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
您需要在 Tag
and/or Post
上调用 create
,否则记录不会存储在数据库中。
下面您将创建一个 post 和一个与之相关的标签 post。
post = Post.create!(content: "my content")
post.tags.create!(name: "movies")
您可以将 Tag
或 Post
视为数组。例如:
post = Post.create!(title: 'title')
tag = Tag.create!(name: 'test')
tag.posts << post
您已经分别实例化了标签和 Post,但需要让一个对象了解另一个对象。此关联是在您创建的联接 table 中建立的。您可以通过几种方式建立这些关联:
选项 1
Post.create(name: text) # assuming your db was empty, this post now has id = 1
Tag.create(name: text, post_id: 1)
选项 2
post = Post.create(name: text)
tag = Tag.create(name: text)
# associate tag with post
post.tags << tag
选项 2 可能更可取,通常可以在您的控制器中调用。例如:
# in PostsController
def create
post = Post.create(post_params)
tag = Tag.find_or_create_by(params[:tag_id])
post.tags << tag
render root_path
end
private
def post_params
params.require(:post).permit(:name, :content, :pub_time, :category_id, :tag_id)
end
在多对多关系中,使用您的示例,您不会在 Post 或标记 table 中看到外键,因为它使用的是 "join" table 您创建了名为 Post 的标签来存储关系。由于您已经在 3 个模型(Post、Tag、PostTag)中设置了 has_many 和 belongs_to 关联,因此您现在必须告诉 Rails在这些 post 和标签之间创建关联。这是按如下方式完成的:
@post = Post.new
@tag = Tag.last (The last is just an example, make sure to use the instance you need!
@post.tags << @tag #This is where the magic happens and the association is formed
最近大多数 Rails 社区已经转向使用 "has_many through" 方法,因为它允许将额外的属性添加到连接 table 而在这里你只能存储外键在 Post 标签 table.
更新:根据以下关于此代码去向的评论:
通常这会在您的控制器中执行,但您也可以在 rails 控制台中执行此操作。例如,如果您有一些 post 的表单输入,并在提交表单时添加了一个标签 ID 来关联它,您的控制器很可能看起来像这样:
def create
@post = Post.create(post_params)
if @post.save
@tag = Tag.find(params[:tag_id])
@post.tags << @tag
redirect_to some_fun_path
else
render 'new'
end
private
def post_params
params.require(:post).permit(:tag_id, :title, :description, etc.)
end
我正在开发博客 rails 应用程序。我想让每个 post 都有很多标签,并且能够显示属于给定标签的所有 post。在 Rails Guide and I also tried this tutorial.
之后,我已经完成了has_and_belongs_to_many
关系的设置
两次我都在设置模型后进入 rails 控制台,检查 table 的格式是否正确。我调用了 Post.new
和 Tag.new
。每个都在 table 中给我一个新的 instance/entry,但都没有显示用于引用另一个的列。不应该有一个吗?如果没有,我应该如何构建我的种子数据?
到目前为止,我只在处理 belongs_to 和 has_many 关系。如果有人在 has_and_belongs_to_many
上有 link 到更好的 explanation/tutorial,我也将不胜感激,我的搜索结果还没有很清楚。
这是我的代码:
post.rb:
class Post < ActiveRecord::Base
has_and_belongs_to_many :tags
belongs_to :categories
end
tag.rb:
class Tag < ActiveRecord::Base
has_and_belongs_to_many :posts
end
longnumber_create_posts.rb:
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :name
t.string :content
t.datetime :pub_time
t.integer :category_id
t.timestamps null: false
end
end
end
lognumber_create_tags.rb:
class CreateTags < ActiveRecord::Migration
def change
create_table :tags do |t|
t.string :name
t.timestamps null: false
end
end
end
longnumber_create_posts_and_tags.rb:
class CreatePostsAndTags < ActiveRecord::Migration
def change
create_table :posts_tags, id: false do |t|
t.belongs_to :post, index: true
t.belongs_to :tag, index: true
end
end
end
schema.rb:
ActiveRecord::Schema.define(version: 20151123235501) do
create_table "posts", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "posts_tags", id: false, force: :cascade do |t|
t.integer "post_id"
t.integer "tag_id"
end
add_index "posts_tags", ["post_id"], name: "index_posts_tags_on_post_id"
add_index "posts_tags", ["tag_id"], name: "index_posts_tags_on_tag_id"
create_table "tags", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
您需要在 Tag
and/or Post
上调用 create
,否则记录不会存储在数据库中。
下面您将创建一个 post 和一个与之相关的标签 post。
post = Post.create!(content: "my content")
post.tags.create!(name: "movies")
您可以将 Tag
或 Post
视为数组。例如:
post = Post.create!(title: 'title')
tag = Tag.create!(name: 'test')
tag.posts << post
您已经分别实例化了标签和 Post,但需要让一个对象了解另一个对象。此关联是在您创建的联接 table 中建立的。您可以通过几种方式建立这些关联:
选项 1
Post.create(name: text) # assuming your db was empty, this post now has id = 1
Tag.create(name: text, post_id: 1)
选项 2
post = Post.create(name: text)
tag = Tag.create(name: text)
# associate tag with post
post.tags << tag
选项 2 可能更可取,通常可以在您的控制器中调用。例如:
# in PostsController
def create
post = Post.create(post_params)
tag = Tag.find_or_create_by(params[:tag_id])
post.tags << tag
render root_path
end
private
def post_params
params.require(:post).permit(:name, :content, :pub_time, :category_id, :tag_id)
end
在多对多关系中,使用您的示例,您不会在 Post 或标记 table 中看到外键,因为它使用的是 "join" table 您创建了名为 Post 的标签来存储关系。由于您已经在 3 个模型(Post、Tag、PostTag)中设置了 has_many 和 belongs_to 关联,因此您现在必须告诉 Rails在这些 post 和标签之间创建关联。这是按如下方式完成的:
@post = Post.new
@tag = Tag.last (The last is just an example, make sure to use the instance you need!
@post.tags << @tag #This is where the magic happens and the association is formed
最近大多数 Rails 社区已经转向使用 "has_many through" 方法,因为它允许将额外的属性添加到连接 table 而在这里你只能存储外键在 Post 标签 table.
更新:根据以下关于此代码去向的评论:
通常这会在您的控制器中执行,但您也可以在 rails 控制台中执行此操作。例如,如果您有一些 post 的表单输入,并在提交表单时添加了一个标签 ID 来关联它,您的控制器很可能看起来像这样:
def create
@post = Post.create(post_params)
if @post.save
@tag = Tag.find(params[:tag_id])
@post.tags << @tag
redirect_to some_fun_path
else
render 'new'
end
private
def post_params
params.require(:post).permit(:tag_id, :title, :description, etc.)
end