Nomura Nori
Nomura Nori

Reputation: 5187

How to set asc and desc with variable in sequel postgresql adapter in ruby?

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

Answers (3)

Pablo
Pablo

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

Jeremy Evans
Jeremy Evans

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

Pradeep Agrawal
Pradeep Agrawal

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

Related Questions