为什么在 Rails 回调上使用大括号?
Why Curly Braces on Rails Callback?
我在 Rails 上学习 Ruby 并且在处理概念时我也在处理语法,这在您开始 RoR 时有点奇怪。根据 Michael Hartl 的教程
When hashes are the last argument in a function call, the curly braces
are optional
我明白了,但是作者在提到回调时,出现了这行代码:
before_save { self.email = email.downcase }
我理解before_save是方法。谁能帮我解释一下这个论点,为什么你不能把花括号去掉?
您所指的作为参数传递的花括号是一个块。
传递给回调的块通过 instance_eval 执行,因此它的范围是记录本身。
您的代码中没有哈希。你看到的是一个块,它是一种匿名函数。 Ruby 有两种不同的块语法。此代码:
before_save { self.email = email.downcase }
...等同于此代码:
before_save do
self.email = email.downcase
end
一般来说,大括号用于单行,do ... end
用于多行。无论哪种情况,您所做的都是定义 "block" 代码,然后将其作为参数传递给 before_save
方法。这允许 Rails 将该代码块存储在变量中并稍后执行,或者将代码传递给其他方法。以上两个例子在很大程度上等同于:
my_block = proc do
self.email = email.downcase
end
before_save(&my_block)
块参数很特殊。一个方法只能有一个块参数,而且它必须是最后一个参数。在最后一段代码中,我使用 proc
(Proc.new
的快捷方式)实际上将块保存到一个变量,然后将该变量作为一个变量传递给 before_save
争论。 &
告诉 Ruby 它应该将该 Proc 视为 before_save
.
的块参数
不过,有些语法问题会随着块出现。例如,这是有效的:
[ "two", "three" ].reduce "one" do |memo, item|
memo << item
end
# => "onetwothree"
但这不是:
[ "two", "three" ].reduce "one" {|memo, item| memo << item }
# => SyntaxError: unexpected '{', expecting end-of-input
当你使用大括号语法并有参数时(如上面的"one"
),你必须使用括号:
[ "two", "three" ].reduce("one") {|memo, item| memo << item }
# => "onetwothree"
除了块和 Proc 之外,Ruby 还有一种特殊的 Proc,称为 lambda。您会在某些 Rails 文档中看到 lambda,它们看起来像这样:
scope :published, -> { where(published: true) }
这是一个快捷方式:
scope :published, lambda { where(published: true) }
# ...or...
scope :published, lambda do
where(published: true)
end
...这些都等同于:
my_lambda = ->{ where(published: true) }
scope :published, my_lambda
请注意,第二行的 my_lambda
之前没有 &
。那是因为 Rails' 开发人员选择让 scope
将 lambda 作为常规参数——而不是它的块参数——我认为这主要是因为它不必是最后一个参数。
块、过程和 lambda 之间的区别超出了本答案的范围,有时甚至很微妙,但掌握这些知识是很好的知识。我推荐这篇文章以获取更多信息:https://rubymonk.com/learning/books/4-ruby-primer-ascent/chapters/18-blocks/lessons/64-blocks-procs-lambdas
我在 Rails 上学习 Ruby 并且在处理概念时我也在处理语法,这在您开始 RoR 时有点奇怪。根据 Michael Hartl 的教程
When hashes are the last argument in a function call, the curly braces are optional
我明白了,但是作者在提到回调时,出现了这行代码:
before_save { self.email = email.downcase }
我理解before_save是方法。谁能帮我解释一下这个论点,为什么你不能把花括号去掉?
您所指的作为参数传递的花括号是一个块。
传递给回调的块通过 instance_eval 执行,因此它的范围是记录本身。
您的代码中没有哈希。你看到的是一个块,它是一种匿名函数。 Ruby 有两种不同的块语法。此代码:
before_save { self.email = email.downcase }
...等同于此代码:
before_save do
self.email = email.downcase
end
一般来说,大括号用于单行,do ... end
用于多行。无论哪种情况,您所做的都是定义 "block" 代码,然后将其作为参数传递给 before_save
方法。这允许 Rails 将该代码块存储在变量中并稍后执行,或者将代码传递给其他方法。以上两个例子在很大程度上等同于:
my_block = proc do
self.email = email.downcase
end
before_save(&my_block)
块参数很特殊。一个方法只能有一个块参数,而且它必须是最后一个参数。在最后一段代码中,我使用 proc
(Proc.new
的快捷方式)实际上将块保存到一个变量,然后将该变量作为一个变量传递给 before_save
争论。 &
告诉 Ruby 它应该将该 Proc 视为 before_save
.
不过,有些语法问题会随着块出现。例如,这是有效的:
[ "two", "three" ].reduce "one" do |memo, item|
memo << item
end
# => "onetwothree"
但这不是:
[ "two", "three" ].reduce "one" {|memo, item| memo << item }
# => SyntaxError: unexpected '{', expecting end-of-input
当你使用大括号语法并有参数时(如上面的"one"
),你必须使用括号:
[ "two", "three" ].reduce("one") {|memo, item| memo << item }
# => "onetwothree"
除了块和 Proc 之外,Ruby 还有一种特殊的 Proc,称为 lambda。您会在某些 Rails 文档中看到 lambda,它们看起来像这样:
scope :published, -> { where(published: true) }
这是一个快捷方式:
scope :published, lambda { where(published: true) }
# ...or...
scope :published, lambda do
where(published: true)
end
...这些都等同于:
my_lambda = ->{ where(published: true) }
scope :published, my_lambda
请注意,第二行的 my_lambda
之前没有 &
。那是因为 Rails' 开发人员选择让 scope
将 lambda 作为常规参数——而不是它的块参数——我认为这主要是因为它不必是最后一个参数。
块、过程和 lambda 之间的区别超出了本答案的范围,有时甚至很微妙,但掌握这些知识是很好的知识。我推荐这篇文章以获取更多信息:https://rubymonk.com/learning/books/4-ruby-primer-ascent/chapters/18-blocks/lessons/64-blocks-procs-lambdas