ruby-on-railsruby-on-rails-4activerecordrails-activerecordfind-by-sql

Converting find_by_sql syntax to proper Active Record AREL syntax in Rails 4


Given a System model with three-dimensional coordinates x, y, and z, I have written the following instance method to give me all of the other Systems within a set range of the specific System in question. Here's the code:

def systems_within(range = '15')
  System.find_by_sql(["SELECT * FROM systems WHERE Sqrt(Pow((:x - systems.x), 2) + Pow((:y - systems.y), 2) + Pow((:z - systems.z), 2)) <= :range AND id!= :current_id", {x: x, y: y, z: z, range: range, current_id: id}])
end

Is there an ActiveRecord way of doing this?


Solution

  • Since you need access to the current instance you'll need to keep the instance method, but you could break it up a little bit by moving parts into scopes (I'm guessing that's what you meant by ActiveRecord).

    Something like this might work. This is untested code.

    scope :within_range, -> (x, y, z, range = '15') {
      where("Sqrt(Pow((:x - systems.x), 2) + Pow((:y - systems.y), 2) + Pow((:z - systems.z), 2)) <= :range", {x: x, y: y, z: z, range: range})
    }
    scope :excluding, -> (excluded_id) { where("id <> ?", excluded_id) }
    
    def systems_within(range = 15)
      System.excluding(id).within_range(x, y, z, range)
    end