Instantly share code, notes, and snippets.

Embed
What would you like to do?
Rails - Sanitize Ordering Params
class ExampleController
include OrderingHelpers
def index
@clients = Clients.order(sanitized_ordering).where(user_id: current_user.id)
end
end
module OrderingHelpers
extend ActiveSupport::Concern
def sanitized_ordering
"#{sanitize_column(params[:order_by])} #{sanitize_column_direction(params[:sort_direction])}"
end
private
def sanitize_column(column)
resource.column_names.include?(column) ? column : "created_at"
end
def sanitize_column_direction(direction)
direction = direction.upcase
['DESC', 'ASC'].include?(direction) ? direction : "DESC"
end
def resource
controller_name.camelize.singularize.safe_constantize
end
end
@dmexs

This comment has been minimized.

dmexs commented Oct 4, 2015

This pattern doesn't seem to work for joined queries. sanitize_column verifies column names that exist only for the current controller.

I forked it and made it switchable: https://gist.github.com/dmexs/ebcfe76d9c282bb205ee

@joshuapinter

This comment has been minimized.

joshuapinter commented Apr 9, 2018

FYI, I ended up extending ActiveRecord::Relation in order to create a sanitized_order() method that accepts the column and direction to sort on. It can be improved to work with other class column names, etc. but it does the job for now:

config/initializers/sanitized_order.rb

class ActiveRecord::Relation

  # This will sanitize the column and direction of the order. Should always be used when taking these params from GET.
  #
  def sanitized_order( column, direction = nil )
    direction ||= "ASC"

    raise "Column value of #{column} not permitted."       unless self.klass.column_names.include?( column.to_s ) 
    raise "Direction value of #{direction} not permitted." unless [ "ASC", "DESC" ].include?( direction.upcase ) 

    self.order( "#{column} #{direction}" )
  end

end

And then you simply call it in the query chain like:

Client.sanitized_order( params[:order_by], params[:sort_direction] ).where(user_id: current_user.id)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment