Forum: Ruby on Rails 5-second code syntax question

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
460ead051b49c0b2a8e45e46252d4bda?d=identicon&s=25 Tom Ha (tom)
on 2009-02-05 17:22
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
8d38199a01d2243e313c48456c6ddff9?d=identicon&s=25 Daly (Guest)
on 2009-02-05 17:30
(Received via mailing list)
Tom, where is it that you want to replace low with params[:id]?
460ead051b49c0b2a8e45e46252d4bda?d=identicon&s=25 Tom Ha (tom)
on 2009-02-05 17:38
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!
Ed437e52d8d6720308720e7e678f3e6d?d=identicon&s=25 Patrick Doyle (Guest)
on 2009-02-05 18:03
(Received via mailing list)
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 :-)

--wpd
460ead051b49c0b2a8e45e46252d4bda?d=identicon&s=25 Tom Ha (tom)
on 2009-02-05 18:11
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!
8217faf2bfdfa7daf10135d41ddd421e?d=identicon&s=25 Jeff Cohen (jeff)
on 2009-02-05 18:23
(Received via mailing list)
On Feb 5, 11:11 am, Tom Ha <rails-mailing-l...@andreas-s.net> 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
8d38199a01d2243e313c48456c6ddff9?d=identicon&s=25 Daly (Guest)
on 2009-02-05 18:24
(Received via mailing list)
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]}")
96146b7a23174e2e024c06a49f845bb8?d=identicon&s=25 Jeffrey L. Taylor (Guest)
on 2009-02-05 18:46
(Received via mailing list)
Responses interwoven below.

Quoting Tom Ha <rails-mailing-list@andreas-s.net>:
>   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
This topic is locked and can not be replied to.