5-second code syntax question


#1

Hi there,

I have a n00b question regarding the correct code syntax:

The aim is to have code that looks like this…

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

[…]

…where every “low” should be replaced by “params[:id]” (in order for
“low” to be able to take other values, such as “medium” or “high”).

How do I have to write the syntax correctly in my controller?

Thank you very much for your help!
Tom


#2

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


#3

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

[…]

…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

[…]

Thanks for your help!


#4

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


#5

On Feb 5, 11:11 am, Tom Ha removed_email_address@domain.invalid wrote:

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


#6

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]}")


#7

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!


#8

Responses interwoven below.

Quoting Tom Ha removed_email_address@domain.invalid:

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