views:

358

answers:

1

In a Rails model I am trying to acheive a named_scope that filters on a start_date and end_date. This is easy. But I am going to have to do it on lots of different fields on many occasions.

Is this asking for trouble? If so why (SQL injection?) and is there another way to acheive this.

named_scope :between, lambda {|start_date, end_date, field|
  { :conditions => ["#{field} >= ? AND #{field} <= ?", start_date, end_date] }
}

EDIT: Solution Used

Using Eggdrop's line of thinking I went with:

@@valid_fields = %w(fields in here)

named_scope :between, lambda{ |start_date, end_date, field_name|
  field = (@@valid_fields.include?(field_name)) ? (field_name) : raise (ActiveRecord::StatementInvalid)
  {  :conditions => ["#{field} >= ? AND #{field} <= ?",  start_date, end_date]}
}

Now I can reuse my named_scope for fields I wish to filter on date range without rewriting essentially the same scope over and over and whitelist the field names to avoid any mucking about with my column names and tricky SQL injection should the code ever get exposed to user input in the future.

+3  A: 

Maybe you could write a method in your model to validate 'field':

If table x, then 'field' must be a particular existing date field in that table.

In other words you don't allow external input into 'field' directly - the external input has to map to known attributes and defined conditions specified in your validate method.

In general, though, this overall direction would not seem to be recommended.

eggdrop
I am currently looking at using a field whitelist and raising an exception if the field is not in this.
railsninja
Yes, I think we're talking about the same thing.
eggdrop
Cool, that's what someone else I spoke to suggested too. Seems like the best path right now. Thanks :)
railsninja