views:

1547

answers:

1

I am trying make a complex form (like the railscast) with repeated-auto-complete (modified by Pat Shaughnessy) work for creating articles with many authors (has-many :through). I've got it working as long as I willing to always create new authors when I save an article. How can I get my associated author records to only be created when they don't already exist and just get a join table update for when they do?

I know you can you use find-or-create to get this result with the parent object but I need it for the associated objects that are saved when @article.save is called for the article.

in articles.rb

before_save :remove_blank_authors
after_update :save_authors

def remove_blank_authors
    authors.delete authors.select{ |author| author.fullname.blank?}
  end


def new_author_attributes=(author_attributes)
    author_attributes.each do |attributes|
      authors.build(attributes)
    end
  end

def existing_author_attributes=(author_attributes)
    authors.reject(&:new_record?).each do |author|
      attributes = author_attributes[author.id.to_s]
      if attributes
        author.attributes = attributes
      else
        author.delete(author)
      end
    end
  end

  def save_authors
    authors.each do |author|
      author.save(false)
    end
  end

and the authors partial of my view:

<div class="author">
  <% fields_for_author author  do |f| %>

    <%= error_messages_for :author, :object => author %>
    <%= f.label :fullname, "Author Fullname:" %>
    <%= f.text_field_with_auto_complete :author, :fullname, {}, {:method => :get } %>


    <%= link_to_function "remove", "$(this).up('.author').remove()" %>

  <% end %>
</div>

I'm using Rails 2.2.2.

The problem is that I can't see where I could use the find-or-create. At the point where the attributes for the authors are being built - new_author_attributes - I have nothing to search on - that is just pre-building empty objects I think - and at the point where the authors are being saved they are already new objects. Or am I wrong?

+2  A: 

It depends on what version of Rails you are using but you should be able to do:

 @article.authors.find_or_create_by_article_id(@author)

or

 @author.articles.find_or_create_by_author_id(@article)

then Rails "should" fill in the details for you...

In order to use find_or_create you need to have a condition to evaluate it by. That condition (the by_author_id part) can be changed to any column in the Article model.

This is one of the convention features that Rails includes which I haven't been able to find too much info on, so if this is way off, sorry ;)

vrish88