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,
开发者_如何学Cuser = 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
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
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
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
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 :)
you can do as Zepplock said. But for given example following is the best way (just an example)
action_name = (user.ban)? "ban" : ( (user.lock)? "lock" : "default")
redirect_to(:action => action_name)
@Brian, the idea of a switch case is that you have a variable that accepts a dynamic value and checks it against a couple of constant set of values. In the piece of code you wrote, the case statements contains dynamic values like user.ban which depends on the variable itself which you are trying to check. The correct way to use a switch case is how @Zepplock demonstrated.
精彩评论