1

I have an object with a bunch of attributes that represent searchable model attributes, and I would like to dynamically create an sql query using only the attributes that are set. I created the method below, but I believe it is susceptible to sql injection attacks. I did some research and read over the rails active record query interface guide, but it seems like the where condition always needs a statically defined string as the first parameter. I also tried to find a way to sanitize the sql string produced by my method, but it doesn't seem like there is a good way to do that either.

How can I do this better? Should I use a where condition or just somehow sanitize this sql string? Thanks.

def query_string
  to_return = ""

  self.instance_values.symbolize_keys.each do |attr_name, attr_value|
    if defined?(attr_value) and !attr_value.blank?
      to_return << "#{attr_name} LIKE '%#{attr_value}%' and "
    end
  end
  to_return.chomp(" and ")
end

1 Answer 1

2

Your approach is a little off as you're trying to solve the wrong problem. You're trying to build a string to hand to ActiveRecord so that it can build a query when you should simply be trying to build a query.

When you say something like:

Model.where('a and b')

that's the same as saying:

Model.where('a').where('b')

and you can say:

Model.where('c like ?', pattern)

instead of:

Model.where("c like '#{pattern}'")

Combining those two ideas with your self.instance_values you could get something like:

def query
  self.instance_values.select { |_, v| v.present? }.inject(YourModel) do |q, (name, value)|
    q.where("#{name} like ?", "%#{value}%")
  end
end

or even:

def query
  empties      = ->(_, v) { v.blank? }
  add_to_query = ->(q, (n, v)) { q.where("#{n} like ?", "%#{v}%") }
  instance_values.reject(&empties)
                 .inject(YourModel, &add_to_query)
end

Those assume that you've properly whitelisted all your instance variables. If you haven't then you should.

Sign up to request clarification or add additional context in comments.

1 Comment

Wow I'm awestruck by your Ruby skills. The second example is mind blasting. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.