I have the following set-up
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
This means the following works:
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
But the following doesn't behave the same way:
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
How can I make the :inverse_of
relationship extend to the extension methods? (Is this just a bug?)
I have found a workaround if (as I am) you're willing to give up the SQL optimisation granted by Arel and just do it all in 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
By writing the extension to filter in Ruby the full results of the association, rather than narrowing down the SQL query, results returned by the extension behave correctly with :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