Как методы ассоциации направляющих работают?

Интересный. Я на самом деле никогда не видел, что диалоговое окно - знаю, что существует опция позволить/запретить выполнить предыдущую успешную сборку, поэтому возможно, это показывает диалоговое окно сначала. Можно изучить отключение его, если Вы не будете использовать его.

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

20
задан Chirantan 7 October 2009 в 05:14
поделиться

3 ответа

На самом деле это работает так, что объект ассоциации является «прокси-объектом». Конкретный класс - AssociationProxy . Если вы посмотрите на строку 52 этого файла, вы увидите:

instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_|^object_id$)/ }

При этом такие методы, как class , больше не существуют для этого объекта. Таким образом, если вы вызовете class для этого объекта, вы получите отсутствующий метод. Итак, существует method_missing , реализованный для прокси-объекта, который перенаправляет вызов метода «цели»:

def method_missing(method, *args)
  if load_target
    unless @target.respond_to?(method)
      message = "undefined method `#{method.to_s}' for \"#{@target}\":#{@target.class.to_s}"
      raise NoMethodError, message
    end

    if block_given?
      @target.send(method, *args)  { |*block_args| yield(*block_args) }
    else
      @target.send(method, *args)
    end
  end
end

Цель - это массив, поэтому, когда вы вызываете класс для этого объекта , он говорит, что это массив, но только потому, что целью является массив, фактический класс - это AssociationProxy, но вы больше этого не видите.

Итак, все методы, которые вы добавляете, такие как of_sector , добавляются к прокси-серверу ассоциации, поэтому они вызываются напрямую. Такие методы, как [] и class , не определены в прокси-сервере ассоциации, поэтому они отправляются в цель, которая представляет собой массив.

Чтобы помочь вам увидеть, как это происходит, добавьте это в строка 217 этого файла в вашей локальной копии association_proxy.rb:

Rails.logger.info "AssociationProxy forwarding call to `#{method.to_s}' method to \"#{@target}\":#{@target.class.to_s}" 

Если вы не знаете, где находится этот файл, команда gem, которая 'active_record / association / association_proxy' сообщит вам. Теперь, когда вы вызываете class в AssociationProxy, вы увидите сообщение журнала, в котором говорится, что он отправляет это целевому объекту, что должно прояснить, что происходит. Это все для Rails 2.3.2 и может измениться в других версиях.

t определены на прокси-сервере ассоциации, поэтому они отправляются в цель, которая представляет собой массив.

Чтобы помочь вам увидеть, как это происходит, добавьте это в строку 217 этого файла в вашей локальной копии association_proxy.rb:

Rails.logger.info "AssociationProxy forwarding call to `#{method.to_s}' method to \"#{@target}\":#{@target.class.to_s}" 

Если вы не знаете, где находится этот файл, команда gem, которая 'active_record / association / association_proxy' сообщит вам. Теперь, когда вы вызываете class в AssociationProxy, вы увидите сообщение журнала, в котором говорится, что он отправляет это целевому объекту, что должно прояснить, что происходит. Это все для Rails 2.3.2 и может измениться в других версиях.

t определены на прокси-сервере ассоциации, поэтому они отправляются в цель, которая представляет собой массив.

Чтобы помочь вам увидеть, как это происходит, добавьте это в строку 217 этого файла в вашей локальной копии association_proxy.rb:

Rails.logger.info "AssociationProxy forwarding call to `#{method.to_s}' method to \"#{@target}\":#{@target.class.to_s}" 

Если вы не знаете, где находится этот файл, команда gem, которая 'active_record / association / association_proxy' сообщит вам. Теперь, когда вы вызываете class в AssociationProxy, вы увидите сообщение журнала, в котором говорится, что он отправляет это целевому объекту, что должно прояснить, что происходит. Это все для Rails 2.3.2 и может измениться в других версиях.

Чтобы узнать, где находится этот файл, команда gem, о которой вам сообщит 'active_record / association / association_proxy' . Теперь, когда вы вызываете class в AssociationProxy, вы увидите сообщение журнала, в котором говорится, что он отправляет это целевому объекту, что должно прояснить, что происходит. Это все для Rails 2.3.2 и может измениться в других версиях.

Чтобы узнать, где находится этот файл, команда gem, о которой вам сообщит 'active_record / association / association_proxy' . Теперь, когда вы вызываете class в AssociationProxy, вы увидите сообщение журнала, в котором говорится, что он отправляет это целевому объекту, что должно прояснить, что происходит. Это все для Rails 2.3.2 и может измениться в других версиях.

21
ответ дан 30 November 2019 в 00:31
поделиться

Когда вы выполняете ассоциацию ( has_one , has_many и т. Д.), Она сообщает модели, чтобы она автоматически включала некоторые методы с помощью ActiveRecord. Однако, когда вы решили создать метод экземпляра, возвращающий ассоциацию самостоятельно, вы не сможете использовать эти методы.

Последовательность примерно такая

  1. setup статьи в Модель пользователя , то есть has_many: article
  2. ActiveRecord автоматически включает удобные методы в модель (например, size , empty? , find , все , первый и т. Д.)
  3. настроить пользователя в статье , т. Е. Сделать own_to:
0
ответ дан 30 November 2019 в 00:31
поделиться

Как уже упоминалось, ассоциации активных записей создают метрическую контрольную нагрузку вспомогательных методов. Конечно, вы можете написать свои собственные методы для получения всего. Но это не путь Rails.

The Rails Way - это кульминация двух девизов. СУХОЙ (Не повторяйся) и «Соглашение важнее конфигурации». По сути, называя вещи осмысленным образом, некоторые надежные методы, предоставляемые фреймворком, могут абстрагироваться от всего общего кода. Код, который вы помещаете в свой вопрос, является прекрасным примером того, что можно заменить одним вызовом метода.

Эти удобные методы действительно проявляют себя в более сложных ситуациях. Такие вещи, как модели объединения, условия, проверки и т. Д.

Чтобы ответить на ваш вопрос, когда вы делаете что-то вроде @ user.articles.find (: all,: condition => ["created_at>?", вторник]) , Rails подготавливает два SQL-запроса и затем объединяет их в один. где ваша версия просто возвращает список объектов. Именованные области действия делают то же самое, но обычно не выходят за границы модели.

Вы можете проверить это, проверив запросы SQL в development.log, когда вы вызываете эти вещи в консоли.

Итак, давайте немного поговорим о Named Scopes , потому что они дают отличный пример того, как rails обрабатывает SQL, и я думаю, что это более простой способ продемонстрировать, что происходит за кулисами, поскольку им не нужны модельные ассоциации, чтобы выставлять напоказ.

Именованные области могут использоваться для выполнения пользовательского поиска модели. Их можно связать вместе или даже вызвать через ассоциации. Вы можете легко создать собственные средства поиска, которые возвращают идентичные списки, но тогда вы столкнетесь с теми же проблемами, упомянутыми в вопросе.

class Article < ActiveRecord::Base
  belongs_to :user
  has_many :comments
  has_many :commentators, :through :comments, :class_name => "user"
  named_scope :edited_scope, :conditions => {:edited => true}
  named_scope :recent_scope, lambda do
    { :conditions => ["updated_at > ? ", DateTime.now - 7.days]}

  def self.edited_method
    self.find(:all, :conditions => {:edited => true})
  end

  def self.recent_method
    self.find(:all, :conditions => ["updated_at > ?", DateTime.now - 7 days])
  end
end

Article.edited_scope
=>     # Array of articles that have been flagged as edited. 1 SQL query.
Article.edited_method
=>     # Array of Articles that have been flagged as edited. 1 SQL query.
Array.edited_scope == Array.edited_method
=> true     # return identical lists.

Article.recent_scope
=>     # Array of articles that have been updated in the past 7 days.
   1 SQL query.
Article.recent_method
=>     # Array of Articles that have been updated in the past 7 days.
   1 SQL query.
Array.recent_scope == Array.recent_method
=> true     # return identical lists.

Здесь все меняется:

Article.edited_scope.recent_scope
=>     # Array of articles that have both been edited and updated 
    in the past 7 days. 1 SQL query.
Article.edited_method.recent_method 
=> # no method error recent_scope on Array

# Can't even mix and match.
Article.edited_scope.recent_method
=>     # no method error
Article.recent_method.edited_scope
=>     # no method error

# works even across associations.
@user.articles.edited.comments
=>     # Array of comments belonging to Articles that are flagged as 
  edited and belong to @user. 1 SQL query. 

По сути, каждая именованная область создает фрагмент SQL. Rails будет умело объединяться со всеми остальными фрагментами SQL в цепочке для создания единого запроса, возвращающего именно то, что вы хотите. Методы, добавленные методами ассоциации, работают одинаково. Вот почему они легко интегрируются с named_scopes.

Причина, по которой сочетание и сопоставление не работает, та же, что и метод of_sector, определенный в вопросе, не работает. edited_methods возвращает массив, в котором edited_scope (а также find и все другие вспомогательные методы AR, вызываемые как часть цепочки) передают свой фрагмент SQL следующему элементу в цепочке. Если это' s последний в цепочке, который выполняет запрос. Точно так же это тоже не сработает.

@edited = Article.edited_scope
@edited.recent_scope

Вы пробовали использовать этот код. Вот правильный способ сделать это:

class User < ActiveRecord::Base
   has_many :articles do
     def of_sector(sector_id)
       find(:all, :conditions => {:sector_id => sector_id})
     end
   end
end

Для достижения этой функциональности вам нужно сделать следующее:

class Articles < ActiveRecord::Base
  belongs_to :user
  named_scope :of_sector, lambda do |*sectors|
    { :conditions => {:sector_id => sectors} }
  end
end

class User < ActiveRecord::Base
  has_many :articles
end

Затем вы можете сделать что-то вроде этого:

@user.articles.of_sector(4) 
=>    # articles belonging to @user and sector of 4
@user.articles.of_sector(5,6) 
=>    # articles belonging to @user and either sector 4 or 5
@user.articles.of_sector([1,2,3,]) 
=>    # articles belonging to @user and either sector 1,2, or 3
9
ответ дан 30 November 2019 в 00:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: