【问题标题】:return from method used by before_filter从 before_filter 使用的方法返回
【发布时间】:2013-07-22 21:02:37
【问题描述】:

我继承了一些 Rails 代码,用于检查用户是否定义在由前过滤器调用的方法中:

before_filter :get_user

def get_user
  @user = User.find(params[:id])
  if !@user
    return false
  end
end

现在,问题是这不起作用 :) 如果找不到用户,我们不会从控制器返回,我们只是从 get_user() 方法返回,然后在 show() 中继续执行或将@user 设置为nilupdate() 方法。

如果@user 为nil,我的简单解决方案是添加到get_user() 的重定向:

def get_user
  @user = User.find(params[:id])
  if !@user
    redirect_back
    return false
  end
end

现在,我的测试通过了,世界似乎一切正常。但是......我不明白发生了什么。有人能解释一下为什么get_user() 中的返回并没有完全停止控制器中的执行,而是让我们脱离get_user() 并导致我们陷入最初调用的控制器方法?

谢谢!

【问题讨论】:

标签: ruby-on-rails control-flow


【解决方案1】:

http://guides.rubyonrails.org/action_controller_overview.html#filters

“该方法只是在闪存中存储一​​条错误消息,并在用户未登录时重定向到登录表单。如果“之前”过滤器呈现或重定向,则该操作将不会运行。如果安排了其他过滤器要在该过滤器之后运行,它们也会被取消。”

非常不言自明,但本质是您无法返回以在过滤器中停止执行。

【讨论】:

  • 感谢您的链接。我认为过滤器应该在返回时堆叠是有道理的,因此return 将继续进行下一个过滤器/方法。在 Web 框架中使用渲染或重定向来突破非常有意义。
  • 是的,并且“重定向到”另一个动作,有效地停止父动作的执行,而不仅仅是过滤器
【解决方案2】:

在方法中返回只是返回并破坏该方法,没有别的。下面是代码。

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。如果你的方法中有一个 ensure 部分,如果你还没有返回一些东西,那么之前最后执行的代码将被返回。

并且无需在之前的过滤器中返回 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

【讨论】:

    【解决方案3】:

    我会这样重写这段代码

    def get_user
      redirect_back if User.where(id: params[:id]).empty?
    end
    

    有两个原因。首先,如果您可以以更简单的方式检查它,为什么要这样做。其次,如果找不到对象,find 会引发异常,因此此检查毫无意义!

    【讨论】:

      猜你喜欢
      • 2021-12-14
      • 1970-01-01
      • 1970-01-01
      • 2021-07-09
      • 1970-01-01
      • 2014-09-05
      • 1970-01-01
      • 2012-09-20
      • 1970-01-01
      相关资源
      最近更新 更多