Rails:如何在构建前添加或插入关联?

时间:2012-11-28 06:59:47

标签: ruby-on-rails-3 associations

我仍在努力设置在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

我的想法是,构建会创建一个关联,并将其附加到关联列表的末尾。我需要一种方法来构建它,然后将它插入我想要的任何地方。

1 个答案:

答案 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

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