9

私は次のセットアップを持っています

class Player < ActiveRecord::Base
  has_many :cards, :inverse_of => :player do
    def in_hand
      find_all_by_location('hand')
    end
  end
end

class Card < ActiveRecord::Base
  belongs_to :player, :inverse_of => :cards
end

これは、次の作業を意味します。

p = Player.find(:first)
c = p.cards[0]
p.score # => 2
c.player.score # => 2
p.score += 1
c.player.score # => 3
c.player.score += 2
p.score # => 5

ただし、次の場合は同じように動作しません。

p = Player.find(:first)
c = p.cards.in_hand[0]
p.score # => 2
c.player.score # => 2
p.score += 1
c.player.score # => 2
c.player.score += 2
p.score # => 3

d = p.cards.in_hand[1]
d.player.score # => 2

:inverse_of関係を拡張メソッドに拡張するにはどうすればよいですか? (これはただのバグですか?)

4

2 に答える 2

7

Arel によって付与された SQL の最適化をあきらめて、Ruby ですべてを実行する意思がある場合 (私のように) の回避策を見つけました。

class Player < ActiveRecord::Base
  has_many :cards, :inverse_of => :player do
    def in_hand
      select {|c| c.location == 'hand'}
    end
  end
end

class Card < ActiveRecord::Base
  belongs_to :player, :inverse_of => :cards
end

SQL クエリを絞り込むのではなく、関連付けの完全な結果を Ruby でフィルター処理する拡張機能を作成することにより、拡張機能によって返される結果は次のように正しく動作し:inverse_ofます。

p = Player.find(:first)
c = p.cards[0]
p.score # => 2
c.player.score # => 2
p.score += 1
c.player.score # => 3
c.player.score += 2
p.score # => 5

d = p.cards.in_hand[0]
d.player.score # => 5
d.player.score += 3
c.player.score # => 8
于 2010-11-12T09:23:15.690 に答える
4

「in_hand」メソッドにはデータベースに戻るクエリがあるため、機能しません。

inverse_of オプションにより、作業コードは、既にメモリ内にあるオブジェクトの使用方法を認識しています。

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

于 2010-11-11T16:36:43.060 に答える