Theory of Coding

Web Development blog

Associations

Active Record and Associations with Sinatra

Sinatra

Sinatra is a domain specific language that wraps HTTP requests and responses on top of Rack. Sinatra is similar to Ruby; they are both web frameworks. Sinatra is used for smaller web applications.

When you want to build something, like say a web application where a user can submit a blog post, ActiveRecord is a great framework to use to keep track of databases and their data, and also their associations.

Here is a sample migration for creating the posts table. author_id is the association of the posts to the author.

1
2
3
4
5
6
7
8
9
class CreatePosts < ActiveRecord::Migration
  def change
    create_table :posts do |t|
      t.string :title
      t.text :content
      t.integer :author_id
    end
  end
end

Eventually you will have a database that will look something like these charts, filled with seed data.

Posts Table

id title Content Author_id
1 “cats” “meow meow” 1
2 “dogs” “woof woof” 2

Author table

id author
1 “Mr Kitty”
2 “Mr Puppy”

Tags Table

id tag
1 cats
2 dogs
3 parks

Post_tags table —> needed because posts has many tags, and tags has many posts, so there must be a join table created to satisfy those requirements. It is not simply just a table that either has_many or belongs_to anymore.

id post_id tag_id
1 1 1
2 2 2
3 2 3

So here, the first blog post called “cats” will have the tags cats. But for the second blog post called “dogs” it will have the tags dogs, and also parks.

Now here are the models

1
2
3
4
5
class Posts < ActiveRecord::Base
  belongs_to :author
  has_many :post_tags
  has_many :tags, through: :post_tags
end

because the posts table has “author_id”, which means that posts belongs to an author, and an author will have many posts. Also, you must write “has_many” “:post_tags” so you can mention the join table before mentioning that posts “has_many” tags through the join table.

1
2
3
class Author < ActiveRecord::Base
  has_many :posts
end
1
2
3
class Tags < ActiveRecord::Base
  has_many :posts
end
1
2
3
4
class PostTags < ActiveRecord::Base
 belongs_to :post
 belongs_to :tag
end
1
2
3
4
class Tag < ActiveRecord::Base
  has_many :post_tags
  has_many :posts, :through => :post_tags
end

Some tips:

When writing belongs_to for a class, whatever it belongs to will typically have “has_many”.

eg. class Author “has_many” posts, while Posts “belong_to” Author

When associating with join tables, mention the join table, and then write “has_many” something through the join table in the next line. eg. Like so in “class Posts” above.

Provided that you have seed data, and that you want to associate a post with an author, you can first think about the author as the parent, and posts as the child (because posts belongs to an author, and an author has many posts.)

1
2
3
4
5
6
# In a console, possibly in pry, 
author = Author.find(1) #=>in Author class, find the author with id 1. Now author is set to the Author object with id 1.
post = Post.find(2) #=>in Post class, find the post with id 2 and set it to the variable post.
author.posts #=> []  this gives you an empty array right now.
author.posts << post  #=> shovel in the post with #2 to the author.posts array
author.posts #=>Now will include the Post object of id 2.

When associating with Sinatra, if the model of is associated with another model, you can write that association inside the Controller. If there was a blog controller with Sinatra:

1
2
3
4
5
6
7
8
9
10
11
class BlogController < ApplicationController
  get '/' do
    @blogs = Blog.all
    erb: :'/blogs/index'
  end

  get '/blog/new' do
    @authors = Author.all
    erb: :'blogs/new'
  end
end

In the blogs controller, if you wanted to create a new blog post and went to the form to input the new blog post data, you can also asisgn it to an author, to have an author association too. As long as you associated with authors in the post model, you can access it.