I know how to convert the following into using strictly Arel methods, instead of mixed sql/string, but I dont' know how to merge the resulting arel object into an ActiveRecord::Relation so I can chain more AR::Relation methods on it.
I got the following very helpful answer to my previous question:
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))
I tried to do something like this:
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
But I end up with an arel object and I don't know how to merge it with the following ActiveRecord::Relation:
Person.joins(:address).merge(Address.anywhere(query_term))
(not to mention the inject is not very elegant either - how do I improve that?)
ActiveRecord::Relation.where accepts an ARel predicate, so in this case you can just pass your final predicate directly to 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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.