Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 什么时候块比函数更有用(ruby)?_Ruby On Rails_Ruby_Block_Proc - Fatal编程技术网

Ruby on rails 什么时候块比函数更有用(ruby)?

Ruby on rails 什么时候块比函数更有用(ruby)?,ruby-on-rails,ruby,block,proc,Ruby On Rails,Ruby,Block,Proc,我有两个例子给出了相同的结果 带块: def self.do_something(object_id) self.with_params(object_id) do |params| some_stuff(params) end end def self.with_params(object_id, &block) find_object_by_id calculate_params_hash block.call(params_hash) end 方法:

我有两个例子给出了相同的结果

带块:

def self.do_something(object_id)
  self.with_params(object_id) do |params|
    some_stuff(params)
  end
end

def self.with_params(object_id, &block)
  find_object_by_id
  calculate_params_hash
  block.call(params_hash)
end
方法:

def self.do_something(object_id)
  some_stuff(self.get_params(object_id))
end

def self.get_params(object_id)
  find_object_by_id
  calculate_params_hash
  params_hash
end

第二种解决方案似乎更简单,但我在应用程序代码中发现了第一种解决方案的一些用法。我的问题是:在哪种情况下推荐第一种?每种方法的优点和缺点是什么?

当人们想要在另一段代码中运行一段代码时,通常使用块。示例:

DB.with_shard_for_user(user_id) do |db|
  # perform operations on a user's shard

end # shard is reverted back to original value

File.new(filename) do |file|
  # work with file
end # file is closed automatically

User.transaction do
  # run some operations as a single transaction
end
这些块在词法上下文上是封闭的(它们从声明块的位置捕获变量,并将它们带到调用块的位置)

接受块的方法的示意图结构

def transaction
  open_transaction # pre- part

  yield if block_given? # run provided code

  commit_transaction # post- part
rescue
  rollback_transaction # handle problems
end
在第一个示例中,使用块可能是不合理的(IMHO)。太复杂了,没有明显的原因。

当您使用_params()调用时,您不仅在发送数据,还提供了一些要运行的代码。查看是否将不同的块发送到with_params()调用:

在其他地方:

...
self.with_params(object_id) do |params|
  even_more_stuff(params)
end
...

如果块是相同的,或者只是从一个地方调用了(或)PARAMS.(),那么你可以考虑删除块。< /P> 总而言之:如果您想将不同的代码位(块)和数据传递到方法中,请使用块:嘿,使用参数,获取此数据(对象id),顺便说一下,在执行此代码(块)时运行此代码(块)

顺便说一句,在这两个示例中,您正在做不同的事情:使用_params()返回

在评估块之后。而get_params()只返回

params_hash

根据您的示例,块和函数之间的主要区别在于块在调用函数的上下文中运行

如果你的例子是:

def self.do_something(object_id)
  x = "boogy on"
  self.with_params(object_id) do |params|
    some_stuff(params)
    puts x
  end
end
块内的代码可以访问块外定义的变量x。这叫做闭包。如果只是按照第二个示例调用函数,则无法执行此操作

关于块的另一个有趣的事情是,它们可以影响外部函数的控制流。因此,有可能做到:

def self.do_something(object_id)
  self.with_params(object_id) do |params|
    if some_stuff(params)
        return
    end
  end

  # This wont get printed if some_stuff returns true.
  puts "porkleworkle"
end
如果块内的some_stuff调用返回真值,则块将返回。这将返回到块外和剂量测定法外。porkleworkle无法获得输出

在您的示例中,您不依赖于这两个函数,因此使用函数调用可能更干净


但是,在许多情况下,使用块来利用这些功能是非常宝贵的。

块完全依赖于代码,但函数有自己的代码

所以,如果您的代码因情况而异,请使用block。
如果没有,则构建一个函数并将其用作块框。

在您的示例中,我认为没有理由使用Proc对象。Proc对象的全部目的是使它们在词法环境中持久化,并将它们作为参数传递给其他函数。
some_stuff(params)
做什么,它返回什么?在ruby中是“方法”,而不是“函数”。
def self.do_something(object_id)
  x = "boogy on"
  self.with_params(object_id) do |params|
    some_stuff(params)
    puts x
  end
end
def self.do_something(object_id)
  self.with_params(object_id) do |params|
    if some_stuff(params)
        return
    end
  end

  # This wont get printed if some_stuff returns true.
  puts "porkleworkle"
end