Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.ruby > #3631 > unrolled thread
| Started by | Brian Candler <b.candler@pobox.com> |
|---|---|
| First post | 2011-04-28 12:00 -0500 |
| Last post | 2011-04-29 03:22 -0500 |
| Articles | 10 — 5 participants |
Back to article view | Back to comp.lang.ruby
Initialize Struct from Hash Brian Candler <b.candler@pobox.com> - 2011-04-28 12:00 -0500
Re: Initialize Struct from Hash Jesús Gabriel y Galán <jgabrielygalan@gmail.com> - 2011-04-28 12:05 -0500
Re: Initialize Struct from Hash Jesús Gabriel y Galán <jgabrielygalan@gmail.com> - 2011-04-28 12:10 -0500
Re: Initialize Struct from Hash 7stud -- <bbxx789_05ss@yahoo.com> - 2011-04-28 12:16 -0500
Re: Initialize Struct from Hash Jesús Gabriel y Galán <jgabrielygalan@gmail.com> - 2011-04-28 12:19 -0500
Re: Initialize Struct from Hash Brian Candler <b.candler@pobox.com> - 2011-04-28 15:24 -0500
Re: Initialize Struct from Hash Joel VanderWerf <joelvanderwerf@gmail.com> - 2011-04-28 15:50 -0500
Re: Initialize Struct from Hash Robert Klemme <shortcutter@googlemail.com> - 2011-04-29 03:06 -0500
Re: Initialize Struct from Hash Joel VanderWerf <joelvanderwerf@gmail.com> - 2011-04-29 10:27 -0500
Re: Initialize Struct from Hash Brian Candler <b.candler@pobox.com> - 2011-04-29 03:22 -0500
| From | Brian Candler <b.candler@pobox.com> |
|---|---|
| Date | 2011-04-28 12:00 -0500 |
| Subject | Initialize Struct from Hash |
| Message-ID | <919600ef40c16b10cb0f01a757234376@ruby-forum.com> |
I just want to check I've not missed something here. Is there a built-in
way to initialize a Struct from a hash of key/value pairs?
That is, can I shorten the following?
K1 = Struct.new :foo, :bar
module FixStruct
def set(h)
h.each { |k,v| self[k] = v }
self
end
end
class K1
include FixStruct
end
k1 = K1.new.set(:bar=>456, :foo=>123)
p k1
(I'm talking about real Struct here, not OpenStruct etc)
Thanks,
Brian.
--
Posted via http://www.ruby-forum.com/.
[toc] | [next] | [standalone]
| From | Jesús Gabriel y Galán <jgabrielygalan@gmail.com> |
|---|---|
| Date | 2011-04-28 12:05 -0500 |
| Message-ID | <BANLkTinnJvTxPXORtnne78=eZAmka5-qHQ@mail.gmail.com> |
| In reply to | #3631 |
On Thu, Apr 28, 2011 at 7:00 PM, Brian Candler <b.candler@pobox.com> wrote:
> I just want to check I've not missed something here. Is there a built-in
> way to initialize a Struct from a hash of key/value pairs?
>
> That is, can I shorten the following?
>
> K1 = Struct.new :foo, :bar
>
> module FixStruct
> def set(h)
> h.each { |k,v| self[k] = v }
> self
> end
> end
>
> class K1
> include FixStruct
> end
>
> k1 = K1.new.set(:bar=>456, :foo=>123)
> p k1
>
> (I'm talking about real Struct here, not OpenStruct etc)
ruby-1.8.7-p334 :001 > K = Struct.new :id,:timestamp
=> K
ruby-1.8.7-p334 :002 > K[3,8]
=> #<struct K id=3, timestamp=8>
Jesus.
[toc] | [prev] | [next] | [standalone]
| From | Jesús Gabriel y Galán <jgabrielygalan@gmail.com> |
|---|---|
| Date | 2011-04-28 12:10 -0500 |
| Message-ID | <BANLkTim3zKr-02ZLmp6Dy1yuNDab0O9vYQ@mail.gmail.com> |
| In reply to | #3632 |
2011/4/28 Jesús Gabriel y Galán <jgabrielygalan@gmail.com>:
> On Thu, Apr 28, 2011 at 7:00 PM, Brian Candler <b.candler@pobox.com> wrote:
>> I just want to check I've not missed something here. Is there a built-in
>> way to initialize a Struct from a hash of key/value pairs?
>>
>> That is, can I shorten the following?
>>
>> K1 = Struct.new :foo, :bar
>>
>> module FixStruct
>> def set(h)
>> h.each { |k,v| self[k] = v }
>> self
>> end
>> end
>>
>> class K1
>> include FixStruct
>> end
>>
>> k1 = K1.new.set(:bar=>456, :foo=>123)
>> p k1
>>
>> (I'm talking about real Struct here, not OpenStruct etc)
>
> ruby-1.8.7-p334 :001 > K = Struct.new :id,:timestamp
> => K
> ruby-1.8.7-p334 :002 > K[3,8]
> => #<struct K id=3, timestamp=8>
Sorry, I just realized this is not what you want.
Although if you know the order of the attributes defined by the
Struct, you can build something upon this, transforming the hash into
an array in the appropriate order. Whether that's cleaner than your
solution is not so clear.
Jesus.
[toc] | [prev] | [next] | [standalone]
| From | 7stud -- <bbxx789_05ss@yahoo.com> |
|---|---|
| Date | 2011-04-28 12:16 -0500 |
| Message-ID | <061feef934e8496634c868f2a00a4ff2@ruby-forum.com> |
| In reply to | #3632 |
"Jesús Gabriel y Galán" <jgabrielygalan@gmail.com> wrote in post
#995567:
> On Thu, Apr 28, 2011 at 7:00 PM, Brian Candler <b.candler@pobox.com>
> wrote:
>> self
>> (I'm talking about real Struct here, not OpenStruct etc)
> ruby-1.8.7-p334 :001 > K = Struct.new :id,:timestamp
> => K
> ruby-1.8.7-p334 :002 > K[3,8]
> => #<struct K id=3, timestamp=8>
>
> Jesus.
Is there a hash anywhere in your code? How about this:
K1 = Struct.new :foo, :bar
class MyClass < K1
def initialize(hash)
super(*hash.values_at(:foo, :bar) )
end
end
puts MyClass.new(bar: 456, foo: 123)
(stolen from:
http://stackoverflow.com/questions/2680523/dry-ruby-initialization-with-hash-argument)
--
Posted via http://www.ruby-forum.com/.
[toc] | [prev] | [next] | [standalone]
| From | Jesús Gabriel y Galán <jgabrielygalan@gmail.com> |
|---|---|
| Date | 2011-04-28 12:19 -0500 |
| Message-ID | <BANLkTi=rTnHVOqphCJ7GfdfmqPY_uyQHHQ@mail.gmail.com> |
| In reply to | #3636 |
On Thu, Apr 28, 2011 at 7:16 PM, 7stud -- <bbxx789_05ss@yahoo.com> wrote:
> "Jesús Gabriel y Galán" <jgabrielygalan@gmail.com> wrote in post
> #995567:
>> On Thu, Apr 28, 2011 at 7:00 PM, Brian Candler <b.candler@pobox.com>
>> wrote:
>>> self
>>> (I'm talking about real Struct here, not OpenStruct etc)
>> ruby-1.8.7-p334 :001 > K = Struct.new :id,:timestamp
>> => K
>> ruby-1.8.7-p334 :002 > K[3,8]
>> => #<struct K id=3, timestamp=8>
>>
>> Jesus.
>
> Is there a hash anywhere in your code? How about this:
Yep, I know. How about this?
ruby-1.8.7-p334 :014 > h = {:id => 3, :timestamp => 6}
=> {:timestamp=>6, :id=>3}
ruby-1.8.7-p334 :043 > K = Struct.new :id, :timestamp do
ruby-1.8.7-p334 :044 > def self.from_hash h
ruby-1.8.7-p334 :045?> self[*h.values_at(*K.members.map {|m| m.to_sym})]
ruby-1.8.7-p334 :046?> end
ruby-1.8.7-p334 :047?> end
=> K
ruby-1.8.7-p334 :048 > K.from_hash h
=> #<struct K id=3, timestamp=6>
Jesus.
[toc] | [prev] | [next] | [standalone]
| From | Brian Candler <b.candler@pobox.com> |
|---|---|
| Date | 2011-04-28 15:24 -0500 |
| Message-ID | <69c1ac462d5ff72621121fcf6c8135ec@ruby-forum.com> |
| In reply to | #3631 |
Thanks for all the feedback, at least I know I hadn't missed something obvious :-) I found an interesting thread here too: http://www.ruby-forum.com/topic/67759 Cheers, Brian. -- Posted via http://www.ruby-forum.com/.
[toc] | [prev] | [next] | [standalone]
| From | Joel VanderWerf <joelvanderwerf@gmail.com> |
|---|---|
| Date | 2011-04-28 15:50 -0500 |
| Message-ID | <4DB9D327.9000905@gmail.com> |
| In reply to | #3654 |
On 04/28/2011 01:24 PM, Brian Candler wrote:
> Thanks for all the feedback, at least I know I hadn't missed something
> obvious :-)
>
> I found an interesting thread here too:
> http://www.ruby-forum.com/topic/67759
Tangentially, I wonder if anything like the following (very rough proof
of concept) has been used instead of Struct.
class Hash
def structify!
keys.each do |key|
class << self; self; end.class_eval do
define_method key do
fetch key
end
define_method "#{key}=" do |val|
store key, val
end
end
end
end
end
h = {:foo => 1, :bar => 2}
h.structify!
p h.foo # 1
h.foo = 3
p h.foo # 3
p h # {:foo=>3, :bar=>2}
p h.oof # undefined
[toc] | [prev] | [next] | [standalone]
| From | Robert Klemme <shortcutter@googlemail.com> |
|---|---|
| Date | 2011-04-29 03:06 -0500 |
| Message-ID | <BANLkTikR=wRKtkfe46=j+apo9bLRR-CHgQ@mail.gmail.com> |
| In reply to | #3657 |
On Thu, Apr 28, 2011 at 10:50 PM, Joel VanderWerf
<joelvanderwerf@gmail.com> wrote:
> Tangentially, I wonder if anything like the following (very rough proof of
> concept) has been used instead of Struct.
>
> class Hash
> def structify!
> keys.each do |key|
> class << self; self; end.class_eval do
> define_method key do
> fetch key
> end
> define_method "#{key}=" do |val|
> store key, val
> end
> end
> end
> end
> end
>
> h = {:foo => 1, :bar => 2}
> h.structify!
> p h.foo # 1
> h.foo = 3
> p h.foo # 3
> p h # {:foo=>3, :bar=>2}
> p h.oof # undefined
irb(main):004:0> h = {:foo => 1, :bar => 2}
=> {:foo=>1, :bar=>2}
irb(main):005:0> o = OpenStruct.new(h)
=> #<OpenStruct foo=1, bar=2>
irb(main):006:0> o.foo
=> 1
irb(main):007:0> o.bar
=> 2
Well, here we differ
irb(main):008:0> o.oof
=> nil
But the issue with your approach is that it is not dynamic. Keys
added or removed after call to #structify! will not be taken care of.
A more dynamic approach would be
module HashStruct
def method_missing(s,*a,&b)
case
when a.empty? && key?(s)
self[s]
when a.size == 1 && /\A(.+)=\z/ =~ s
self[$1.to_sym] = a.first
else
super
end
end
end
h.extend HashStruct
h.foo
Kind regards
robert
--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
[toc] | [prev] | [next] | [standalone]
| From | Joel VanderWerf <joelvanderwerf@gmail.com> |
|---|---|
| Date | 2011-04-29 10:27 -0500 |
| Message-ID | <4DBAD8F0.8000202@gmail.com> |
| In reply to | #3683 |
On 04/29/2011 01:06 AM, Robert Klemme wrote:
> On Thu, Apr 28, 2011 at 10:50 PM, Joel VanderWerf
> <joelvanderwerf@gmail.com> wrote:
>
>> Tangentially, I wonder if anything like the following (very rough proof of
>> concept) has been used instead of Struct.
>>
>> class Hash
>> def structify!
>> keys.each do |key|
>> class<< self; self; end.class_eval do
>> define_method key do
>> fetch key
>> end
>> define_method "#{key}=" do |val|
>> store key, val
>> end
>> end
>> end
>> end
>> end
>>
>> h = {:foo => 1, :bar => 2}
>> h.structify!
>> p h.foo # 1
>> h.foo = 3
>> p h.foo # 3
>> p h # {:foo=>3, :bar=>2}
>> p h.oof # undefined
>
> irb(main):004:0> h = {:foo => 1, :bar => 2}
> => {:foo=>1, :bar=>2}
> irb(main):005:0> o = OpenStruct.new(h)
> => #<OpenStruct foo=1, bar=2>
> irb(main):006:0> o.foo
> => 1
> irb(main):007:0> o.bar
> => 2
>
> Well, here we differ
>
> irb(main):008:0> o.oof
> => nil
>
> But the issue with your approach is that it is not dynamic. Keys
> added or removed after call to #structify! will not be taken care of.
> A more dynamic approach would be
That's intended: #structify is supposed to turn a hash into something
that looks like a Struct, not an OpenStruct.
[toc] | [prev] | [next] | [standalone]
| From | Brian Candler <b.candler@pobox.com> |
|---|---|
| Date | 2011-04-29 03:22 -0500 |
| Message-ID | <03b8b18259c6ce145336bdbb11ba2e1f@ruby-forum.com> |
| In reply to | #3657 |
Joel VanderWerf wrote in post #995632:
> Tangentially, I wonder if anything like the following (very rough proof
> of concept) has been used instead of Struct.
That's neat. However you'd have to make sure you've set a value for
every key of interest, including defaults, before calling "structify!"
How about this variation:
class StructHash < Hash
def initialize(h = {})
replace(self.class::DEFAULTS.merge(h))
end
end
def StructHash(defaults)
k = Class.new(StructHash)
k.const_set(:DEFAULTS, defaults)
defaults.keys.each do |key|
k.class_eval do
define_method key do
fetch key
end
define_method "#{key}=" do |val|
store key, val
end
end
end
k
end
Foo = StructHash(:foo=>123, :bar=>456)
f = Foo.new(:foo=>0)
p f
p f.foo
p f.bar
I'm usually not a fan of subclassing core types, but I could be
persuaded here.
Perhaps the initialize function should look like this instead:
class StructHash < Hash
def initialize(h = {})
replace(self.class::DEFAULTS)
h.each { |k,v| send("#{k}=", v) }
end
end
It's not as fast, but it will catch errors if you try to set
non-existent members, and it lets you use symbols and strings
interchangeably.
--
Posted via http://www.ruby-forum.com/.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.ruby
csiph-web