0

我仍在努力寻找在 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 创建了一个关联并将其附加到关联列表的末尾。我需要一种方法来构建它,然后将它插入到我想要的任何地方。

4

1 回答 1

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

我仍然觉得我错过了一些东西,因为这对我来说似乎太有用了,不能以某种方式包含在内。

于 2012-11-30T01:43:11.577 回答