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

时间:2012-01-15 06:03:36

标签: ruby-on-rails activerecord associations

我有三个模型ArticleAuthorAuthorLine在多对多映射中呈现文章与作者之间的关系。

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

问题是我不知道何时更新相应position的{​​{1}}属性。如果我删除第1行并取消注释第2行,则创建的AuthorLine可能只有AuthorLine,因为arctile_id可能没有给出。

1 个答案:

答案 0 :(得分:1)

我可能会将用于创建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,但我喜欢在回调中进行非常明确的检查。