我有一个表单可以让我创建新的博客帖子,我希望能够从同一表单创建新类别。
我在帖子和类别之间有一种关系,这就是我遇到这个问题的原因。
我有以下两种型号:
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(而不是category),那么我的表单甚至都不会显示。
我花了一段时间试图解决这个问题,并在nested_models和simple_form上观看了最近的railscast,但无法解决我的问题。
如果我使用has_many:through关系(使用连接模型)而不是habtm,这会更容易吗?
答案 0 :(得分:1)
感谢所有回答的人。经过多次试验和错误,我设法找到了解决办法。
首先,我从HABTM切换到 has_many:通过关系,调用我的连接模型 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步:我将视图改为:
-# just showing the relevent parts
= fields_for :category do |builder|
= builder.label :name, "Name"
= builder.text_field :name
从上面的观看代码中,重要的是要注意fields_for :category
的使用,而不是有点不直观的fields_for :categories_attributes
第3步 最后,我向控制器添加了一些代码:
# 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
现在,当我创建新帖子时,我可以同时从选择菜单中选择多个现有类别和同时创建一个全新的类别 - 这不是一个或多个案例所述-其他
当编辑和更新现有帖子时,会发生一个微小错误 仅;在这种情况下,它不会让我同时创建一个新类别和选择多个现有类别 - 如果我尝试同时执行这两个类别,那么只有现有类别与帖子相关联,并且全新的被拒绝(没有错误信息)。 但是我可以通过编辑帖子两次,一次创建新类别(自动将其与帖子关联)然后第二次从菜单中选择一些其他现有类别来解决这个问题 - 比如我说这不是什么大问题,因为它一切都很好,否则我的用户可以适应这些限制
无论如何,我希望这有助于某人。
阿门。
答案 1 :(得分:0)
在您的表单中,您可能应该为每个类别呈现fields_for一次(每个帖子可以有多个类别,因此是habtm关系)。尝试类似:
- for category in @post.categories
= fields_for "post[categories_attributes][#{category.new_record? ? category.object_id : category.id}]", category do |builder|
= builder.hidden_field :id unless category.new_record?
= builder.label :content, "Name"
= builder.text_field :content
答案 2 :(得分:0)
我已经完成了我的应用程序,我的嵌套表单与HABTM一起使用。 我的模特是:
class UserProfile < ActiveRecord::Base
attr_accessible :name, :profession
has_and_belongs_to_many :cities
belongs_to :user
attr_accessible :city_ids, :cities
def self.check_city(user,city)
user.cities.find_by_id(city.id).present?
end
end
class City < ActiveRecord::Base
attr_accessible :city_name
has_and_belongs_to_many :user_profiles
end
在我的表格中,我有:
-# just showing the relevent parts
= f.fields_for :cities do|city|
= city.text_field :city_name
在我的控制器上:
def create
params[:user_profile][:city_ids] ||= []
if params[:user_profile][:cities][:city_name].present?
@city= City.create(:city_name=>params[:user_profile][:cities][:city_name])
@city.save
params[:user_profile][:city_ids] << @city.id
end
@user=current_user
params[:user_profile].delete(:cities)
@user_profile = @user.build_user_profile(params[:user_profile])
respond_to do |format|
if @user_profile.save
format.html { redirect_to @user_profile, notice: 'User profile was successfully created.' }
format.json { render json: @user_profile, status: :created, location: @user_profile }
else
format.html { render action: "new" }
format.json { render json: @user_profile.errors, status: :unprocessable_entity }
end
end
end
def update
params[:user_profile][:city_ids] ||= []
if params[:user_profile][:cities][:city_name].present?
@city= City.create(:city_name=>params[:user_profile][:cities][:city_name])
@city.save
params[:user_profile][:city_ids] << @city.id
end
@user=current_user
params[:user_profile].delete(:cities)
@user_profile = @user.user_profile
respond_to do |format|
if @user_profile.update_attributes(params[:user_profile])
format.html { redirect_to @user_profile, notice: 'User profile was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @user_profile.errors, status: :unprocessable_entity }
end
end
end
此代码有效。
答案 3 :(得分:-1)
也许你应该尝试(不是testet):
attr_accessible :category_attributes
HBTM关系并没有真正推荐......但我自己使用它们:P