使用has_many:through在Rails中嵌套表单

时间:2011-08-09 06:24:27

标签: ruby-on-rails ruby-on-rails-3 nested-forms has-many-through

我无法弄清楚如何使用has_many:through关系创建嵌套表单。我使用了这个Railscast,我看了this tutorial以及Stack Overflow和Google周围其他地方的很多问题。

我正试图通过文章表单创建标签。我的代码已经经历了很多基于来自许多不同来源的信息的迭代,但没有一个有效,但是现在我已经

文章课程

class Article < ActiveRecord::Base
    attr_accessible :content, :heading, :image, :tag_ids, :tags, :tag_name, :tag_attributes

  belongs_to :user
  has_many :comments, :dependent => :destroy
  has_many :article_tags
  has_many :tags, :through => :article_tags
  accepts_nested_attributes_for :tags, :reject_if => proc { |attributes| attributes['tag_name'].blank? }
...
end

标签类

class Tag < ActiveRecord::Base
  attr_accessible :tag_name

  has_many :article_tags
  has_many :articles, :through => :article_tags
end

article_tags的类

class ArticleTag < ActiveRecord::Base
  belongs_to :article
  belongs_to :tag
end

我的articles_controller.rb中的New是这样的:

def new
  @article = Article.new
  @tags = Tag.find(:all)
  article_tag = @article.article_tags.build()
  @article_tags = @article.tags.all
  @article.article_tags.build.build_tag
  3.times do
      article_tag = @article.article_tags.build()
  end
end

我的文章形式目前是这样的(我已经在fields_for:tags_tags中的fields_for:标签之间来回走动,或者让它们独立出来):

<%= form_for @article , :html => { :multipart => true } do |f| %>
 ...excerpted...
<%= f.fields_for :article_tags do |t| %>
  <%= t.fields_for :tags do |ta| %>
    <%= ta.label :tag_name, "Tag name" %>
    <%= ta.text_field :tag_name %>
  <% end %>
<% end %>

我意识到这可能是凌乱的;我对此非常陌生,我正在努力解决这个问题。我是否必须向articles_controller创建添加任何内容?它与attr_accessible有关吗?或者我应该做一些完全不同的事情?

编辑:

以下是Hck建议更改并创建新文章后的请求参数,选择包含tag_id 3的现有标记并尝试同时创建新标记:

在2011-08-10 19:05:46 +1000开始发布“/ articles”for 127.0.0.1   由ArticlesController处理#create as HTML   参数:{“utf8”=&gt;“✓”,“authenticity_token”=&gt;“5CQuV4RWfFZD1uDjv1DrZbIe + GB / sDQ6yiAETZutmZ4 =”,“article”=&gt; {“heading”=&gt;“测试标题”,“内容”= &gt;“测试内容”,“tag_ids”=&gt; [“3”],“article_tags”=&gt; {“tags”=&gt; {“tag_name”=&gt;“测试标记”}}},“提交” =&gt; “中提交”}   用户负载(0.2ms)SELECT“users”。* FROM“users”WHERE“users”。“id”= 1 LIMIT 1 警告:无法批量分配受保护的属性:article_tags   标记加载(0.4ms)SELECT“tags”。* FROM“tags”WHERE“tags”。“id”= 3 LIMIT 1   AREL(0.4ms)INSERT INTO“articles”(“content”,“user_id”,“created_at”,“updated_at”,“heading”,“image_file_name”,“image_content_type”,“image_file_size”)VALUES('Test Content', 1,'2011-08-10 09:05:46.228951','2011-08-10 09:05:46.228951','测试标题',NULL,NULL,NULL)   AREL(0.2ms)INSERT INTO“article_tags”(“article_id”,“tag_id”,“created_at”,“updated_at”)VALUES(88,3,'2011-08-10 09:05:46.243076','2011-08 -10 09:05:46.243076') [回形针]保存附件。 重定向到[localhost] 完成302发现在212ms

如果我将article_tags添加到文章的attr_accessible并重试,我会得到:

在2011-08-10 19:11:49 +1000开始发布“/ articles”for 127.0.0.1   由ArticlesController处理#create as HTML   参数:{“utf8”=&gt;“✓”,“authenticity_token”=&gt;“5CQuV4RWfFZD1uDjv1DrZbIe + GB / sDQ6yiAETZutmZ4 =”,“article”=&gt; {“heading”=&gt;“测试标题”,“内容”= &gt;“测试内容”,“tag_ids”=&gt; [“3”],“article_tags”=&gt; {“tags”=&gt; {“tag_name”=&gt;“测试标记”}}},“提交” =&gt; “中提交”}   用户负载(0.2ms)SELECT“users”。* FROM“users”WHERE“users”。“id”= 1 LIMIT 1   标记加载(0.4ms)SELECT“tags”。* FROM“tags”WHERE“tags”。“id”= 3 LIMIT 1 完成时间为119毫秒

ActiveRecord :: AssociationTypeMismatch(ArticleTag(#2165285820)预期,得到数组(#2151973780)):   app / controllers / articles_controller.rb:32:在'create'

2 个答案:

答案 0 :(得分:0)

尝试在控制器的操作中将@article.article_tags.build.build_tag替换为@article.tags.build

答案 1 :(得分:0)

我认为你也不必将文章标签嵌入其中。文章标签只是文章和标签之间的关联。您可以在文章中创建新标记,因为您已经与它们相关联。我相信这是来自“accepts_nested_attributes”的神奇之处。试试这个。

<%= form_for @article , :html => { :multipart => true } do |f| %>
 ...excerpted...
  <%= f.fields_for :tags, Tag.new do |t| %>
    <%= t.label :tag_name, "Tag name" %>
    <%= t.text_field :name %>
  <% end %>
<% end %>

此外,您应该尝试批量分配它,而不是使用私有参数逐个保存每个属性。我之前也遇到过嵌套表单问题,所以你可以看看我编写代码的方式: Cannot save record to database RAILS nested forms

我唯一遗漏的是私人参数部分,我建议你这样做。

private
    def venue_params
      params.require(:venue).permit(:name, :address, :discount, :latitude, :longitude, :tags_attributes =>[:name],:tag_ids => [])
    end

我还写了一篇关于嵌套表单的博客文章,所以你也可以看看它

http://minling.github.io/