Pregunta

Quiero definir un método de clase que tiene acceso a una variable local.Así que esto sería diferente para cada instancia de la clase.Sé que se puede hacer una clase de método dinámico con lambda como cuando se utiliza con named_scope.Pero se puede hacer esto para los valores que son específicos de una instancia?

En detalle es el has_attached_file método para el clip plugin de rails.Quiero pasar un lambda para los estilos de hash, de modo que los estilos de imagen que pueden ser basados en los atributos de los objetos almacenados en la base de datos.Es esto posible?

¿Fue útil?

Solución

Descargo de responsabilidad: En primer lugar, la pregunta (Se puede pasar el auto a lambda?) y el problema que estamos tratando de resolver (dinámica de estilos con clip) no coinciden plenamente.No voy a responder a la pregunta original porque no está totalmente relacionado con su problema, y rampion tomó una valiente puñalada en ella.

Lugar de ello voy a responder a su clip pregunta.

En detalle es el has_attached_file método para el clip plugin de rails.Quiero pasar un lambda para los estilos de hash, de modo que los estilos de imagen que pueden ser basados en los atributos de los objetos almacenados en la base de datos.Es esto posible?

Sí, es posible. En el clip, la :styles opción puede tomar un Proc.Cuando el adjunto es inicializado, si un Proc fue utilizado, el apego a sí mismo se pasa a la Proc.El apego tiene una referencia a los asociados de ActiveRecord objeto, de modo que usted puede utilizar para determinar su dinámica de estilos.

Por ejemplo, su has_attached_file declaración podría ser algo como esto (suponiendo que el Usuario y avatar escenario donde el usuario puede personalizar el tamaño de su avatar):

class User < ActiveRecord::Base
  has_attached_file :avatar, :styles => lambda { |attachment| 
    user = attachment.instance
    dimensions = "#{user.avatar_width}x#{user.avatar_height}#"
    { :custom => dimensions }
  }
end

Otros consejos

Ok, estás siendo poco clara.

Las variables locales en rubí comienzan con una letra minúscula (como foo, bar o steve), y están en el ámbito léxico (como las variables C). No tienen nada que ver con "una instancia de una clase"

Las variables de instancia en Ruby comienzan con un sigilo @ (como @foo, @bar, o @carl), y están en el alcance cada vez que el valor actual de self es el objeto que se almacenan en.

Si quieres un método que se puede acceder a las variables de instancia de un objeto directamente, eso se llama un método de instancia. Por ejemplo, battle_cry y initialize son ambos métodos de instancia:

class Character
  def initialize(name)
    @name=name
  end
  def battle_cry
    @name.upcase + "!!!"
  end
  def Character.default
    new("Leeroy Jenkins")
  end
end

un método de clase, por el contrario, es un método para un objeto Class, y no tiene acceso a ninguna de las variables de instancia de ese objeto. En el ejemplo anterior, default es un método de clase.

Si desea un método (clase o instancia) que desencadena un cambio en o se pone un valor en el ámbito actual, rubí utiliza un tipo de devolución de llamada denomina bloque.

class Character
   ATTACKS = [ "Ho!", "Haha!", "Guard!", "Turn!", "Parry!", "Dodge!", "Spin!", "Ha", "THRUST!" ]
   def attack
     ATTACKS.inject(0) { |dmg, word| dmg + yield(word) }
   end
end

person = Character.default
puts person.battle_cry

num_attacks = 0;
damage = person.attack do |saying|
  puts saying
  num_attacks += 1
  rand(3)
end
puts "#{damage} points of damage done in #{num_attacks} attacks"

En el ejemplo anterior, attack utiliza la palabra clave yield para llamar al bloque pasado lo. Cuando llamamos attack, entonces, el num_attacks variable local sigue siendo en su alcance en el bloque lo pasamos (delimitado por aquí do ... end), de modo que podamos se incrementará. attack es capaz de pasar los valores en el bloque, aquí que son capturados en la variable saying. El bloque también pasa los valores de de vuelta al método, que se muestran como el valor de retorno de yield.

La palabra lambda en rubí generalmente significa la palabra clave lambda, que se utiliza para hacer bloques en independiente, funcionan como objetos (que de por sí son normalmente se hace referencia como lambdas, procs, o Procs).

bounce = lambda { |thing| puts "I'm bouncing a #{thing}" }
bounce["ball"]
bounce["frog"]

Así que creo que lo que estás preguntando es si se puede pasar una Proc en lugar de un Hash para un argumento a un método. Y la respuesta es "depende". Si el único método siempre utiliza el método #[], entonces sí:

class Character
  attr_accessor :stats
  def set_stats(stats)
    @stats = stats
  end
end

frank = Character.new("Victor Frankenstein")
frank.set_stats({ :str => 7, :dex => 14, :con => 9, :int => 19, :wis => 7, :cha => 11 })

monster = Character.new("Frankenstein's Monster")
monster.set_stats(lambda do |stat_name|
  rand(20)
end)

Sin embargo, podría usar algunos métodos específicos Hash otra, o llamar a la misma clave varias veces, que puede producir resultados extraños:

monster = Character.new("Frankenstein's Monster")
monster.set_stats(lambda do |stat_name|
  rand(20)
end)

monster.stats[:dex] #=> 19
monster.stats[:dex] #=> 1

En cuyo caso, usted puede ser mejor de almacenamiento en caché de las solicitudes en un hash intermedia. Esto es bastante fácil, ya que una Hash puede tener un bloque de inicialización. Así que si cambiamos el anterior a:

monster.set_stats(Hash.new do |stats_hash, stat_name|
  stats_hash[stat_name] = rand(20)
end)

monster.stats[:dex] #=> 3
monster.stats[:dex] #=> 3

Los resultados se almacenan en caché en el hash

Para ver más sobre inicializadores bloque Hash, ver ri Hash::new:

-------------------------------------------------------------- Hash::new
     Hash.new                          => hash
     Hash.new(obj)                     => aHash
     Hash.new {|hash, key| block }     => aHash
------------------------------------------------------------------------
     Returns a new, empty hash. If this hash is subsequently accessed
     by a key that doesn't correspond to a hash entry, the value
     returned depends on the style of new used to create the hash. In
     the first form, the access returns nil. If obj is specified, this
     single object will be used for all default values. If a block is
     specified, it will be called with the hash object and the key, and
     should return the default value. It is the block's responsibility
     to store the value in the hash if required.

        h = Hash.new("Go Fish")
        h["a"] = 100
        h["b"] = 200
        h["a"]           #=> 100
        h["c"]           #=> "Go Fish"
        # The following alters the single default object
        h["c"].upcase!   #=> "GO FISH"
        h["d"]           #=> "GO FISH"
        h.keys           #=> ["a", "b"]

        # While this creates a new default object each time
        h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
        h["c"]           #=> "Go Fish: c"
        h["c"].upcase!   #=> "GO FISH: C"
        h["d"]           #=> "Go Fish: d"
        h.keys           #=> ["c", "d"]
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top