Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby on Rails Case/Switch. How to match against object?

I am working on a ruby on rails application. For a session controller, I want to use a case to check if a user's account is locked or banned. I am trying to use the object of a class as the case, and use when to check attributes.

For example,

user = Profile.find(1)
case user
when user.ban
  redirect_to()
when user.lock
  redirect_to()
else
  redirect_to()
end

The only problem is that doesn't work.

What does work is this:

case user.ban
when true
  redirect_to()
else
  redirect_to()
end

Any advice on how I can go about checking if a user object is banned or locked using a switch?

Thank you

like image 771
Brian Avatar asked Jul 03 '10 02:07

Brian


People also ask

Can you use || IN CASE statement Ruby?

You can't use “||” in case names.

Does Ruby have switch case?

Ruby Case StatementIn Ruby, we use 'case' instead of 'switch' and 'when' instead of 'case'.

What does .first mean in Ruby?

The first() is an inbuilt method in Ruby returns an array of first X elements. If X is not mentioned, it returns the first element only. Syntax: range1.first(X) Parameters: The function accepts X which is the number of elements from the beginning. Return Value: It returns an array of first X elements.

Does Ruby case fall through?

It does not fall through. Ruby just doesn't have the same behavior as Java for this type of statement.


4 Answers

Make a user.status method which returns a state of a user, then you can do this:

user = Profile.find(1)
case user.status
when "banned"
  redirect_to()
when "locked"
  redirect_to()
else
  redirect_to()
end
like image 100
Zepplock Avatar answered Oct 22 '22 23:10

Zepplock


I like @Salil's answer; however, if you really like case, you can do this:

case true
  when user.ban
    redirect_to()
  when user.lock
    redirect_to()
  else
    redirect_to()
end

UPDATE Jörg said this works too, and he's right! Give him some votes on his answer! (As will I)

case
  when user.ban
    redirect_to()
  when user.lock
    redirect_to()
  else
    redirect_to()
end

UPDATE 2012 This works now:

case user
  when lambda(&:ban)
    redirect_to()
  when lambda(&:lock)
    redirect_to()
  else
    redirect_to()
  end
end
like image 36
Amadan Avatar answered Oct 22 '22 22:10

Amadan


Just leave out the user:

user = Profile.find(1)
case
when user.ban
  redirect_to
when user.lock
  redirect_to
else
  redirect_to
end

In Ruby, there are two forms of the case expression. In the form above, it simply executes the first branch which evaluates to a truish value (i.e. anything except nil or false).

The other form

case foo
when bar
  baz
end

is equivalent to

if bar === foo
  baz
end
like image 33
Jörg W Mittag Avatar answered Oct 22 '22 23:10

Jörg W Mittag


Lol, I love Amadan's answer. And if you really want a case statement, you should probably be doing what Zepplock said (though might consider symbols in place of strings), but based on your use case, you want a more if-statement based solution, like Salil's.

Anyway, thought I'd throw in and have some fun too ^_^ Here is a solution that will work with what you said, it creates objects that respond to === (what case statements use), then they invoke the method of interest (lock or ban) and return it. You should probably put them into some sort of config or initializer, or otherwise store the results after the first invocation, in order to save performance (your app only needs to create these objects one time)

user = Class.new do
  def ban() true end
  def lock() true end
end.new

def banned?
  ban_checker = Object.new
  def ban_checker.===(user) user.ban end
  ban_checker
end

def locked?
  lock_checker = Object.new
  def lock_checker.===(user) user.lock end
  lock_checker
end

case user
when banned?
  puts 'banned'
when locked?
  puts 'locked'
else
  puts 'default'
end

Note: I'm not advocating this solution, because it is violates encapsulation. Banned should be defined and used on your user, but to make this work, it must be defined in the enclosing scope. I mostly bring this up for fun :)

like image 34
Joshua Cheek Avatar answered Oct 22 '22 22:10

Joshua Cheek