5-second code syntax question

Hi there,

I have a n00b question regarding the correct code syntax:

The aim is to have code that looks like this...

Tom, where is it that you want to replace low with params[:id]?

Be careful here, depending on your user base of course.

What will you do if {params[:id]} (I know, incorrect syntax), evaluates to “delete!” or something else.

If you have a completely trustworthy user base (such as only you, or only your colleagues, whom you should trust implicitly, otherwise, why would you want to work with them), then once you figure out the right syntax (which probably involves the use of #send, or something like that), you should be fine.

If you are exposing this to the wild world wide web (WWWW), then I would recommend against this.

You would probably be better off writing a helper function that mapped params[:id] into one of the acceptable values. Perhaps something like:

def better_form_of_low(user, id) case id when :low user.low

when :high user.high end

and call that with better_form_of_low(@user, params[:id])

just my $.02 from my paranoid mind :slight_smile:

–wpd

Thanks. In this case, the "params[:id]" value is actually a system-generated one - so there's no user input involved and therefore it should be secure.

Can you tell my how to get the syntax correct in the above example?

("params[:id]" could of course be replaced by any variable, such as "@level")

Thanks!

Thanks. In this case, the "params[:id]" value is actually a system-generated one - so there's no user input involved and therefore it should be secure.

Can you tell my how to get the syntax correct in the above example?

("params[:id]" could of course be replaced by any variable, such as "@level")

Ruby is great for calling methods that you don't know the name of ahead of time. Every object has a "send" method you can call to dynamically call methods:

method_name = params[:id] # or whatever your case may be current_value = @user.send(method_name) # call the method

Then you can do whatever you want with that value.

Does this help?

Jeff

purpleworkshops.com switchingtorails.com

Patrick is 100% right. And he's not even being paranoid, it is almost guaranteed that someone will try this.

This is how I would do it, and as Patrick suggests, put it in helper:

if (%w(low medium high).include? params[:id]   instance_variable_set("@#{params[:id]}", user.send(params[:id])) else   # somebody is being really naughty, blow up their computer end

You can then get the instance variable by invoking instance_variable_get("@#{params[:id]}")

Responses interwoven below.

Quoting Tom Ha <rails-mailing-list@andreas-s.net>:

Well, basically *everywhere* where it says "low" in the below code example:

The "resulting" code...

  if @user.low == true     @low = false   elsif @user.low == false     @low = true   end

  [...]

Breaking your question into pieces.

case @user.low when true   @low = false when false   @low = true end

This is exactly equivalent to your code above. If all you care about is the falseness (nil or false) or trueness (anything else), it can be simplified to:

@low = !@user.low

...is supposed to be "generated" by something like this... (which is NOT yet correct syntax)

==========================   if @user.{params[:id]} == true     @{params[:id]} = false   elsif @user.{params[:id]} == false     @{params[:id]} = true   end

This is harder to handle, your syntax is not valid Ruby, so I have to make some assumptions what you mean. Again breaking into pieces:

@user.{params[:id]} isn't valid Ruby.

If @user is a hash, i.e., it was set with something like:

@user = {1 => 2, 3 => 4}

Then @user[params[:id]] is the proper syntax.

The same is true if @user is derived from ActiveRecord. You will get the attributes of @user, not the instance variables. Attributes are stored in the database, instance variables usually aren't (except of course for the values in the @attributes hash).

If both @user and the current object instance are ActiveRecords, and both are only true or false and all values of params[:id] are attribute names:

self[params[:id]] = !@user[params[:id]]

If all values of params[:id] are methods, i.e. explicit via "def abc() ... end" or implicit (i.e. accessors, e.g. attr_accessor 'abc') then the previous example becomes:

self.send(params[:id] + '=', !@user.send(params[:id]])

For most any combination of types, the following is correct:

case @user.send(params[:id]) when true   self.send(params[:id] + '=', false) when false   self.send(params[:id] + '=', true) end

If "@{params[:id]}" is instance variables without accessors, i.e. private, someone else will have to answer your question.

HTH,   Jeffrey