在Ruby中我可以在initialize方法中以某种方式自动填充实例变量吗?

在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 

您可以像这样使用instance_variable_set

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

为了简单起见:

 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 

你可以通过元编程的方式做一些更聪明的事情,但这真的有必要吗?

我建议

 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 

我想你可以简单地说:

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

然后在周末课程中添加其他内容:

 class Weekend #whatever you need to add here end 

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 

请注意,您甚至不需要使用inheritance - 可以在创建期间自定义新的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 ] 

请注意,这实际上并不设置实例变量。 你的课将有不透明的getter和setter。 如果您不想暴露它们,可以在它周围包装另一个类。 这是一个例子:

 # 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