Rails foundationSort Order

Rails: Many to Many Relationships

In this episode we take a look at many to many relationships in rails. These can come in handy when you want to connect many of one kind of object to many of another kind of object. A good example is tags. Each tag in your site may be linked to many posts and at the same time each of the posts in your site can have many tags.

Let's begin by generating our tag model

rails g model tag name:string

We should now see the tag.rb model in our application with the following content

class Tag < ActiveRecord::Baseend

To creat a many to many relationship we also need a join table that will track the reference between both the Post and the Tag to generate the join model we will use the following command.

rails g model tagging post:references tag:references

We will get the Tagging model in our app.

class Tagging < ActiveRecord::Base  belongs_to :post  belongs_to :tagend

We also get a migration file for the join model that looks like this

class CreateTaggings < ActiveRecord::Migration  def change    create_table :taggings do |t|      t.references :post, index: true, foreign_key: true      t.references :tag, index: true, foreign_key: true            t.timestamps null: false    end  endend

We need to finish off the relationship setup by filling out our Tag Model with

class Tag < ActiveRecord::Base  has_many :taggings  has_many :posts, through: :taggingsend

Now for the Post model

class Post < ActiveRecord::Base  # ...    has_many :taggings  has_many :tags, through: :taggingsend

The last step in our setup would be to simply run rake db:migrate or if you are using Rails 5 and a bove you can use rails db:migrate

Let's hop into rails c

post = Post.firsttag = Tag.create(name: "Ruby")# To assign the tag to the post we can simply dopost.tags = [tag]post.save# We can see the tags assigned to a post by callingpost.tags

If we re-assign the post.tags it will replace the old relationship in the database automatically, for example.

new_tag = Tag.create(name: "Some Other Tag")post.tags = [new_tag]post.save

The example above will remove the previous tag from this post. We can append more tag instead but we have to change the operator

ruby_tag = Tag.where(name: "Ruby").firstpost.tags += [ruby_tag]# We should now see both tagspost.tags

Rendering out the Tags

Now let's render out the tags for the post

# app/views/posts/_post.html.erb<%= div_for post, class: 'col-md-8 col-md-offset-2' do %># ...  <ul>    <% post.tags.each do |tag| %>      <li>        <%= tag.name %>      </li>    <% end %>  </ul><% end >