2010-10-22 98 views
4

我有一个表格,让我创造新的博客文章,我希望能够创建相同的形式新类别HABTM关系和accepts_nested_attributes_for

我有帖子和类别之间的关系,这就是为什么我遇到麻烦。

我有以下2种型号:

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 target更改为:categories(而不是category),那么我的表单甚至不会显示。

我花了一段时间试图弄清楚这一点,并观察了nested_models和simple_form上最近的railscasts,但无法解决我的问题。

如果我使用has_many:through关系(使用连接模型)而不是habtm,会更容易吗?

+0

http://stackoverflow.com/a/12961298/1446551 – 2013-04-30 07:48:05

回答

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 

从上面桩模型:很明显,访问命名:CA tegory_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

也许你应该(不testet)尝试:

attr_accessible :category_attributes 

而且HBTM关系的arent真正recommened ...但我使用它们在我自己的:P

+0

我试过这个,也使用categories_attributes(在模型和表单中),都没有工作。你会推荐使用has_many:through代替吗?我认为我会立即行动 – stephenmurdoch 2010-10-22 10:54:44

+0

Baybe你在用non-hbtm解决这个问题上更快:P – Lichtamberg 2010-10-22 10:58:14

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 
+0

不错的想法,但没有用 - 我修复了问题,一旦我找到答案,已停止启动 – stephenmurdoch 2010-10-22 12:53:20

+0

啊,好的。我期待着看到你的解决方案... – Yannis 2010-10-22 13:36:43

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 

此代码的工作。