开发者

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,

开发者_如何学C
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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜