我继承了一些rails代码,用于检查用户是否在之前过滤器调用的方法中定义:
before_filter :get_user
def get_user
@user = User.find(params[:id])
if !@user
return false
end
end
现在,问题是这不起作用:)如果找不到用户,我们不从控制器返回,我们只是从get_user()
方法返回,然后继续执行{将show()
设置为update()
的{1}}或@user
方法。
我的简单解决方案是在nil
为零时向get_user()
添加重定向:
@user
现在,我的测试正在通过,世界上的一切似乎都是正确的。但是......我不明白发生了什么。有人可以解释一下为什么def get_user
@user = User.find(params[:id])
if !@user
redirect_back
return false
end
end
中的返回没有完全停止在控制器中执行但只会使我们脱离get_user()
并导致我们陷入最初调用的控制器方法中吗?
谢谢!
答案 0 :(得分:3)
http://guides.rubyonrails.org/action_controller_overview.html#filters
“该方法只是在闪存中存储错误消息,并在用户未登录时重定向到登录表单。如果”之前“过滤器呈现或重定向,则操作将不会运行。如果安排了其他过滤器要在该过滤器之后运行,它们也会被取消。“
非常自我解释,但性质是你不能在过滤器中停止执行。
答案 1 :(得分:1)
返回一个方法只返回并破坏该方法而没有别的。 Se代码如下。
def foo
return "foo"
return "bar"
end
puts my_method # this will puts "foo" and the second return will never be called.
但是,在ruby中,您仍然可以在使用ensure
返回后执行代码。
def bar
return "bar"
ensure
@bar = 'Hello world'
end
puts bar # returns and prints "bar"
puts @bar # prints "Hello world" because the ensure part was still executed
请记住,方法中最后执行的代码将被返回,因此您不必总是在值之前编写return
。如果你的方法中有一个确保部分,那么如果你还没有返回一些东西,那么之前执行的最后一个代码将被返回。
并且在过滤器之前不需要返回false。如果我记得版本3.1之前的右轨道确实在前一个过滤器返回一个假值时停止控制器。 Nil在ruby中仍然是假的,并且删除一些行,你可以像下面那样编写过滤器,因为如果没有找到用户,@user
在这个例子中将是nil。
def get_user
@user = User.find_by id: params[:id] # I use find_by to prevent exception, else we may return an 500 error which you may or may not want.
redirect_back unless @user
end
答案 2 :(得分:0)
我会用这种方式重写这段代码
def get_user
redirect_back if User.where(id: params[:id]).empty?
end
有两个原因。首先,如果您能以更简单的方式检查它,为什么会这样做。其次,如果找不到对象,find
会引发异常,所以这个检查完全没有意义!