2012-05-10 8 views
5

estoy trabajando con ActiveAttr que le da ese bonito initialize través de la opción de bloque:fregado un bloque de una llamada a super

person = Person.new() do |p| 
    p.first_name = 'test' 
    p.last_name = 'man' 
end 

Sin embargo, en una clase específica que incluye ActiveAttr :: Modelo, quiero omitir esta funcionalidad ya que quiero usar el bloque para otra cosa. Así que aquí vamos:

class Imperator::Command 
include ActiveAttr::Model 
end 


class MyCommand < Imperator::Command 

    def initialize(*args, &block) 
    @my_block = block 

    super(*args) 
    end 
end 

Esta falla estrepitosamente, porque el bloque aún se transmite en la cadena, y, finalmente, en el interior de ActiveAttr, este código se ejecute:

def initialize(*) 
    super 
    yield self if block_given? 
end 

Así que si mi llamada parece por lo que:

MyCommand.new() { |date| date.advance(month: 1) } 

se produce un error de la siguiente manera:

NoMethodError: undefined method `advance' for #<MyCommand:0x007fe432c4fb80> 

ya que MyCommand no tiene ningún método: anticípelo, la llamada a MyCommand obviamente falla.

Así que mi pregunta es esta, ¿hay alguna manera de que pueda eliminar el bloque de la firma del método antes de llamar al super nuevamente, para que el bloque no viaje más allá de mi inicializador anulado?

Respuesta

12

Trate

super(*args,&nil) 

El & hace uso de rubí nula como el bloque y el rubí parece lo suficientemente inteligente para darse cuenta de esto significa que no hay bloque.

+0

Perfecto, no sé por qué no pensé en eso. ¡Gracias! – TheDelChop

+1

Esto debe ser un error de rubí, aunque todavía está presente en ruby ​​2.0 – Mikey

0

Sin duda, es un truco genial, pero un mejor enfoque sería no utilizar el módulo ActiveAttr :: Model directamente y, en su lugar, incluir solo los módulos que necesita.

En lugar de

class Imperator::Command 
    include ActiveAttr::Model 
end 

Haz

class Imperator::Command 
    include BasicModel 
    # include BlockInitialization 
    include Logger 
    include MassAssignmentSecurity 
    include AttributeDefaults 
    include QueryAttributes 
    include TypecastedAttributes 

    def initialize(*args, &block) 
    @my_block = block 
    super(*args) 
    end 
end 

Una vez que vea la vista despiezada de ActiveAttr :: Modelo está haciendo puede haber otras cosas que realmente no desea. En ese caso simplemente omita los includes. La intención era proporcionar un enfoque a la carta para la construcción de modelos.

Cuestiones relacionadas