2011-03-28 4 views
9

Я прибил все, что захочу, но я не могу понять, как это делают дизайнеры рельсов. В принципе, у меня есть (пожалуйста, отложите плюрализацию/и т.д. вопросы):Has_Many: Через или: finder_sql

Human Отношение (Родитель, Offspring)

Я пытаюсь получить все отпрыски для одного из родителей, и единственный родитель для многих потомки (предполагают только одного родителя на потомство).

Я могу сделать это следующим образом в модели:

has_one  :parent, :through => :relationships, :foreign_key => :human_id, :source => :source_human 
has_many :offsprings, :finder_sql => 
      'SELECT DISTINCT offsprings.* ' + 
      'FROM humans offsprings INNER JOIN relationships r on ' + 
      'r.human_id = offsprings.id where r.source_human_id = #{id}' 

Я должен был сделать это, потому что лучше способ сделать это:

has_many :offsprings, :through => :relationships, :foreign_key => :source_human_id, :source => :human 

Не представляется возможным, так как внешние ключи игнорируются в has_many (согласно документации здесь: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many)

Однако, теперь я получаю эту ошибку:

DEPRECATION WARNING: String-based interpolation of association conditions is deprecated. Please use a proc instead. So, for example, has_many :older_friends, :conditions => 'age > #{age}' should be changed to has_many :older_friends, :conditions => proc { "age > #{age}" }. (called from irb_binding at (irb):1)

Однако, независимо от того, как я взламываю: условия здесь, не выглядит так: finder_sql хочет участвовать. Есть предположения?

ответ

35

Что делать, если вы

has_many :offsprings, :finder_sql => 
      proc { "SELECT DISTINCT offsprings.* " + 
      "FROM humans offsprings INNER JOIN relationships r on " + 
      "r.human_id = offsprings.id where r.source_human_id = #{id}" } 
+2

Дамы и микробы, победитель. Документы здесь неправильные, вы не делаете: условия на: finder_sql, вы просто создаете его. – aronchick

4

На самом деле, я бы написать так:

has_many :offsprings, :finder_sql => proc {OFFSPRING_SQL % {id: id}} 

OFFSPRING_SQL = "SELECT DISTINCT offsprings.* 
        FROM humans offsprings 
        INNER JOIN relationships r 
         ON r.human_id = offsprings_id 
         WHERE r.source_human_id = %{id}" 

Я думаю, что это делает объединение легче понять, и это сделать голый SQL проще редактировать. Он также использует штриховую интерполяцию параметров.

Смежные вопросы