1

I have the following piece of code, where params[:sort] is a variable whose value is one of m's column.

eval "@movie = @movie.sort_by { |m| m.#{params[:sort]}}"

Basically I want to sort the array @movie according to the column specified. Is there any way to do this without eval?

2
  • 2
    I personally like to sort movies by the key "destroy". Commented Jul 4, 2012 at 14:05
  • also, the pattern var = f(var) is pretty dubious, why not create a new variable for the new value? Commented Jul 4, 2012 at 14:20

3 Answers 3

6
@movie = @movie.sort_by { |m| m.send(params[:sort])}

You need to sanitize params[:sort] to prevent calling destroy for example.

Sign up to request clarification or add additional context in comments.

1 Comment

For whitelisting the columns, check out railscasts.com/episodes/228-sortable-table-columns -- you are sorting the columns after getting them from the database, the railscast shows how to make the database do the sorting first.
1

As told before, you should use send and as you use params (which I assume is Rails), you should probably check if the method exists to avoid a NoMethodError exception and, even better, test against a white list to prevent some user to use it to get data they shouldn't have.

# Just for the example :
valid_sort_methods = Movie.new.attributes.keys - Movie.protected_attributes.to_a

if valid_sort_methods.include? params[:sort]
  @movie = @movie.sort_by { |m| m.send params[:sort] }
end

1 Comment

idea for an abstraction, Object#whitelist: "white".whitelist("black", "white") #=> "white", "blue".whitelist("black", "white") #=> nil.
0

You can use send to call the accessor method. Depending on where params[:sort] has come from and what sanitisation has been applied, this could still be dangerous. You wouldn't want params[:sort] to be destroy for example.

If you only intend to read attributes then the simplest thing is probably to call read_attribute, which is also aliased as [], for example

@movie = @movie.sort_by { |m| m[params[:sort]]}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.