为什么Rails上的卷曲大括号回调?

时间:2015-07-20 20:11:49

标签: ruby-on-rails callback

我正在学习Ruby on Rails,因为我正在处理概念,我也正在处理语法,当你开始使用RoR时这有点奇怪。每个Michael Hartl的教程

  

当散列是函数调用中的最后一个参数时,大括号   是可选的

我理解这一点,但是当作者提到回调时,这行代码出现了:

category = []
columns = []

read = open('file1.txt', 'r')

for line in read:
    fields = line.split('|')
    columns.append(fields)
    category.append(int(fields[4]))
category = sorted(set(category))
print(category)

for line in columns:
    print(line)

out = open('fileout.txt', 'w')

out.write('column 1|column 2|column 6|column 7|')
for val in category:
    out.write('column3_{0}|'.format(val))
for val in category:
    out.write('column4_{0}|'.format(val))
out.write('\n')

for line in columns:
    out.write('{0}|{1}|{2}|{3}|'.format(line[0], line[1], line[5], line[6].rstrip()))
    for val in category:
        if int(line[4]) == val:
            out.write('{0}|'.format(line[2]))
        else:
            out.write(' |')
    for val in category:
        if int(line[4]) == val:
            out.write('{0}|'.format(line[3]))
        else:
            out.write(' |')                    
    out.write('\n')

我理解before_save是方法。有人可以为我打破这个论点,为什么你不能放弃大括号?

2 个答案:

答案 0 :(得分:4)

您的代码中没有哈希值。你正在看的是一个块,这是一种匿名函数。 Ruby有两种不同的块语法。这段代码:

before_save { self.email = email.downcase }

...相当于这段代码:

before_save do
  self.email = email.downcase
end

通常,花括号用于单行,do ... end用于多行。在任何一种情况下,你正在做的是定义一个"块"代码然后将其作为参数传递给before_save方法。这允许Rails将该代码块存储在变量中并稍后执行,或者将代码传递给其他方法。上述两个例子大致相当于:

my_block = proc do
  self.email = email.downcase
end

before_save(&my_block)

块参数很特殊。一个方法只能有一个块参数,它必须是最后一个参数。在最后一段代码中,我使用procProc.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文档中看到lambdas,它们看起来像这样:

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&#39;开发人员已经选择让scope将lambda作为常规参数 - 而不是它的块参数 - 我认为这主要是因为它不必是最后一个参数。

块,触发器和lambdas之间的区别超出了这个答案的范围,有时甚至是微妙的,但它具有很好的知识。我推荐这篇文章以获取更多信息:https://rubymonk.com/learning/books/4-ruby-primer-ascent/chapters/18-blocks/lessons/64-blocks-procs-lambdas

答案 1 :(得分:1)

你指的是作为参数传递的花括号是一个块 传递给回调的块通过instance_eval执行,因此其范围是记录本身。