在保存模型之前更新其他关联属性

问题描述:

我有三个模型Article,AuthorAuthorLine以多对多映射表示文章及其作者之间的关系。在保存模型之前更新其他关联属性

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 

AuthorLine模型有一个附加属性position,它告诉作者的顺序的文章。

下面是我在做什么,以创建具有给定的作者姓名的一篇文章,在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 

的问题是我不知道什么时候更新对应AuthorLine S的position属性。如果删除线#1,并取消对线路#2中,创建AuthorLine可以具有零arctile_id因为self.id可能不给出。

我可能会移动代码在你的文章模型创建AuthorLines到after_create钩。如果我理解正确的问题,这样的事情应该做的伎俩:

after_create :set_author_line_positions 

def set_author_line_positions 
    self.authors.each_with_index do |author, index| 
    existing_author_line = AuthorLine.where("author_id = ? and article_id = ?", author.id, article.id).first 
    if existing_author_line 
     existing_author_line.update_attributes(:position => index) 
    else 
     AuthorLine.create(:author_id => author.id, :article_id => self.id, :position => index) 
    end 
    end 
end 

这样的话,你只能拉闸后已创建您的文章,并有一个ID设置AuthorLine位置。这也检查以确保已经创建了AuthorLine;我相信,一个AuthorLine会得到创建的每个作者被添加到文章的时间,但我喜欢在这样的回调很明确的检查。