Ruby on Rails 案例/开关。如何与对象匹配?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3170037/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Ruby on Rails Case/Switch. How to match against object?
提问by Brian
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.
我正在开发 ruby on rails 应用程序。对于会话控制器,我想使用一个案例来检查用户的帐户是否被锁定或禁止。我试图使用类的对象作为案例,并使用 when 来检查属性。
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
谢谢
回答by Zepplock
Make a user.statusmethod which returns a state of a user, then you can do this:
创建一个返回用户状态的user.status方法,然后你可以这样做:
user = Profile.find(1)
case user.status
when "banned"
redirect_to()
when "locked"
redirect_to()
else
redirect_to()
end
回答by Amadan
I like @Salil's answer; however, if you really like case, you can do this:
我喜欢@Salil 的回答;但是,如果你真的喜欢case,你可以这样做:
case true
when user.ban
redirect_to()
when user.lock
redirect_to()
else
redirect_to()
end
UPDATEJ?rg said this works too, and he's right! Give him some votes on his answer! (As will I)
更新J?rg 说这也有效,他是对的!给他一些投票给他的答案!(我也会)
case
when user.ban
redirect_to()
when user.lock
redirect_to()
else
redirect_to()
end
UPDATE 2012This works now:
2012 年更新这现在有效:
case user
when lambda(&:ban)
redirect_to()
when lambda(&:lock)
redirect_to()
else
redirect_to()
end
end
回答by J?rg W Mittag
Just leave out the user:
只需省略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 caseexpression. In the form above, it simply executes the first branch which evaluates to a truish value (i.e. anything except nilor false).
在 Ruby 中,case表达式有两种形式。在上面的形式中,它只是执行第一个分支,该分支的计算结果为真值(即除了nilor之外的任何内容false)。
The other form
另一种形式
case foo
when bar
baz
end
is equivalent to
相当于
if bar === foo
baz
end
回答by Joshua Cheek
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.
大声笑,我喜欢阿马丹的回答。如果你真的想要一个 case 语句,你可能应该按照 Zepplock 所说的做(尽管可能会考虑用符号代替字符串),但是根据你的用例,你需要一个更基于 if 语句的解决方案,比如 Salil 的。
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)
无论如何,我想我也会投入并玩得开心^_^ 这是一个可以处理您所说的内容的解决方案,它创建响应 ===(使用哪种 case 语句)的对象,然后它们调用利息(锁定或禁止)并归还。您可能应该将它们放入某种配置或初始化程序中,或者在第一次调用后以其他方式存储结果,以节省性能(您的应用程序只需要创建这些对象一次)
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 :)
注意:我不提倡这种解决方案,因为它违反了封装。Banned 应该在您的用户上定义和使用,但要使其工作,它必须在封闭范围内定义。我主要是为了好玩而提出这个:)
回答by Suman Mukherjee
@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.
@Brian,切换案例的想法是您有一个接受动态值的变量,并根据一组常量值对其进行检查。在您编写的这段代码中,case 语句包含动态值,例如 user.ban,这取决于您尝试检查的变量本身。使用 switch case 的正确方法是 @Zepplock 演示的方式。
回答by Salil
you can do as Zepplock said. But for given example following is the best way (just an example)
你可以按照 Zepplock 说的去做。但是对于给定的示例,以下是最好的方法(只是一个示例)
action_name = (user.ban)? "ban" : ( (user.lock)? "lock" : "default")
redirect_to(:action => action_name)

