0

レールに関連付けを設定する適切な方法にまだ苦労しています。最終的に、ほとんどの作業をモデルに任せたいという結論に達しました。私の基本モデルはかなり単純です。書籍のモデル、賞のモデル、および 2 つをリンクする book_awards のモデルがあります。book モデルから 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

私の頭の中の問題は、ビルドが関連付けを作成し、それを関連付けリストの最後に追加することです。それを構築して、好きな場所に挿入する方法が必要です。

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 に答える