user3500854
user3500854

Reputation: 45

Try create my own Struct via Ruby

I can't inherit the Struct. I must implement class which act like Struct. Is there a way improve my code for use "ClassName" and functional like Struct ? And write k=Dave.new("Rachel" , "Greene") ???

class MyStruct
  def self.new(*attributes)
    puts "ppp"
    dynamic_name = "ClassName"
    Kernel.const_set(dynamic_name,Class.new()  do
      attributes.each do |action|
        self.send(:define_method, action) {
          puts "call #{action}" 
        }
      end  
    end
    )
  end
end

# class ClassName
  # def new *args 
    # puts "iii"
  # end
# end



Dave = MyStruct.new(:name, :surname)

k=Dave.new()     # k=Dave.new("Rachel" , "Greene")
k.surname
k.name

Upvotes: 2

Views: 155

Answers (2)

Uri Agassi
Uri Agassi

Reputation: 37419

Here is a version of your code which works:

class MyStruct
  def self.new(*attributes)
    Class.new do
      self.send(:attr_accessor, *attributes)
      self.send(:define_method, :initialize) do |*values|
        values.each_with_index { |val, i| self.send("#{attributes[i]}=", val) }
      end  
    end
  end
end

Dave = MyStruct.new(:name, :surname)
k = Dave.new('Rachel', 'Green')
# => #<Dave:0x00000001af2b10 @name="Rachel", @surname="Green"> 
k.name
# => "Rachel"
k.surname
# => "Green"
  1. You don't need to const_set inside the method - Dave = is enough
  2. I'm creating here an attr_accessor for each of the attributes, so you are getting a getter and a setter for each
  3. In the initialize method I'm sending each value to its corresponding setter, to set all values. If there are less values than anticipated, the last attributes will not be set, if there are more - an exception will be thrown (undefined method '=')

Upvotes: 5

bodacious
bodacious

Reputation: 6705

Have you looked at the Struct class in Ruby?

http://www.ruby-doc.org/core-2.1.2/Struct.html

class MyStruct < Struct.new(:first_name, :last_name)

end

MyClassObj = MyStruct.new("Gavin", "Morrice")

Also, you shouldn't ever overwrite self.new, define initialize instead

Upvotes: 3

Related Questions