代码之家  ›  专栏  ›  技术社区  ›  Chowlett

Rails::逆和关联扩展

  •  9
  • Chowlett  · 技术社区  · 14 年前

    我有以下设置

    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

    2 回复  |  直到 14 年前
        1
  •  4
  •   RajeshT    13 年前

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

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

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

        2
  •  7
  •   Chowlett    14 年前

    我已经找到了一个解决方法,如果(我是)你愿意放弃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
    

    :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