如何在 Rails 控制器中使用闭包?
How use closures in Rails controller?
class MyController < ApplicationController
def getuser
data = params[:data]
first.call
end
first = lambda { user = User.first.name + data }
end
但是在我看来我得到了
NameError undefined local variable or method `first' for
感谢您的帮助
创建 lambda 时收集 lambda 或 proc 的闭包。因此,lambda 的主体可以访问在创建 lambda 时定义和可见的所有局部变量。这不包括仅在调用 lambda 时定义的其他变量。
因此,您必须使用参数将 lambda 需要的任何数据(创建 lambda 时闭包中尚不可用的数据)传递给它。
最后,为了能够调用 lambda,您需要使其在您要使用它的范围内可用。这可能看起来像这样:
class MyController < ApplicationController
# define a local variable which will be available in the lambda's closure
scope = ENV['scope']
# Assign the lambda to a constant. That way, it can be resolved
# by every method in the current class
FIRST = lambda do |data|
# The scope variable is available here when the lambda is called
# since it is available in the closure from the lambda's creation.
#
# Since the data variable is not available during the lamda's
# creation, we need to get it from a parameter from the caller.
User.where(scope: scope).first.name + data
end
def getuser
data = params[:data]
FIRST.call(data)
end
end
话虽如此,一种更常见的方法是在对象上使用完整方法而不是传递 lambda:
class MyController < ApplicationController
def getuser
data = params[:data]
first(data)
end
private
def first(data)
User.first.name + data
end
end
这避免了对(大部分是隐式的且不是很明显的)闭包的内容进行推理,以支持可以访问当前对象的实例变量和方法的普通方法调用。
特别是如果您来自 Javascript(通常使用类似于 Ruby 的 lambda 的闭包传递匿名函数),您应该尝试适应 Ruby-way 并避免这种构造,支持具有显式方法的对象。
class MyController < ApplicationController
def getuser
data = params[:data]
first.call
end
first = lambda { user = User.first.name + data }
end
但是在我看来我得到了
NameError undefined local variable or method `first' for
感谢您的帮助
创建 lambda 时收集 lambda 或 proc 的闭包。因此,lambda 的主体可以访问在创建 lambda 时定义和可见的所有局部变量。这不包括仅在调用 lambda 时定义的其他变量。
因此,您必须使用参数将 lambda 需要的任何数据(创建 lambda 时闭包中尚不可用的数据)传递给它。
最后,为了能够调用 lambda,您需要使其在您要使用它的范围内可用。这可能看起来像这样:
class MyController < ApplicationController
# define a local variable which will be available in the lambda's closure
scope = ENV['scope']
# Assign the lambda to a constant. That way, it can be resolved
# by every method in the current class
FIRST = lambda do |data|
# The scope variable is available here when the lambda is called
# since it is available in the closure from the lambda's creation.
#
# Since the data variable is not available during the lamda's
# creation, we need to get it from a parameter from the caller.
User.where(scope: scope).first.name + data
end
def getuser
data = params[:data]
FIRST.call(data)
end
end
话虽如此,一种更常见的方法是在对象上使用完整方法而不是传递 lambda:
class MyController < ApplicationController
def getuser
data = params[:data]
first(data)
end
private
def first(data)
User.first.name + data
end
end
这避免了对(大部分是隐式的且不是很明显的)闭包的内容进行推理,以支持可以访问当前对象的实例变量和方法的普通方法调用。
特别是如果您来自 Javascript(通常使用类似于 Ruby 的 lambda 的闭包传递匿名函数),您应该尝试适应 Ruby-way 并避免这种构造,支持具有显式方法的对象。