7

Duplicar posible:
attr_accessor default values¿Cómo inicializar los valores del atributo 'attr_accessor'?

estoy usando Ruby on Rails 3.0.9 y me gustaría para inicializar algunos valores de atributos attr_accessor en mi clase \ modelo que hereda de ActiveRecord::Base. Es decir,

... en mi módulo que tengo:

class User < ActiveRecord::Base 
    attr_accessor :attribute_name1, 
       :attribute_name2, 
       :attribute_name3, 
       ... 
end 

y me gustaría establecer a true todos los valores de atributos attr_accessor. ¿Cómo puedo hacer eso?

P.S .: Por supuesto, me gustaría resolver el problema anterior que se aproxima a "à la Ruby on Rails Way". Yo sé sobre el after_initialize de devolución de llamada, pero mediante el uso de ese método que debería repetir cada attribute_name<N> declaración para los que me gustaría establecer el valor en su interior que trueafter_initialize declaración (... y esto es no seco - No Repeat Yourself) . Tal vez hay una mejor manera de lograr esto. ¿Hay alguna forma de establecer valores de atributo attr_accessor "sobre la marcha" cuando especifica esos atributos? Es decir, espero declarar y establecer los atributos attr_accessor a la vez.

+0

hay una lógica real detrás de los nombres (1,2 ...)? – apneadiving

+0

@apneadiving - Sí, por supuesto. – Backo

Respuesta

6

para los carriles 3.2 o anterior, se puede usar attr_accessor_with_default:

class User < ActiveRecord::Base 
    attr_accessor_with_default :attribute_name1, true 
    attr_accessor_with_default :attribute_name2, true 
    attr_accessor_with_default :attribute_name3, true 
    ... 
end 

Debido a que su valor por defecto es un tipo inmutable (booleano), esta forma de método es segura de usar aquí. Pero no lo use si el valor predeterminado es un objeto mutable, incluyendo una matriz o cadena, porque todos sus nuevos objetos de modelo compartirán la misma instancia exacta, que probablemente no sea la que usted desea.

En cambio, attr_accessor_with_default aceptará un bloque, donde se puede devolver una nueva instancia cada vez:

attr_accessor_with_default(:attribute_name) { FizzBuzz.new } 
+5

Nota para los lectores actuales que 'attr_accessor_with_default' está en desuso a partir de Rails 3.2 –

11

¿Usted intentó:

class User < ActiveRecord::Base 
    attr_accessor :attribute_name1, 
       :attribute_name2, 
       :attribute_name3, 
       ... 

    after_initialize :set_attr 

    def set_attr 
    @attribute_name1 = true 
    ... 
    end 
end 
+0

Actualicé la pregunta (lea "P.S .:" al final). – Backo

+0

@Backo, aquí está todo lo suficientemente SECO en la respuesta – fl00r

+0

@apneadiving - ¿Hay alguna forma de establecer los valores de los atributos 'attr_accessor' "sobre la marcha" cuando los especifica? – Backo

3

me acaba de definir un captador que carga con pereza el valor que está interesado en , y usa attr_writer para definir el setter. Por ejemplo,

class Cat 
    attr_writer :amount_of_feet 
    def amount_of_feet; @amount_of_feet ||= 4; end # usually true 
end 

Lo cual, si lo haces en serio, puede reescribirse con un poco de meta-programación:

class Cat 
    # The below method could be defined in Module directly 
    def self.defaulted_attributes(attributes) 
    attributes.each do |attr, default| 
     attr_writer attr 

     define_method(attr) do 
     instance_variable_get("@#{attr}") || 
      instance_variable_set("@#{attr}", default) 
     end 
    end 
    end 

    defaulted_attributes :amount_of_feet => 4 
end 

calin = Cat.new 
print "calin had #{calin.amount_of_feet} feet... " 
calin.amount_of_feet -= 1 
puts "but I cut one of them, he now has #{calin.amount_of_feet}" 

Esto funciona porque, por lo general, calculando el valor por defecto no tendrá ningún lado El efecto hace que el orden sea importante y no será necesario calcular el valor hasta que primero intente acceder a él.

(Câlin es mi gato; lo está haciendo bien, y todavía tiene el cuatro de sus pies)

Cuestiones relacionadas