# Struct is cleverer than the documentation claims

**URL:** <https://www.ruby-forum.com/t/struct-is-cleverer-than-the-documentation-claims/113729>\
**Category:** Ruby\
**Created:** [September 4, 2007, 12:00pm UTC](https://www.ruby-forum.com/t/struct-is-cleverer-than-the-documentation-claims/113729 "2007-09-04T12:00:05Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![paulbutcher](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@paulbutcher](https://www.ruby-forum.com/u/paulbutcher)\
**Post date:** [September 4, 2007, 12:00pm UTC](https://www.ruby-forum.com/t/struct-is-cleverer-than-the-documentation-claims/113729/1 "2007-09-04T12:00:05Z")

</div>

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:

> **[钛刻专家——官网](https://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.

---

<div class="post-metadata">

**Author:** ![paulbutcher](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@paulbutcher](https://www.ruby-forum.com/u/paulbutcher)\
**Post date:** [September 4, 2007, 12:58pm UTC](https://www.ruby-forum.com/t/struct-is-cleverer-than-the-documentation-claims/113729/2 "2007-09-04T12:58:43Z")

</div>

2007/9/4, Paul B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> 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

---

<div class="post-metadata">

**Author:** ![paulbutcher](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@paulbutcher](https://www.ruby-forum.com/u/paulbutcher)\
**Post date:** [September 4, 2007, 2:14pm UTC](https://www.ruby-forum.com/t/struct-is-cleverer-than-the-documentation-claims/113729/3 "2007-09-04T14:14:57Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![paulbutcher](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@paulbutcher](https://www.ruby-forum.com/u/paulbutcher)\
**Post date:** [September 4, 2007, 3:41pm UTC](https://www.ruby-forum.com/t/struct-is-cleverer-than-the-documentation-claims/113729/4 "2007-09-04T15:41:23Z")

</div>

2007/9/4, Paul B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

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

---

<div class="post-metadata">

**Author:** ![paulbutcher](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@paulbutcher](https://www.ruby-forum.com/u/paulbutcher)\
**Post date:** [September 4, 2007, 3:32pm UTC](https://www.ruby-forum.com/t/struct-is-cleverer-than-the-documentation-claims/113729/5 "2007-09-04T15:32:19Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![paulbutcher](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@paulbutcher](https://www.ruby-forum.com/u/paulbutcher)\
**Post date:** [September 5, 2007, 12:49am UTC](https://www.ruby-forum.com/t/struct-is-cleverer-than-the-documentation-claims/113729/6 "2007-09-05T00:49:48Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![paulbutcher](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@paulbutcher](https://www.ruby-forum.com/u/paulbutcher)\
**Post date:** [September 5, 2007, 12:58am UTC](https://www.ruby-forum.com/t/struct-is-cleverer-than-the-documentation-claims/113729/7 "2007-09-05T00:58:49Z")

</div>

On 9/4/07, Daniel DeLorme [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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

---

<div class="post-metadata">

**Author:** ![paulbutcher](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@paulbutcher](https://www.ruby-forum.com/u/paulbutcher)\
**Post date:** [September 5, 2007, 1:10am UTC](https://www.ruby-forum.com/t/struct-is-cleverer-than-the-documentation-claims/113729/8 "2007-09-05T01:10:50Z")

</div>

> 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](http://gilesbowkett.blogspot.com)  
Portfolio: [http://www.gilesgoatboy.org](http://www.gilesgoatboy.org)  
Tumblelog: [http://giles.tumblr.com/](http://giles.tumblr.com/)
