Create Your own blog: Ruby on Rails

Kristaps Dzērve-Štrāls
7 min readJul 24, 2018

--

For the second framework in my “Create a blog in ..” I’ve chosen to tackle Ruby on Rails (RoR). Same as with .NET Core, We’ll be just building the API that returns JSON formatted blog posts.

Step 1: The installation

Setting up RoR differs between operating systems. Since I’m working on a windows machine, I’ll be describing that setup. Here are some links for setup on Mac and Linux as well.

There are two simple ways to get started on a windows machine: RubyInstaller and RailsInstaller. While using RailsInstaller will setup everything you might need, I don’t recommend using that as the updates are less frequent and you might be stuck using an older version of Ruby and RoR. For this reason, I’ll go ahead with RubyInstaller. There’s a big, shiny red “Download” button on the front page there and if you follow up with that, You’ll see a lot of options, but We are only interested in the ones with DEVKIT included. To get the download file I used, follow this link.

Once the installer runs to the end, make sure that the checkbox to install MSYS is checked. After You click next, that will open up a terminal windows with that installation. If You just hit ENTER when prompted, the setup will install all the relevant native extensions.

NOW it is time to install Rails. Open up you favorite terminal (I use GIT Bash) and set up Rails Gem like so:

gem install Rails --version 5.2.0

That’s it! If you now run rails --version, you should see the relevant Rails version installed.

Step 2: The setup

Now we can start setting up the actual Rails app. We will want to use it without Views (as an API) and with PostgreSQL. Lucky for us, all of that can be passed in as command line arguments when creating the app:

rails new blog-app --api --database=postgresql

Now, if You don’t have PostgreSQL setup, I went over on how to do it in my previous article. To make sure that Rails knows how to connect to your database, open up config/database.yml file. Here, you can tell Rails what the relevant development and test databases should be called and what credentials should it use to connect.

development:
<<: *default
database: blog-rails_development
username: postgres
password: admin

test:
<<: *default
database: blog-rails_test
username: postgres
password: admin

Step 3: The models

So, here we are again. We’ll want to create a couple of models — for BlogPost and Author, as well as the BlogPost controller. Fortunately for us, Rails comes with a lot of helpful generators.

We’ll start by creating the Author model.

rails generate model Author name:string description:string

With that command, several files were created. What we are interested in is the db/migrate/<id>_create_authors.rb database migrations file and app/models/author.rb model file.

The migration defines the authors table with the two parameters and bind those auto-magically with our Authors model. If you now open the authors.rb file, you’ll notice that there are no properties there.

class Author < ApplicationRecord
end

Everything is managed by Active Record based on the fields in the corresponding table, as defined in the migration file:

class CreateAuthors < ActiveRecord::Migration[5.2]
def change
create_table :authors do |t|
t.string :name
t.string :description

t.timestamps
end
end
end

Similarly, we can create the BlogPost model by running the following command:

rails generate model BlogPost title:string summary:string body:string tags:string author:references

That will create another model and migration with the necessary fields. Note that author:references sets up the foreign-key relationship nicely and reflects that in the blog_post.rb model.

class BlogPost < ApplicationRecord
belongs_to :author
end

As for the migration, we need to modify that a little bit. There is unfortunately no way to tell the generator that we need an array of thing in the DB, but we can add that definition in the migration by hand. So change the line

t.string :tags

to include the array definition like so

t.string :tags, array: true, default: []

and the final <id>_create_blog_posts.rb migration looks like this

class CreateBlogPosts < ActiveRecord::Migration[5.2]
def change
create_table :blog_posts do |t|
t.string :title
t.string :summary
t.string :body
t.string :tags, array: true, default: []
t.references :author, foreign_key: true

t.timestamps
end
end
end

That COULD be it for the database setup, but for easier testing our API, we’ll add some seed data. Open up the db/seeds.rb file and add a new Author and BlogPost.

# This file should contain all the record creation needed to seed the database with its default values.
# The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup).
#
# Examples:
#
# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
# Character.create(name: 'Luke', movie: movies.first)

Author.destroy_all
BlogPost.destroy_all

sample_author = Author.create(
name: 'Kriss',
description: 'Hi, my name is Kristaps'
)

BlogPost.create(
title: 'Sample post',
summary: 'This is a sample seed post',
body: 'Lorem ipsum dolor amet sit...',
tags: ['sample', 'post'],
author: sample_author
)

puts "Created seed data"

With that done, the final command to run now is

rails db:setup

That command will load the database, initialize the schema and then seed it with seed data. Learn more about Active Record migrations here.

Step 4: The Controller

So now everything that’s left for us to be able to see the posts on the front end is a controller. And you can bet that there is a Rails generator for that as well.

rails generate controller BlogPosts

In our API project, that will create app/controllers/blog_posts_controller.rb and the corresponding test file. Currently the controller is empty, but we can add a quick index action to get all posts and a show action to get posts by id.

class BlogPostsController < ApplicationController

def index
@posts = BlogPost.all
render json: @posts
end

def show
@post = BlogPost.find_by(id: params[:id])
render json: @post
end

end

Notice, that to get the posts (or one post), all we have to do is query the model. As the model inherits from ApplicationRecord, it has all the necessary methods to query the database. BlogPost.all will return all records from the blog_posts table and similarly, BlogPost.find_by(id: params[:id]) will fetch the record where the id column value is the same as provided in the params of the route. And to return something to the browser, we just use the render method with a render type.

Now, this alone will not get us anywhere far as there are no routes set up in our application. To remedy that, open up the config/routes.rb file. We’ll add the routes such that they are the same as in the .NET Core tutoriallocalhost:port/api/posts etc.

Rails.application.routes.draw do
scope '/api' do
resources :posts, controller: 'blog_posts'
end
end

the scope defines what the prefix is and the resource name defines the actual route. If the resource name is the same as the controller, then there is no need to further specify the controller, but as our controller is called BlogPostsController not PostsController, then we must specify the controller in snake case (when in doubt, check the controller file name). Learn more about routing in Rails here.

Finally, we can start the rails server rails s and visit localhost:3000/api/posts to see the JSON data returned.

Congratulations! You have successfully created your own Rails API!

To quickly add the remaining CRUD actions to the controller you should use def create, def update and def destroy. These actions require params to come in from the browser. So let’s set up these params to be private and only contain things that we have defined in our model:

private
def post_params
params.require(:blog_post).permit(:title, :summary,
:body, :tags, :author)
end

Now we can use those post_params in both our create and update methods. The final BlogPost controller looks something like this:

class BlogPostsController < ApplicationController

def index
@posts = BlogPost.all
render json: @posts
end

def show
@post = BlogPost.find_by(id: params[:id])
render json: @post
end

def create
puts params[:title]
@post = BlogPost.new(post_params)
if @post
@post.save
end
end


def update
@post = BlogPost.find_by(id: params[:id])
if @post
@post.update(post_params)
end
end

def destroy
@post = BlogPost.find_by(id: params[:id])
if @post
@post.destroy
end
end

private
def post_params
params.require(:blog_post).permit(:title, :summary, :body, :tags, :author)
end

end

Step 4: Future work

This is the beginning of a good blog API. But as always, feel free to change the fields to fit your needs. Create another controller for the Author model. Maybe try adding a Comment model/controller that references a single blog post!

The point is, there is much more to learn and the world is your oyster! Make sure to check out the awesome Rails tutorials and keep on hacking!

Also, follow future posts in this series here to be notified when the next API is ready (Django is up next) and when we can start tackling some front-end stuff for our blog!

See You next time!

--

--

Kristaps Dzērve-Štrāls

Software developer and Tech enthusiast looking to expand and share knowledge.