开发者

Nested forms in Rails using has_many :through

开发者 https://www.devze.com 2023-03-27 04:32 出处:网络
I am having trouble figuring out how to make a nested form using a has_many :through relationship. I used this Railscast and I took at look at this tutorial and lots of the questions on Stack Overflow

I am having trouble figuring out how to make a nested form using a has_many :through relationship. I used this Railscast and I took at look at this tutorial and lots of the questions on Stack Overflow and elsewhere around Google.

I'm trying to make a way to create tags via the articles form. My code has gone through lots of iterations based on information from lots of different sources and none of them have worked, but right now I have

A class for articles

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

A class for tags

class Tag < ActiveRecord::Base
  attr_accessible :tag_name

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

A class for article_tags

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

The New in my articles_controller.rb is like this:

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

And my form for articles is currently like this (I have gone back and forth between nesting the fields_for :tags inside the fields_for :article_tags or just letting them be on their own):

<%= 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 %>

I realize this is probably messy; I'm pretty new at this and I'm trying to figure it out. Do I have to add anything to the articles_controller create? Is it something to do with the attr_accessible? Or should I do something completely different?

EDIT:

Here are the request parameters after making the change suggest开发者_运维百科ed by Hck and creating a new article, selecting an existing tag with tag_id 3 and trying to also create a new tag at the same time:

Started POST "/articles" for 127.0.0.1 at 2011-08-10 19:05:46 +1000 Processing by ArticlesController#create as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"5CQuV4RWfFZD1uDjv1DrZbIe+GB/sDQ6yiAETZutmZ4=", "article"=>{"heading"=>"Test heading", "content"=>"Test Content", "tag_ids"=>["3"], "article_tags"=>{"tags"=>{"tag_name"=>"Test tag"}}}, "commit"=>"Submit"} User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1 WARNING: Can't mass-assign protected attributes: article_tags Tag Load (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', 'Test heading', 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') [paperclip] Saving attachments. Redirected to [localhost] Completed 302 Found in 212ms

And if I add :article_tags to the attr_accessible for Article and try again, I get:

Started POST "/articles" for 127.0.0.1 at 2011-08-10 19:11:49 +1000 Processing by ArticlesController#create as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"5CQuV4RWfFZD1uDjv1DrZbIe+GB/sDQ6yiAETZutmZ4=", "article"=>{"heading"=>"Test heading", "content"=>"Test content", "tag_ids"=>["3"], "article_tags"=>{"tags"=>{"tag_name"=>"Test tag "}}}, "commit"=>"Submit"} User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1 Tag Load (0.4ms) SELECT "tags".* FROM "tags" WHERE "tags"."id" = 3 LIMIT 1 Completed in 119ms

ActiveRecord::AssociationTypeMismatch (ArticleTag(#2165285820) expected, got Array(#2151973780)): app/controllers/articles_controller.rb:32:in `create'


Try to replace @article.article_tags.build.build_tag with @article.tags.build in your controller`s action.


I don't think you have to nest the article tags in it too. Article tags is just an association between the articles and tags. You can simply create the new tag within the articles because you already associated with them. I believe it is from the magic of the "accepts_nested_attributes". try this.

<%= 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 %>

Also, you should try to mass assign it instead of saving every attribute piece by piece by using private params. I had a nested forms problem before too, so you can take a look at how I wrote my code: Cannot save record to database RAILS nested forms

The only thing I left out there was the private params section, which I recommended you to do.

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

I also wrote a blog post about nested forms, so you can take a look at it too

http://minling.github.io/

0

精彩评论

暂无评论...
验证码 换一张
取 消