# Model Relations

**URL:** <https://www.ruby-forum.com/t/model-relations/165232>\
**Category:** Rails\
**Created:** [April 10, 2009, 1:22pm UTC](https://www.ruby-forum.com/t/model-relations/165232 "2009-04-10T13:22:40Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![ephracis](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/59ef9b/32.png) [@ephracis](https://www.ruby-forum.com/u/ephracis)\
**Post date:** [April 10, 2009, 1:22pm UTC](https://www.ruby-forum.com/t/model-relations/165232/1 "2009-04-10T13:22:40Z")

</div>

Hi,

I am creating my databases and models and I need to use some  
relationships. I am very new at this so any help or info at all would be  
great. 🙂

The concept is:  
There are three resources: people, items and tags.

- An item belongs to one person, the creator.
- A person can create many items.
- An item can have many tags.
- A tag can be used on many items.

Here my models:

* * *

/\* models/item.rb \*/  
class Item \< ActiveRecord::Base  
belongs\_to :person  
has\_many :tags  
end

* * *

/\* models/person.rb \*/  
class Person \< ActiveRecord::Base  
has\_many :items  
end

* * *

/\* models/tag.rb _/  
class Tag \< ActiveRecord::Base  
/_ should I use ‘has\_and\_belongs\_to\_many’ here? \*/  
end

Here’s the migrations:

* * *

/\* db/migrate/1\_create\_items.rb _/  
class CreateItems \< ActiveRecord::Migration  
def self.up  
create\_table :items do |t|  
t.string :name  
t.belongs\_to :person  
/_ what should I put here to create a relation to tags? \*/  
end  
end

def self.down  
drop\_table :items  
end  
end

* * *

/\* db/migrate/2\_create\_people.rb _/  
class CreatePeople \< ActiveRecord::Migration  
def self.up  
create\_table :people do |t|  
t.string :name  
/_ do I need something here to create a relation to items? \*/  
end  
end

def self.down  
drop\_table :people  
end  
end

* * *

/\* db/migrate/3\_create\_tags.rb _/  
class CreateTags \< ActiveRecord::Migration  
def self.up  
create\_table :tags do |t|  
t.string :name  
/_ what should I put here to create a relation to items? \*/  
end  
end

def self.down  
drop\_table :tags  
end  
end

---

<div class="post-metadata">

**Author:** ![ephracis](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/59ef9b/32.png) [@ephracis](https://www.ruby-forum.com/u/ephracis)\
**Post date:** [April 10, 2009, 2:31pm UTC](https://www.ruby-forum.com/t/model-relations/165232/2 "2009-04-10T14:31:49Z")

</div>

On Apr 10, 12:22 pm, Christoffer Brodd-reijer \<rails-mailing-  
removed\_email\_address@domain.invalid\> wrote:

> end  
> You could use has and belongs to many or has many through. Either way  
> you will need another table (the join table for the relationship  
> between tags and items), the existing tables are fine as is.  
> You might find [Active Record Associations — Ruby on Rails Guides](http://guides.rubyonrails.org/association_basics.html)  
> helpful.

Fred

---

<div class="post-metadata">

**Author:** ![ephracis](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/59ef9b/32.png) [@ephracis](https://www.ruby-forum.com/u/ephracis)\
**Post date:** [April 10, 2009, 5:24pm UTC](https://www.ruby-forum.com/t/model-relations/165232/3 "2009-04-10T17:24:26Z")

</div>

Frederick C. wrote:

> On Apr 10, 12:22ï¿½pm, Christoffer Brodd-reijer \<rails-mailing-  
> removed\_email\_address@domain.invalid\> wrote:
> 
> > end  
> > You could use has and belongs to many or has many through. Either way  
> > you will need another table (the join table for the relationship  
> > between tags and items), the existing tables are fine as is.  
> > You might find [Active Record Associations — Ruby on Rails Guides](http://guides.rubyonrails.org/association_basics.html)  
> > helpful.
> 
> Fred

I went with using a joint table

* * *

/\* db/migrate/3\_create\_tags.rb \*/  
…  
create\_table :item\_tags, :id =\> false do |t|  
t.integer :tag  
t.integer :item  
end  
…

Now I am coding the controller that creates the item. I am iterating  
through each tag that the user typed in and I want this to happen:

- Create a new tag in the ‘tags’ table if it does not already exists
- Associate the tag and item by adding the pair to the ‘item\_tags’ table

The idea here is that each tag should be only once in the tags table.  
Here’s the controller function so far:

* * *

/\* controllers/items\_controller.rb \*/  
def create  
for tag in tags.split(’ ')  
match = Tag.find(:first, :conditions =\> “name = ‘#{tag}’”)  
unless match  
Tag.create(:name =\> tag)  
end

```
/* make association here */

```

end  
end

Problem is, I don’t know how to add the association in the controller.  
Also, am I doing the rest of the stuff right? Or maybe Rails can  
automate this whole process somehow? Thanks,

---

<div class="post-metadata">

**Author:** ![ephracis](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/59ef9b/32.png) [@ephracis](https://www.ruby-forum.com/u/ephracis)\
**Post date:** [April 11, 2009, 8:29pm UTC](https://www.ruby-forum.com/t/model-relations/165232/4 "2009-04-11T20:29:51Z")

</div>

You can shorten this part up by using Tag.find\_or\_create\_by\_name, one  
of the dynamic finder methods.  
And I’d add a generic warning to NEVER use #{} interpolation directly  
in anything you’re feeding to an AR conditions parameter, unless you  
want to relearn the lesson of little Bobby Tables…

The final code will look something like:

def create  
# find item, put in @item  
@item.tags = params[:tags].split(’ ').map do |tag|  
Tag.find\_or\_create\_by\_name(tag)  
end  
# do whatever else  
end

Alternatively, you could encapsulate this behavior in the Item model,  
using a virtual tags\_attr or the like to do the parsing. I’d recommend  
that you take a look at some of the approaches taken by  
acts\_as\_taggable and it’s descendants.

–Matt J.

On Apr 10, 11:24 am, Christoffer Brodd-reijer \<rails-mailing-
