The Pickaxe book asserts that it will be possible to pass a block to
Struct.new in Ruby 1.9. While spelunking the code, I discovered that the
functionality has actually been present since 1.8.3. I've blogged about
this here:
But reading this mailing list, I notice that there's another way to
achieve a similar effect, specifically deriving from Struct.new.
So, both of the following achieve broadly the same effect:
Customer = Struct.new(:name, :address) do
def to_s
"Customer called '#{name}' living at '#{address}'"
end
end
class Customer < Struct.new(:name, :address)
def to_s
"Customer called '#{name}' living at '#{address}'"
end
end
Which leads to the question, what *are* the differences, and should I
prefer one approach over the other?
Thanks in advance for any light you can cast on this!
Well, difference is that you get two classes vs. one class. I
frequently use the first idiom because I do not see the point in
creating two classes for this scenario. IMHO a base class makes sense
only if you want to inherit multiple times or separate concerns.
Neither is the case here.
Kind regards
robert
···
2007/9/4, Paul Butcher <paul@82ask.com>:
The Pickaxe book asserts that it will be possible to pass a block to
Struct.new in Ruby 1.9. While spelunking the code, I discovered that the
functionality has actually been present since 1.8.3. I've blogged about
this here:
You can occasionally run into issues with the base class form. For example, when Rails does it's reloading magic on a file containing such a construct you will receive an error.
James Edward Gray II
···
On Sep 4, 2007, at 5:01 AM, Paul Butcher wrote:
So, both of the following achieve broadly the same effect:
Customer = Struct.new(:name, :address) do
def to_s
"Customer called '#{name}' living at '#{address}'"
end
end
class Customer < Struct.new(:name, :address)
def to_s
"Customer called '#{name}' living at '#{address}'"
end
end
Which leads to the question, what *are* the differences, and should I
prefer one approach over the other?
Thanks in advance for any light you can cast on this!
Why should I reopen a class if I can have everything with the block?
Customer = Struct.new :name, :address do
def to_s
"Customer called '#{name}' living at '#{address}'"
end
end
Kind regards
robert
···
2007/9/4, Paul Brannan <pbrannan@atdesk.com>:
On Tue, Sep 04, 2007 at 07:01:15PM +0900, Paul Butcher wrote:
> > Customer = Struct.new(:name, :address) do
> > def to_s
> > "Customer called '#{name}' living at '#{address}'"
> > end
> > end
>
> > class Customer < Struct.new(:name, :address)
> > def to_s
> > "Customer called '#{name}' living at '#{address}'"
> > end
> > end
Why not reopen the class?
Customer = Struct.new(:name, :address)
class Customer
def to_s
"Customer called '#{name}' living at '#{address}'"
end
end
You can occasionally run into issues with the base class form. For
example, when Rails does it's reloading magic on a file containing
such a construct you will receive an error.
I have some code in a Rails app which depends on a class derived from
Struct. I basically used that to create a presenter. I just switched
that class to a block form - I'd been using the class form - and the
unit tests all went nuts. Rails *thought* that its standard
expectation, that file xyz.rb will define Xyz, was violated. I got
"expected xyz.rb to define Xyz" errors, even though xyz.rb really
*did* define Xyz. So it kind of seems like a damned if you do, damned
if you don't here, with Structs and Rails.
Why should I reopen a class if I can have everything with the block?
Customer = Struct.new :name, :address do
def to_s
"Customer called '#{name}' living at '#{address}'"
end
end
because, say, you'd want to add a constant to that class
Customer = Struct.new :name, :address do
K = 42
end
Customer::K
(irb):7: warning: toplevel constant K referenced by Customer::K
Robert Klemme wrote:
> Why should I reopen a class if I can have everything with the block?
>
> Customer = Struct.new :name, :address do
> def to_s
> "Customer called '#{name}' living at '#{address}'"
> end
> end
because, say, you'd want to add a constant to that class
Customer = Struct.new :name, :address do
K = 42
end
Customer::K
(irb):7: warning: toplevel constant K referenced by Customer::K
This is workaroundable, if a bit ugly as I recently learned:
Customer = Struct.new :name, :address do
self::K = 42
end
Customer::K
···
On 9/4/07, Daniel DeLorme <dan-ml@dan42.com> wrote: