我有三个模型Article
,Author
和AuthorLine
在多对多映射中呈现文章与作者之间的关系。
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
可能没有给出。
答案 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,但我喜欢在回调中进行非常明确的检查。