我仍在努力寻找在 Rails 中设置关联的适当方法。我终于推断我希望模型完成大部分工作。我的基本模型相当简单。我有一个书籍模型、一个奖项模型和一个将两者联系起来的 book_awards 模型。我想从图书模型创建 book_awards。
class Book < ActiveRecord::Base
has_many :book_awards, :inverse_of :book
has_many :awards, :through => :book_awards
end
当我处理一本新书时,建立可能的奖项列表非常容易。它看起来像这样:(在每种情况下award_list
都传入 as Award.some_scope
)
def build_book_awards(award_list)
award_list.each do |award|
book_awards.build(:award => award)
end
end
但是,在处理现有书籍时,我需要检查关联是否已经存在。一个相当简单的方法是这样的:
def build_book_awards(award_list)
award_list.each do |award|
book_rewards.build(:award => award) if book_awards.find{|s| s.award == award}.nil?
end
end
问题是这不会按奖励顺序列出奖项。相反,它将首先列出现有的 book_awards,然后是该书尚未获得的奖项。出于纯粹的审美原因,我觉得这很可怕。我希望每次都以相同的顺序列出关联。
接下来我想出了以下代码。这会按顺序列出内容,并且在编辑页面上看起来很漂亮,但是如果用户不继续更新,它会删除任何现有的关联,这会带来不可接受的副作用。
def build_book_awards(award_list)
current = book_awards.clone
book_awards.clear
award_list.each do |award|
book_award = current.find{|s| s.award == award}
if book_award
book_awards.push(book_award)
else
book_awards.build(:book => book)
end
end
end
我心中的问题是 build 创建了一个关联并将其附加到关联列表的末尾。我需要一种方法来构建它,然后将它插入到我想要的任何地方。