我有一个表单可以让我创建新的博客文章,我希望能够从同一个表单创建新类别。
我在帖子和类别之间存在 habtm 关系,这就是我遇到问题的原因。
我有以下两种型号:
class Post < ActiveRecord::Base
has_and_belongs_to_many :categories
attr_accessible :title, :body, :category_ids
accepts_nested_attributes_for :categories # should this be singular?
end
class Category < ActiveRecord::Base
has_and_belongs_to_many :posts
attr_accessible :name
end
我的表单让我可以从一堆现有类别中进行选择或创建一个全新的类别。我的表格如下。
# using simple_form gem
.inputs
= f.input :title
= f.input :body
# the line below lets me choose from existing categories
= f.association :categories, :label => 'Filed Under'
# I was hoping that the code below would let me create new categories
= f.fields_for :category do |builder|
= builder.label :content, "Name"
= builder.text_field :content
当我提交表单时,它会得到处理,但不会创建新类别。我的命令提示符输出告诉我:
WARNING: Can't mass-assign protected attributes: category
但是,如果我添加
attr_accessible :category
,则会出现严重的崩溃并显示错误消息“未知属性:类别”。如果我将 fields_for 目标更改为 :categories (而不是类别),那么我的表单甚至不会显示。
我花了一段时间试图弄清楚这一点,并在nested_models和simple_form上观看了最近的railscast,但无法解决我的问题。
如果我使用 has_many :through 关系(使用连接模型)而不是 habtm,这会更容易吗?
最佳答案
感谢所有回答的人。经过多次反复试验,我设法想出了一个解决办法。
首先,我从 HABTM 切换到 has_many :through 关系,调用我的连接模型 categorization.rb (而不是 categorizations_posts.rb) - 注意:下面详述的修复也可能适用于 HABTM:
第 1 步:我将模型更改为如下所示:
# post.rb
class Post < ActiveRecord::Base
has_many :categorizations
has_many :categories, :through => :categorizations
attr_accessible :title, :body, :category_ids
accepts_nested_attributes_for :categories
end
#category.rb
class Category < ActiveRecord::Base
has_many :categorizations
has_many :posts, :through => :categorizations
attr_accessible :name, :post_ids
end
#categorization.rb
class Categorization < ActiveRecord::Base
belongs_to :post
belongs_to :category
end
从上面的帖子模型:显然,如果您想启用选择多个 现有类别 ,则必须存在名为 :category_ids 的访问器,但您 不需要 需要一个访问器方法来为 创建新类别...不知道。
第 2 步:我将 View 更改为如下所示:
-# just showing the relevent parts
= fields_for :category do |builder|
= builder.label :name, "Name"
= builder.text_field :name
从上面的 View 代码中,重要的是要注意
fields_for :category
的使用,而不是有点不直观的 fields_for :categories_attributes
第 3 步
最后,我在 Controller 中添加了一些代码:
# POST /posts
# POST /posts.xml
def create
@post = Post.new(params[:post])
@category = @post.categories.build(params[:category]) unless params[:category][:name].blank?
# stuff removed
end
def update
@post = Post.find(params[:id])
@category = @post.categories.build(params[:category]) unless params[:category][:name].blank?
# stuff removed
end
现在,当我创建一个新帖子时,我可以同时从选择菜单中选择多个现有类别 和 同时创建一个全新的类别 - 这不是一个或另一个的情况
有一个小错误 在编辑和更新现有帖子时只发生 ;在这种情况下,它不会让我同时创建一个新类别 和 选择多个现有类别 - 如果我尝试同时执行这两项操作,那么只有现有类别与帖子相关联,而全新的类别被拒绝(没有错误消息)。 但是 我可以通过两次编辑帖子来解决这个问题,一次创建新类别(自动将其与帖子关联),然后第二次从菜单中选择一些其他现有类别 - 就像我说的那样很重要,因为否则一切都很好,我的用户可以适应这些限制
无论如何,我希望这对某人有所帮助。
阿门。
关于ruby-on-rails - HABTM 关系和 accepts_nested_attributes_for,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3995576/