Russell Quinn
Russell Quinn

Reputation: 1350

How can I create, associate, and de-associate related records in Rails ActiveRecord with accepts_nested_attributes_for

I have a typical has_many relationship between two models (lets say Article has_many Authors.)

My Article form lets the user:

  1. Create new Authors and associate them with the Article,
  2. Select existing Authors to associate with the Article,
  3. Remove the association with an Author (without deleting the Author record.)

I am using accepts_nested_attributes_for and this handles #1 perfectly. However, I am yet to find the best way of implementing #2 and #3 while still using accepts_nested_attributes_for.

I actually had this all working with Rails 3.0.0. ActiveRecord would automatically create a new association when given an Author id that it had not seen before. But it turned out I was accidentally exploiting the security bug that was then fixed in Rails 3.0.1.

I've tried a bunch of different approaches, but nothing works completely and I can't find much information on best practices in this case.

Any advice would be appreciate.

Thanks,

Russell.

Upvotes: 4

Views: 737

Answers (3)

Mauricio Pasquier Juan
Mauricio Pasquier Juan

Reputation: 2375

For completeness, the way I'm doing this now is this:

class Article < ActiveRecord::Base
  belongs_to :author, validate: false
  accepts_nested_attributes_for :author

  # This is called automatically when we save the article
  def autosave_associated_records_for_author
    if author.try(:name)
      self.author = Author.find_or_create_by_name(author.name)
    else
      self.author = nil # Remove the association if we send an empty text field
    end
  end

end

class Author < ActiveRecord::Base
  has_many :articles
end

I haven't found a way to validate the associated model (Author) with it's validations..

Upvotes: 1

aceofspades
aceofspades

Reputation: 7586

Assuming you probably need to use a join table. Give this a go:

class Article < ActiveRecord::Base
  has_many :article_authors
  accepts_nested_attributes_for :article_authors, allow_delete: true
end

class Author < ActiveRecord::Base
  has_many :article_authors
end

class ArticleAuthor < ActiveRecord::Base
  belongs_to :article
  belongs_to :author
  accepts.nested_attributes_for :author
end


# PUT /articles/:id
params = {
  id: 10,
  article_authors_attributes: {
    [
      # Case 1, create and associate new author, since no ID is provided
      {
        # A new ArticleAuthor row will be created since no ID is supplied
        author_attributes: {
          # A new Author will be created since no ID is supplied
          name: "New Author"
        }
      }

    ],
    [
      # Case 2, associate Author#100
      {
        # A new ArticleAuthor row will be created since no ID is supplied
        author_attributes: {
          # Referencing the existing Author#100
          id: 100
        }
      }
    ],
    [
      # Case 3, delete ArticleAuthor#101
      # Note that in this case you must provide the ID to the join table to delete
      {
        id: 1000,
        _destroy: 1
      }
    ]
  }
}

Upvotes: 2

BvuRVKyUVlViVIc7
BvuRVKyUVlViVIc7

Reputation: 11821

Look at this: http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes

its for rails 2.3, but most of the syntax is the same with rails3... It mentions all things you look for..

Upvotes: 1

Related Questions