Как объединить объект arel в цепочку ActiveRecord::Relation?

Я знаю, как преобразовать следующее в использование строго методов Arel вместо смешанных sql / string, но я не знаю, как объединить получившийся объект arel в ActiveRecord:: Relation, чтобы я мог связать с ним несколько методов AR:: Relation,

Я получил следующий очень полезный ответ на мой предыдущий вопрос:

class Address < ActiveRecord::Base
  scope :anywhere, lambda{|search|
    attrs = [:line1, :line2, :city, :state, :zip]
    where(attrs.map{|attr| 
      "addresses.#{attr} LIKE :search"
    }.join(' OR '), search: "#{search}%").order(*attrs) 
  }
end

Person.joins(:address).merge(Address.anywhere(query_term))

Я пытался сделать что-то вроде этого:

class Address < ActiveRecord::Base
  scope :anywhere, lambda{|search|
    addr_arel = Address.arel_table
    attrs = [:line1, :line2, :city, :state, :zip]
    attrs.inject {|attr| 
      q = addr_arel[attr].match("%#{search}%") unless q
      q = q.or(addr_arel[attr].match("%#{search}%")
    }
  }
end

Но я получаю объект arel и не знаю, как объединить его со следующим ActiveRecord:: Relation:

Person.joins (: адрес).merge(Address.anywhere(QUERY_TERM))

(не говоря уже о том, что инъекция тоже не очень элегантна - как мне это улучшить?)

1 ответ

Решение

ActiveRecord::Relation.where принимает предикат ARel, поэтому в этом случае вы можете просто передать свой последний предикат непосредственно в Address.where.

class Address < ActiveRecord::Base
  scope :anywhere, -> search {
    addr_arel = Address.arel_table
    attrs = [:line1, :line2, :city, :state, :zip]

    where attrs
      .map {|attr| addr_arel[attr].matches("%#{search}%")}
      .inject(:or)
  }
end
Другие вопросы по тегам