2012-03-07 6 views

Respuesta

14

Puede utilizar instance_variable_set así:

params.each do |key, value| 
    self.instance_variable_set("@#{key}".to_sym, value) 
end 
6

Para simplificar las cosas:

class Weekend 
    attr_accessor :start_date, :end_date, :title, :description, :location 

    def initialize(params) 
  @start_date = params[:start_date] # I don't really know the structure of params but you have the idea 
    @end_date = params[:end_date] 
    end 
end 

se podría hacer algo más elegante con un toque de metaprogramming pero es realmente necesario?

+0

me gusta contestar desde el iPhone y veo marcado estropeado ... – apneadiving

+2

Entiendo el deseo de evitar el metaprog innecesario, pero este no es realmente el código sucinto que el OP estaba pidiendo. Debe especificar manualmente cada nombre de campo. – Kelvin

2

que sugieren

class Weekend 
    @@available_attributes = [:start_date, :end_date, :title, :description, :location] 
    attr_accessor *@@available_attributes 

    def initialize(params) 
    params.each do |key,value| 
     self.send(:"#{key}=",value) if @@available_attributes.include?(key.to_sym) 
    end 
    end 
end 
+0

¿Qué tal una constante 'AVAILABLE_ATTRIBUTES' en lugar de una variable de clase? – jhirsch

1

Ruby puede dar miedo a veces sencilla. No hay bucles a la vista!

class Weekend < Struct.new(:start_date, :end_date, :title, :description, :location) 
    # params: Hash with symbols as keys 
    def initialize(params) 
    # arg splatting to the rescue 
    super(* params.values_at(* self.class.members)) 
    end 
end 

Tenga en cuenta que ni siquiera es necesario utilizar la herencia - un nuevo Struct puede ser personalizado durante la creación:

Weekend = Struct.new(:start_date, :end_date, :title, :description, :location) do 
    def initialize(params) 
    # same as above 
    end 
end 

prueba:

weekend = Weekend.new(
    :start_date => 'start_date value', 
    :end_date => 'end_date value', 
    :title => 'title value', 
    :description => 'description value', 
    :location => 'location value' 
) 

p [:start_date , weekend.start_date ] 
p [:end_date , weekend.end_date ] 
p [:title  , weekend.title  ] 
p [:description, weekend.description ] 
p [:location , weekend.location ] 

Tenga en cuenta que esto no en realidad establecer variables de instancia. Tu clase tendrá getters y setters opacos. Si prefieres no exponerlos, puedes ajustar otra clase alrededor de él. He aquí un ejemplo:

# this gives you more control over readers/writers 
require 'forwardable' 
class Weekend 
    MyStruct = ::Struct.new(:start_date, :end_date, :title, :description, :location) 
    extend Forwardable 
    # only set up readers 
    def_delegators :@struct, *MyStruct.members 

    # params: Hash with symbols as keys 
    def initialize(params) 
    # arg splatting to the rescue 
    @struct = MyStruct.new(* params.values_at(* MyStruct.members)) 
    end 
end 
+0

thx. ¿Es esta una forma común de Ruby de hacer las cosas? – BKSpurgeon

+0

@BKSpurgeon No sé qué tan común es. Si tiene la intención de usarlo en un proyecto de equipo, le sugiero que pregunte al equipo si se sienten cómodos con él. – Kelvin

2

Creo que simplemente podría poner:

Weekend < Struct.new(:start_date, :end_date, :title, :description, :location) 

y luego añadir nada más a la clase de fin de semana con:

class Weekend 
#whatever you need to add here 
end 
+1

Volví para responder a esta pregunta que vi hace dos años solo para encontrar a alguien que me diera la respuesta que tenía en mente hace un año. (Pero prefiero 'clase Fin de semana nurettin

Cuestiones relacionadas