# Creating a "Foo has\_many bars" association where bar isn't a

**URL:** <https://www.ruby-forum.com/t/creating-a-foo-has-many-bars-association-where-bar-isnt-a/59958>\
**Category:** Rails\
**Created:** [May 8, 2006, 11:30pm UTC](https://www.ruby-forum.com/t/creating-a-foo-has-many-bars-association-where-bar-isnt-a/59958 "2006-05-08T23:30:32Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![alder](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/a4c791/32.png) [@alder](https://www.ruby-forum.com/u/alder)\
**Post date:** [May 8, 2006, 11:30pm UTC](https://www.ruby-forum.com/t/creating-a-foo-has-many-bars-association-where-bar-isnt-a/59958/1 "2006-05-08T23:30:32Z")

</div>

Hi

Let’s say we have model Foo. Each Foo instance can have several bars.  
Those bars are primitive, so they shouldn’t be models. For example,  
Foo might be a type of convention, and the bars might be years the  
convention was held in. Naively, we would have a conventions\_years  
date, and put:

has\_many :years

inside class Convention. But then we’d get an error, since for  
has\_many to work, there must be a Year model. Which is silly: why  
would we have a Year model, then get the actual year by Year#year…?

So what’s the Railish take on this? Can you have a has\_many  
association with the “many” as simple values, not full models? What  
did I miss?

-Alder

---

<div class="post-metadata">

**Author:** ![alder](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/a4c791/32.png) [@alder](https://www.ruby-forum.com/u/alder)\
**Post date:** [May 9, 2006, 12:16am UTC](https://www.ruby-forum.com/t/creating-a-foo-has-many-bars-association-where-bar-isnt-a/59958/2 "2006-05-09T00:16:58Z")

</div>

On May 8, 2006, at 2:29 PM, Alder G. wrote:

> would we have a Year model, then get the actual year by Year#year…?
> 
> So what’s the Railish take on this? Can you have a has\_many  
> association with the “many” as simple values, not full models? What  
> did I miss?

This is a case of persisting “values objects” rather than  
“entities.” (I like to think of the difference as “would I compare  
these by value or by id?”)

Active Record provides the composed\_of and serialize class methods to  
map columns to custom classes or to store them as YAML.

Using serialize:

# create table conventions (id serial primary key, years text);

class Convention  
serialize :years, Set  
end

foscon = Convention.new  
foscon.years \<\< 2005  
foscon.save!  
foscon[‘years’] == foscon.years.to\_yaml

Using composed\_of:

Currency = Struct.new(:code)

# create table markets (id serial primary key, currency\_code char

(3));  
class Market  
composed\_of :currency, :mapping =\> %w(currency\_code code)  
end

japan = Market.new(:currency =\> Currency.new(‘JPY’))  
japan.save!  
japan.currency\_code == ‘JPY’  
japan.currency == Currency.new(‘JPY’)

Active Record does not handle mappings such as:

# create table conventions (id serial primary key)

# create table conventions\_years (convention\_id not null primary

key references conventions(id), year)  
class Conventions  
# Returns a Set of 2001, 2002, etc.  
has\_many :years, :collection =\> Set, :value =\> ‘year’

```
 # However, you may:
 has_many :convention_years
 def years() convention_years.map { |y| y.year }.to_set end

```

end

Best,  
jeremy

---

<div class="post-metadata">

**Author:** ![alder](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/a4c791/32.png) [@alder](https://www.ruby-forum.com/u/alder)\
**Post date:** [May 9, 2006, 10:11am UTC](https://www.ruby-forum.com/t/creating-a-foo-has-many-bars-association-where-bar-isnt-a/59958/3 "2006-05-09T10:11:42Z")

</div>

On 5/9/06, Jeremy K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > has\_many to work, there must be a Year model. Which is silly: why  
> > Active Record provides the composed\_of and serialize class methods to  
> > foscon = Convention.new  
> > foscon.years \<\< 2005  
> > foscon.save!  
> > foscon[‘years’] == foscon.years.to\_yaml

Nice. A small problem here is that after

foscon = Convention.new

foscon.years is nil, so it doesn’t have the \<\< (or most any other)  
method. You can ammend this with

foscon.years = Set.new

but I’m sure there’s a more proper common practice?

> japan = Market.new(:currency =\> Currency.new(‘JPY’))  
> class Conventions  
> jeremy
> 
> * * *
> 
> Rails mailing list  
> removed\_email\_address@domain.invalid  
> [http://lists.rubyonrails.org/mailman/listinfo/rails](http://lists.rubyonrails.org/mailman/listinfo/rails)

The rest of your response acquainted me with a comprehensive set of  
tools relevant to the task. Thanks, Jeremy!

-Alder
