从before_filter使用的方法返回

时间:2013-07-22 21:02:37

标签: ruby-on-rails control-flow

我继承了一些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()并导致我们陷入最初调用的控制器方法中吗?

谢谢!

3 个答案:

答案 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会引发异常,所以这个检查完全没有意义!