我仍在努力设置在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
都作为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
我的想法是,构建会创建一个关联,并将其附加到关联列表的末尾。我需要一种方法来构建它,然后将它插入我想要的任何地方。
答案 0 :(得分:0)
如果有其他人感兴趣,这样的事情就有效了。在我的真实应用程序中,我继续前进,使它更通用。
def build_book_awards(award_list)
award_list.each_with_index do |award, idx|
unless index = book_awards.find_index{|s| s.award == award}
event_awards.build(:award_id => award.id)
index = -1
end
book_awards.insert(idx, book_awards.delete_at(index))
end
end
我仍然觉得我错过了一些东西,因为这对我来说太有用了,不能以某种方式包括在内。