Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the idiomatic way to write multi-line ActiveRelation queries?

I have many multi-line ActiveRelation query methods in our app, and I'm unsure about the most idiomatic way to write these methods. Take a look at this example:

def postal_code_ids_within(miles)
  nearby_postal_codes = PostalCode.where("latitude > :min_lat and latitude < :max_lat",
    min_lat: (latitude - (miles.to_f / MILES_PER_DEGREE_LATITUDE.to_f / 2.to_f)),
    max_lat: (latitude + (miles.to_f / MILES_PER_DEGREE_LATITUDE.to_f / 2.to_f)))
  nearby_postal_codes = nearby_postal_codes.where("longitude > :min_lon and longitude < :max_lon",
    min_lon: (longitude - (miles.to_f / MILES_PER_DEGREE_LONGITUDE.to_f / 2.to_f)),
    max_lon: (longitude + (miles.to_f / MILES_PER_DEGREE_LONGITUDE.to_f / 2.to_f)))
  nearby_postal_codes.pluck(:id)
end

It feels a bit off to me. A block from which an ActiveRelation object is returned seems idiomatic, but I haven't seen that approach around.

What is standard?

like image 583
barelyknown Avatar asked Aug 20 '12 15:08

barelyknown


1 Answers

Building on Brian's suggestion, this is much more legible and works well.

scope :near, lambda { |postal_code, miles|
  degree_offset = miles / MILES_PER_DEGREE / 2
  where("latitude > :min_lat and latitude < :max_lat and longitude > :min_lon and longitude < :max_lon",
    min_lat: postal_code.latitude - degree_offset,
    max_lat: postal_code.latitude + degree_offset,
    min_lon: postal_code.longitude - degree_offset,
    max_lon: postal_code.longitude + degree_offset)
}

def postal_code_ids_within(miles)
  self.class.near(self, miles).pluck(:id)
end
like image 90
barelyknown Avatar answered Nov 14 '22 23:11

barelyknown