0
votes

In my case I have a model Product has_one Location

I use a geocoder gem to search location near a distance.

The request Location.near([0, 0], 100) is look like this:

SELECT locations.*, 6371.0 * 2 * ASIN(SQRT(POWER(SIN((0 - locations.latitude) * PI() / 180 / 2), 2) + COS(0 * PI() / 180) * COS(locations.latitude * PI() / 180) * POWER(SIN((1 - locations.longitude) * PI() / 180 / 2), 2) )) AS distance, CAST(DEGREES(ATAN2( RADIANS(longitude - 1), RADIANS(latitude - 0))) + 360 AS decimal) % 360 AS bearing FROM \"locations\" WHERE (6371.0 * 2 * ASIN(SQRT(POWER(SIN((0 - locations.latitude) * PI() / 180 / 2), 2) + COS(0 * PI() / 180) * COS(locations.latitude * PI() / 180) * POWER(SIN((1 - locations.longitude) * PI() / 180 / 2), 2) )) <= 20) ORDER BY distance

I want to do something like this:

Product.where(...).joins(:location).dosomething

How can I do it?

2

2 Answers

0
votes

Location#near is a named scope? If so you can merge it with your Product scope using the & operator. I think this should work:

class Product
  scope :near, lambda { |coord, dist| joins(:location) & Location.near(coord, dist) }

  ...
end

Then you can just use it like so:

Product.near([0, 0], 100)
0
votes

Another possibility, since merging the scopes doesn't seem to work:

class Product
  scope :near, lambda { |coord, dist| where(:id => Location.near(coord, dist).all.map(&:locationable_id) }

  ...
end

And usage like in the other answer:

Product.near([0, 0], 100)