6

同じ結果をもたらす2つの例があります。

ブロック付き:

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

2番目の解決策はより簡単に思えますが、アプリケーションコードで最初の解決策のいくつかの使用法を見つけました。私の質問は次のとおりです。どのような状況で最初のものが推奨されますか?それぞれの長所と短所は何ですか?

4

4 に答える 4

3

通常、人々は、あるコードを別のコード内で実行したいときにブロックを使用します。例:

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)。明らかな理由もなく複雑すぎます。

于 2012-03-15T11:36:50.360 に答える
2

あなたの例によるブロックと関数の主な違いは、ブロックが呼び出し元の関数のコンテキスト内で実行されることです。

したがって、例が次のようになっている場合:

def self.do_something(object_id)
  x = "boogy on"
  self.with_params(object_id) do |params|
    some_stuff(params)
    puts x
  end
end

ブロック内のコードは、ブロック外で定義された変数xにアクセスできます。これはクロージャと呼ばれます。2番目の例のように関数を呼び出しているだけでは、これを行うことはできません。

ブロックのもう1つの興味深い点は、外部関数の制御フローに影響を与える可能性があることです。だからそれは可能です:

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呼び出しが真の値を返す場合、ブロックは戻ります。これは、ブロックとdosomethingメソッドから戻ります。porkleworkleは出力を取得しませんでした。

あなたの例では、これらのどちらにも依存していないので、関数呼び出しを使用する方がおそらくはるかにクリーンです。

ただし、ブロックを使用してこれらの機能を利用できるようにすることが非常に重要な状況は数多くあります。

于 2012-03-15T13:17:16.223 に答える
1

with_params()を呼び出すと、データを送信するだけでなく、実行するコードも提供されます。異なるブロックがwith_params()呼び出しに送信されるかどうかを確認します。

...
self.with_params(object_id) do |params|
  some_other_stuff()
  some_stuff(params)
end
...

そしてどこか他の場所:

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

ブロックがすべて同じであるか、with_params()が1つの場所から呼び出されただけの場合は、ブロックを削除することを検討してください。

要約すると、データだけでなくコード(ブロック)のさまざまなビットをメソッドに渡したい場合はブロックを使用します:ちょっとwith_params、このデータ(object_id)を取得し、ところで、このコード(ブロック)を実行しますそれで再。

ところで、2つの例では異なることをしています:with_params()は

some_stuff(params_hash)

ブロックを評価した後。そしてget_params()はただ返す

params_hash
于 2012-03-15T12:07:13.823 に答える
1

ブロックは完全にコードに依存しますが、関数には独自のコードがあります。

したがって、コードが状況によって状況が異なる場合は、ブロックを使用してください。そうでない場合は、関数を作成してブロックボックスとして使用します。

于 2012-03-15T14:17:26.860 に答える