"Hal Fulton" <hal9000 / hypermetrics.com> schrieb im Newsbeitrag
news:411AE8D6.8060607 / hypermetrics.com...
> Hello, all...
>
> I ran across an interesting bit of behavior, and I'm not sure I
> understand why it happens.
>
> Here's the background. I have a SuperStruct class which I use frequently
> (though I hope to find a better name for it). See the snippet on
> rubyforge: http://rubyforge.org/snippet/detail.php?type=snippet&id=25
>
> So. If you call SuperStruct.new, you get a class that is much like
> a Struct; if you call SuperStruct.open instead, you get a class that
> is more like an OpenStruct.
>
> That is, in the latter case, if you reference a nonexistent attribute,
> it will spring into existence:
>
>    klass = SuperStruct.open(:alpha)  # Create with attr "alpha"
>    foo = klass.new
>    x = foo.beta      # nil
>    foo.gamma = 5     # 5
>
> In fact, when you referenced the getter OR the setter... then the getter
> AND the setter would be defined. Make sense so far?
>
> But this leads to an oddity...
>
>    foo.delta ||= 7              # gives an error!
>    foo.delta = foo.delta || 7   # I think this also gives an error
>
> I had to fix this by saying: When the getter or setter is referenced,
> define ONLY that method. I don't quite like this; but oh, well.
>
> But puzzling out why it works this way has given me a headache.
>
> What do you think?

I think it doesn't happen with OpenStruct:

>> foo = OpenStruct.new
=> <OpenStruct>
>> foo.alpha = nil
=> nil
>> foo
=> <OpenStruct alpha=nil>
>> foo.delta ||= 7
=> 7
>> foo
=> <OpenStruct delta=7 alpha=nil>
>>

Personally I'd implement SuperStruct like this:

require 'ostruct'
class SuperStruct
  def self.new(*attrs)
    Struct.new( *attrs ).new
  end

  def self.open(*attrs)
    st = OpenStruct.new
    attrs.each {|at| st.send( "#{at}=", nil) }
    st
  end
end

>> x = SuperStruct.new :foo
=> #<struct #<Class:0x10187710> foo=nil>
>> y = SuperStruct.open :foo
=> <OpenStruct foo=nil>

But apparently you're adding more magic, so that's probably not a solution
for you.

Kind regards

    robert