Struct is cleverer than the documentation claims

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:

http://www.texperts.com/2007/09/03/hidden-feature-in-rubys-struct/

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!

Paul.

2007/9/4, Paul B. [email protected]:

So, both of the following achieve broadly the same effect:

end
end

Which leads to the question, what are the differences, and should I
prefer one approach over the other?

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

On Sep 4, 2007, at 5:01 AM, Paul B. wrote:

"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!

I too feel the block is better.

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 G. II

2007/9/4, Paul B. [email protected]:

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

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

On Tue, Sep 04, 2007 at 07:01:15PM +0900, Paul B. wrote:

end
Why not reopen the class?

Customer = Struct.new(:name, :address)
class Customer
  def to_s
    "Customer called '#{name}' living at '#{address}'"
  end
end

Paul

Robert K. 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

Daniel

On 9/4/07, Daniel DeLorme [email protected] wrote:

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

I too feel the block is better.

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.


Giles B.

Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org
Tumblelog: http://giles.tumblr.com/

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs