Rails :: inverse_of和Association扩展

Cho*_*ett 9 ruby ruby-on-rails associations inverse ruby-on-rails-3

我有以下设置

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
Run Code Online (Sandbox Code Playgroud)

这意味着以下工作:

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
Run Code Online (Sandbox Code Playgroud)

但以下行为方式不同:

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
Run Code Online (Sandbox Code Playgroud)

如何使:inverse_of关系扩展到扩展方法?(这只是一个错误吗?)

Cho*_*ett 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
Run Code Online (Sandbox Code Playgroud)

通过将扩展名编写为Ruby中的过滤器的完整结果,而不是缩小SQL查询,扩展返回的结果正确地表现为: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
Run Code Online (Sandbox Code Playgroud)


Ari*_*tee 4

它不起作用,因为“in_hand”方法有一个返回数据库的查询。

由于 inverse_of 选项,工作代码知道如何使用内存中已有的对象。

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