в Ruby я могу как-то автоматически заполнить переменные экземпляра в методе initialize? - PullRequest
14 голосов
/ 07 марта 2012

в Ruby, я могу как-то автоматически заполнить переменные экземпляра в методе initialize?

Например, если бы у меня было:

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

  def initialize(params)
    # SOMETHING HERE TO AUTO POPULATE INSTANCE VARIABLES WITH APPROPRIATE PARAMS
  end

end

Ответы [ 5 ]

14 голосов
/ 07 марта 2012

Вы можете использовать instance_variable_set так:

params.each do |key, value|
  self.instance_variable_set("@#{key}".to_sym, value)
end
7 голосов
/ 07 марта 2012

Для простоты:

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

Вы могли бы сделать что-то умнее с поворотом метапрограммирования, но действительно ли это необходимо?

2 голосов
/ 11 апреля 2013

Я думаю, вы могли бы просто написать:

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

А затем добавьте что-нибудь еще в класс выходного с:

class Weekend
#whatever you need to add here
end
2 голосов
/ 07 марта 2012

Я предлагаю

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
1 голос
/ 01 июня 2012

Ruby иногда может быть страшно простым. Цикла не видно!

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

Обратите внимание, что вам даже не нужно использовать наследование - новый Struct можно настроить при создании:

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

Тест:

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    ]

Обратите внимание, что это на самом деле не устанавливает переменные экземпляра. В вашем классе будут непрозрачные геттеры и сеттеры. Если вы не хотите их выставлять, вы можете обернуть вокруг себя другой класс. Вот пример:

# 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...