Last active
October 29, 2020 18:40
-
-
Save TheKidCoder/9653073 to your computer and use it in GitHub Desktop.
Rails - Sanitize Ordering Params
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ExampleController | |
include OrderingHelpers | |
def index | |
@clients = Clients.order(sanitized_ordering).where(user_id: current_user.id) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
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
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