Есть ли способ фильтрации объединенных ассоциаций с использованием именованной области?

У меня есть следующие связанные модели

class Enrollment < ActiveRecord::Base
  has_many :addresses
end

class Address < ActiveRecord::Base
  belongs_to :address_type
end

В настоящее время я использую следующее (что я считаю уродливым), чтобы отфильтровать адреса регистрации определенного типа адреса.

class Enrollment < ActiveRecord::Base
  def local_address
    adds = []
    addresses.each do |add| 
      adds << add if add.address_type.name == 'Local'
    end
    adds.last
  end
end

Есть ли способ использовать именованную область действия, чтобы делать то же самое?


person JasonOng    schedule 27.07.2009    source источник


Ответы (2)


Общее решение:

class Address < ActiveRecord::Base
  belongs_to :address_type
  named_scope :local, { :conditions => { :address_type => { :name => "Local" }}}
end

Это позволяет сделать следующее:

Enrollment.find(12).addresses.local  # Association extended with .local method
Address.local.all                    # Class methods extended with .local method

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

person molf    schedule 27.07.2009
comment
Ваше решение дало следующую ошибку. Mysql::Error: Неизвестный столбец 'address_type.name' в 'предложении where': SELECT * FROM addresses WHERE (addresses.enrollment_id = 8) AND ((address_type.name = 'Local') AND (addresses.enrollment_id = 8)) ORDER BY address.id DESC LIMIT 1 Похоже, мы должны использовать операторы соединения. - person JasonOng; 28.07.2009

Со ссылкой на следующий пост stackoverflow мне удалось решить мой запрос с именованной областью

Rails named_scopes с соединениями

В основном мне нужно делать соединения в запросе

class Address < ActiveRecord::Base
  belongs_to :address_type
  named_scope :local, { 
    :joins => "INNER JOIN address_types ON address_types.id = addresses.address_type_id",
    :conditions => "address_types.name = 'Local'"
  }
end

Таким образом, я могу эффективно переписать метод «local_address» моего Enrollment на

clss Enrollment < ActiveRecord::Base
    def local_address
      addresses.local.last
    end
end
person JasonOng    schedule 28.07.2009