Forum: Ruby neatest way to extend Struct

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Ae16cb4f6d78e485b04ce1e821592ae5?d=identicon&s=25 Martin DeMello (Guest)
on 2008-10-23 01:00
(Received via mailing list)
I want a Structlike class that takes a hash constructor, so I can say

class A < MyStruct.new(*keys); end

a = A.new(:key1 => val1, :key2 => val2)

Is there any way to base this off Struct?

martin
D7908f05c89e965f6bc5308ad6f41256?d=identicon&s=25 Siep Korteling (steenslag)
on 2008-10-23 01:06
Martin DeMello wrote:
> I want a Structlike class that takes a hash constructor, so I can say
>
> class A < MyStruct.new(*keys); end
>
> a = A.new(:key1 => val1, :key2 => val2)
>
> Is there any way to base this off Struct?
>
> martin
It'standard:

require 'ostruct'

  (...)

  hash = { "country" => "Australia", :population => 20_000_000 }
  data = OpenStruct.new(hash)

  p data        # -> <OpenStruct country="Australia"
population=20000000>

(code from documentation)

hth,

Siep
Ae16cb4f6d78e485b04ce1e821592ae5?d=identicon&s=25 Martin DeMello (Guest)
on 2008-10-23 01:19
(Received via mailing list)
On Wed, Oct 22, 2008 at 4:04 PM, Siep Korteling <s.korteling@gmail.com>
wrote:
> It'standard:
>
> require 'ostruct'

No, OpenStruct pulls in other things I don't want (the whole 'open'
thing).

martin
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2008-10-23 01:31
(Received via mailing list)
Martin DeMello wrote:
> I want a Structlike class that takes a hash constructor, so I can say
>
> class A < MyStruct.new(*keys); end
>
> a = A.new(:key1 => val1, :key2 => val2)
>
> Is there any way to base this off Struct?
>
> martin

Something based on this, maybe? I hope Struct#members preserves order...

class A < Struct.new(:a, :b)
   def initialize(h)
     super *h.values_at(*self.class.members.map {|s| s.intern})
   end
end

a = A.new(:a => 1, :b => 2)
p a # ==> #<struct A a=1, b=2>
F53b05cdbdf561cfe141f69b421244f3?d=identicon&s=25 David A. Black (Guest)
on 2008-10-23 01:36
(Received via mailing list)
Hi --

On Thu, 23 Oct 2008, Martin DeMello wrote:

> I want a Structlike class that takes a hash constructor, so I can say
>
> class A < MyStruct.new(*keys); end
>
> a = A.new(:key1 => val1, :key2 => val2)
>
> Is there any way to base this off Struct?

Do you need to use inheritance, as opposed to just instantiating
MyStruct directly? I'm thinking of, for example:

class MyStruct < Struct
   def self.new(*keys)
     s = super
     s.class_eval do
       define_method(:initialize) do |hash|
         hash.each {|k,v| send("#{k}=",v) }
       end
     end
     s
   end
end

A = MyStruct.new(:a,:b)
a = A.new(:a => 1, :b => 2)
p a.b    # 2


David
Ae16cb4f6d78e485b04ce1e821592ae5?d=identicon&s=25 Martin DeMello (Guest)
on 2008-10-23 01:44
(Received via mailing list)
On Wed, Oct 22, 2008 at 4:34 PM, David A. Black <dblack@rubypal.com>
wrote:
>      end
>    end
>    s
>  end
> end

Doh - of course, since you aren't inheriting from Struct, you
shouldn't be inheriting from MyStruct either :) Wasn't thinking
clearly enough about the problem. Thanks!

martin
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2008-10-23 08:05
(Received via mailing list)
On 23.10.2008 01:42, Martin DeMello wrote:
>>      end
>>    end
>>    s
>>  end
>> end
>
> Doh - of course, since you aren't inheriting from Struct, you
> shouldn't be inheriting from MyStruct either :) Wasn't thinking
> clearly enough about the problem. Thanks!

Why inheritance at all?   Why do too much?

irb(main):001:0> MyStruct = Struct.new :foo, :bar do
irb(main):002:1* def initialize(h={})
irb(main):003:2> members.each {|m| self[m] = h[m.to_sym]}
irb(main):004:2> end
irb(main):005:1> end
=> MyStruct
irb(main):006:0> ms = MyStruct.new(:bar => 1, :foo => 2)
=> #<struct MyStruct foo=2, bar=1>

Kind regards

  robert
58479f76374a3ba3c69b9804163f39f4?d=identicon&s=25 Eric Hodel (Guest)
on 2008-10-23 08:29
(Received via mailing list)
On Oct 22, 2008, at 23:03 PM, Robert Klemme wrote:
> Why inheritance at all?   Why do too much?
>
> irb(main):001:0> MyStruct = Struct.new :foo, :bar do
> irb(main):002:1* def initialize(h={})
> irb(main):003:2> members.each {|m| self[m] = h[m.to_sym]}
> irb(main):004:2> end
> irb(main):005:1> end
> => MyStruct
> irb(main):006:0> ms = MyStruct.new(:bar => 1, :foo => 2)
> => #<struct MyStruct foo=2, bar=1>

Hey, neat! I didn't know you could do that!

I've always reopened the class.
Ae16cb4f6d78e485b04ce1e821592ae5?d=identicon&s=25 Martin DeMello (Guest)
on 2008-10-23 08:36
(Received via mailing list)
On Wed, Oct 22, 2008 at 11:03 PM, Robert Klemme
<shortcutter@googlemail.com> wrote:
>
> Why inheritance at all?   Why do too much?

Because I'd have to repeat that for every new struct I created. But
that's a very neat trick indeed!

martin
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2008-10-23 09:21
(Received via mailing list)
2008/10/23 Martin DeMello <martindemello@gmail.com>:
> On Wed, Oct 22, 2008 at 11:03 PM, Robert Klemme
> <shortcutter@googlemail.com> wrote:
>>
>> Why inheritance at all?   Why do too much?
>
> Because I'd have to repeat that for every new struct I created. But
> that's a very neat trick indeed!

Oh, you want another Struct implementation that does this? I wasn't
aware of this. That's easily fixed.

class MyStruct < Struct
  def initialize(h={})
    members.each {|m| self[m] = h[m.to_sym]}
  end
end

s1 = MyStruct.new :foo, :bar
p s1.ancestors, s1.new(:bar => 123)

Kind regards

robert
This topic is locked and can not be replied to.