我知道如何将以下转换为使用严格的Arel方法,而不是混合sql/字符串,但我不知道如何将产生的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
但我最终与一个雷尔对象,我不知道如何合并它与以下ActiveRecord::Relation:
Person.joins(地址).merge (Address.anywhere (query_term))
(更不用说注入也不是很优雅-我如何改进它?)
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