Pregunta

Tengo dos ejemplos que dan el mismo resultado.

con bloque:

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

y con método:

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

La segunda solución parece más sencilla, pero encontré algunos usos del primero en nuestro código de solicitud.Mi pregunta es: ¿en qué situación se recomienda la primera?¿Cuáles son los pros y los contras de cada uno?

¿Fue útil?

Solución

La principal diferencia entre un bloque y función según su ejemplo es que el bloque se ejecuta dentro del contexto de la función de llamada .

así que si su ejemplo fue como:

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

El código dentro del bloque puede acceder a la variable X que se definió fuera del bloque. Esto se llama un cierre. No se puede hacer esto si solo estaba llamando a una función según tu segundo ejemplo.

Otra cosa interesante sobre los bloques es que pueden afectar el flujo de control de la función exterior. Por lo que es posible hacer:

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

Si la llamada de alguna_stuff dentro del bloque devuelve un valor real, el bloque volverá. Esto volverá a partir del bloque y fuera del método de Dosalgo . PORKLEWORKLE no obtendría la salida.

En sus ejemplos, no confía en ninguno de estos, por lo que el uso de llamadas de función es probablemente mucho más limpio.

Sin embargo, hay muchas situaciones en las que el uso de bloques para permitirle aprovechar estas cosas es invaluable.

Otros consejos

Normalmente, las personas usan bloques cuando quieren ejecutar un pedazo de código dentro de otra pieza de código.Ejemplos:

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

Estos bloques están cerrados en su contexto léxico (captan variables desde donde se declara el bloque, y lleve a los cuadros cuando se llaman bloques).

Estructura esquemática de un método que acepta un bloque.

def transaction
  open_transaction # pre- part

  yield if block_given? # run provided code

  commit_transaction # post- part
rescue
  rollback_transaction # handle problems
end

En su primer ejemplo, el uso de un bloque es probablemente injustificado (IMHO).Demasiado complejo sin ninguna razón aparente.

Cuando llame con_params (), no solo está enviando datos, sino que también está proporcionando algún código para ejecutarse.Vea si se envían diferentes bloques a la llamada con_params ():

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

y en otro lugar:

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

Si los bloques son todos iguales o con_params (), se llaman de un solo lugar, puede considerar eliminar los bloques.

Para resumir: use bloques si desea pasar al método Diferentes bits de código (bloques), así como datos: hey con_params, tome estos datos (Object_ID) y, por cierto, ejecute este código (bloque)mientras estás en ello.

Por cierto, estás haciendo cosas diferentes en los dos ejemplos: con_params () devuelve

some_stuff(params_hash)

Después de evaluar el bloque.Y get_params () solo devuelve

params_hash

Un bloque totalmente confío en su código, pero una función tiene su propio código.

Entonces, si su código varía situación por situación, use bloque. Si no, construye una función y usela como una caja de bloques.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top