I have three models Article, Author, and AuthorLine presenting relationship between article and its authors, in a many-to-many mapping.
class Article < ActiveRecord::Base
has_many :author_lines, :dependent => :destroy
has_many :authors, :through => :author_lines, :dependent => :destroy, :order => 'author_lines.position'
attr_accessor :author_list
end
class Author < ActiveRecord::Base
has_many :author_lines
has_many :articles, :through => :author_lines
end
class AuthorLine < ActiveRecord::Base
validates :author_id, :article_id, :position, :presence => true
belongs_to :author, :counter_cache => :articles_count
belongs_to :article
end
The AuthorLine model has an additional attribute position, which tells the order of authors for an article.
Here is what I am doing to create an article with given author names, in article.rb:
def author_list=(raw)
self.authors.clear
raw.split(',').map(&:strip).each_with_index do |e, i|
next if e.blank?
author = Author.find_or_create_by_name(e)
#1
self.authors << author
#2
# AuthorLine.create(:author_id => author.id, :article_id => self.id, :position => i)
end
end
The problem is I have no idea when to update the position attributes of corresponding AuthorLines. if I remove the line #1 and uncomment the line #2, the created AuthorLine may have a nil arctile_id since self.id may not be given.
I’d probably move the code for creating AuthorLines to an
after_createhook in your Article model. If I understand the problem correctly, something like this should do the trick:That way, you only wind up setting the AuthorLine positions after your article is already created and has an ID. This also checks to make sure an AuthorLine has already been created; I believe that an AuthorLine would get created every time an author is added to an article but I like to have very explicit checks in callbacks like this.