Reputation: 5187
I would like to do orderby query with dynamic variable posted from client. Client shows data tables and I am going to do orderby when user click header of each column. So I post orderby variable to server api. but I am not sure how to set asc and desc with variable. The reason of this requirement is, I have to set orderby name also variable.
I post these two params orderby, orderdir
for example, orderby='name', orderdir='asc'
In this case how to modify this static sequel?
Artist.order(Sequel.desc(:name))
Thanks
Upvotes: 0
Views: 302
Reputation: 3005
Don't use what you receive in the params directly or you can have serious risks. Just analyze params in the controller.
order = case params[:orderby]
when "name" then "name"
when "age" then "age"
else "name"
end
# Wrong version as Jeremy said.
# order = order + " desc" if params[:orderdir] == 'desc'
order = Sequel.desc(order) if params[:orderdir] == 'desc'
Artist.order(order)
Upvotes: 0
Reputation: 12149
First, as Pablo said, allowing the user/attacker control over which column to order is a bad and possibly dangerous idea. To be safe, you should use a whitelist. The code Pablo gave doesn't work with Sequel, but this should:
ord = case params['orderby']
when 'age'
:age
else
:name
end
ord = Sequel.desc(ord) if params['orderdir'] == 'desc'
Artist.order(ord)
Upvotes: 1
Reputation: 346
There are 2 possible ways which I know of. You can use any one of them based on your requirement:
1) If you are ordering the records on the basis of the field of artist object itself then use this:
Artist.order("#{orderby + ' ' + orderdir}")
2) If you are ordering records on the basis of the field of associated records then use this: Let's take an example here Artist belongs to some category and we want to order artists on by name of category then
Artist.send("order_with_#{orderby + '_' + orderdir}")
Lets suppose if you wanted to order Artist on the basis of
orderby='category_name', orderdir='asc'
then This will call a class method 'order_with_category_name_asc'
So either you can create a scope
scope :order_with_category_name_asc, -> { includes(:category).order("categories.name") }
or can create a class method which also do the same
def self.order_with_category_name_asc
self.includes(:category).order("categories.name")
end
Please let me know if you need any other help.
Upvotes: 0