Rails:: inverse_of и расширения Ассоциации - PullRequest
9 голосов
/ 10 ноября 2010

У меня есть следующие настройки

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 ]

7 голосов
/ 12 ноября 2010

Я нашел обходной путь, если (как и я) вы готовы отказаться от оптимизации SQL, предоставленной Arel, и просто сделать все это в 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

При написании расширения для фильтрации в 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
4 голосов
/ 11 ноября 2010

Это не работает, потому что метод "in_hand" имеет запрос, который возвращается к базе данных.

Благодаря опции inverse_of рабочий код знает, как использовать объекты, которые уже находятся в памяти.

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

...