Вопрос

У меня есть два примера, которые дают тот же результат.

с блоком:

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
.

Второе решение кажется простым, но я нашел несколько использований первого в нашем приложении.Мой вопрос: в какой ситуации рекомендуется первый?Каковы плюсы и минусы каждого?

Это было полезно?

Решение

Основная разница между блоком и функцией в соответствии с вашим примером заключается в том, что блок работает в контексте функции вызывающей связи .

Так, если ваш пример был как:

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
.

Если вызов uver_Stuff внутри блока возвращает истинное значение, блок вернется. Это вернется из блока и из способа дошутного набора . PORKLEWORKLOWLE не получит вывод.

В ваших примерах вы не полагаетесь на любой из них, поэтому использование вызовов функций, вероятно, намного чище.

Тем не менее, есть много ситуаций, когда используют блоки, чтобы позволить вам воспользоваться этими вещами бесценны.

Другие советы

Обычно люди используют блоки, когда они хотят запустить кусок кода внутри другого куска кода.Примеры:

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 (), вы не только отправляете в данные, вы также предоставляете какой-то код для запуска.Посмотрите, отправляются ли разные блоки на вызов с in_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
...
.

Если блоки все равно или с_params (), только что вызывают из одного места, вы можете рассмотреть возможность устранения блоков.

Для суммирования: Используйте блоки, если вы хотите перейти в метод разные биты кода (блоки), а также данные: Hey with_params, возьмите эти данные (object_id) и, кстати, запускайте этот код (блок)пока ты на этом.

btw Вы делаете разные вещи в двух примерах: whar_params () Возвращает

some_stuff(params_hash)
.

После оценки блока.И get_params () просто возвращает

params_hash
.

Блок полностью полагается на ваш код, но функция имеет свой собственный код.

Так, если ваш код варьируется ситуация с ситуацией, используйте блок. Если нет, создайте функцию и используйте ее как блок.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top