2012-03-07 13 views

risposta

14

È possibile utilizzare instance_variable_set come questo:

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

Per mantenere le cose semplici:

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 

si potrebbe fare qualcosa più intelligente con un tocco di metaprogrammazione, ma è davvero necessario?

+0

Odio rispondere da iPhone e vedere markup viziato ... – apneadiving

+2

Capisco il desiderio di evitare metaprog inutili, ma questo non è il codice sintetico che l'OP stava chiedendo. Devi specificare manualmente ciascun nome di campo. – Kelvin

2

suggerisco

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

Che ne dici di una costante 'AVAILABLE_ATTRIBUTES' al posto di una variabile di classe? – jhirsch

1

Rubino può essere spaventoso semplice a volte. Nessun loop in 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 

Si noti che non hanno nemmeno bisogno di usare l'ereditarietà - un nuovo Struct può essere personalizzato durante la creazione:

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

prova:

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 ] 

Si noti che questo non lo fa imposta effettivamente variabili di istanza. La tua classe avrà getter e setter opachi. Se preferisci non esporli, puoi avvolgere un'altra classe intorno ad essa. Ecco un esempio:

# 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. è questo un modo rubino comune di fare le cose? – BKSpurgeon

+0

@BKSpurgeon Non so quanto sia comune. Se intendi usarlo in un progetto di squadra, ti suggerisco di chiedere al team se sono a loro agio. – Kelvin

2

Penso che si potrebbe semplicemente mettere:

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

e quindi aggiungere qualsiasi altra cosa alla classe fine settimana con:

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

Sono tornato per rispondere a questa domanda che ho visto due anni fa solo per trovare qualcuno che ha dato la risposta che avevo in mente un anno fa. (ma preferisco 'class Weekend nurettin

Problemi correlati