Каков эквивалент опции has many 'conditions' в Rails 4?
может кто-нибудь сказать мне, каков эквивалентный способ сделать следующую строку в Rails 4?
has_many :friends, :through => :friendships, :conditions => "status = 'accepted'", :order => :first_name
я попробовал следующий:
has_many :friends, -> { where status: 'accepted' }, :through => :friendships , :order => :first_name
но я получаю следующую ошибку:
Invalid mix of scope block and deprecated finder options on ActiveRecord association: User.has_many :friends
5 ответов:
должен быть второй arg:
class Customer < ActiveRecord::Base has_many :orders, -> { where processed: true } end
http://edgeguides.rubyonrails.org/association_basics.html#scopes-for-has-many
ОТВЕТ НА ОБНОВЛЕНИЕ:
поместите заказ внутри блока:
has_many :friends, -> { where(friendship: {status: 'accepted'}).order('first_name DESC') }, :through => :friendships
в то время как другие ответы здесь технически правильны, они нарушают инкапсуляцию. Элемент пользователей модель не должна знать, что Дружба модель имеет столбец называется
status
, и что он может иметь определенное значение какaccepted
.если вы решите внести изменения, чтобы воспользоваться перечислениями в Rails 4, например, вам придется изменить оба пользователей и Дружба модели. Это может привести к ошибкам, которые поддерживают инкапсуляция позволяет избежать.
Я бы выставил область в Дружба модель:
scope :accepted, -> { where(status: :accepted) }
Я бы тогда использовал эту область в пользователей модель, скрывающая любые детали реализации от пользователей.
has_many :friendships, -> { Friendship.accepted } has_many :friends, through: :friendships # Or... has_many :friends, -> { Friendship.accepted }, through: :friendships
вы можете пойти дальше и переименовать область, чтобы
accepted_friendships
чтобы было понятнее.has_many :accepted_friendships, -> { Friendship.accepted } has_many :friends, through: :accepted_friendships
теперь вы успешно инкапсулировали детали реализации в своих соответствующих моделях. Должно ли что-нибудь изменить вас только имейте одно место, котор нужно изменить его, уменьшая обслуживание и увеличивая робастность.
версия Rails 3.2 ответа Мохамада будет следующей:
class Friend < ActiveRecord::Base has_many :friendships, :order => :first_name has_many :friends, :through => :friendships, :conditions => proc { Friendship.accepted.where_ast } has_many :pending_friends, :through => :friendships, class_name => Friend, :conditions => proc { Friendship.pending.where_ast } end class Friendship < ActiveRecord::Base scope :status, ->(status) { where(:status => status) } scope :accepted, -> { status('accepted') } scope :pending, -> { where(arel_table[:status].not_eq('accepted')) } end
Примечания:
where_ast
важно, поскольку он возвращает узлы AREL, необходимые для работы условия- внутри proc передано в
:conditions
,self
не всегда является экземпляром модели (например, когда ассоциация объединяется с другим запросом)- использование необработанного SQL в ваших областях и ассоциациях, скорее всего, вызовет проблемы при некоторые точки связаны с пространством имен имен таблиц... использовать АРЕЛ.