Learning how to build a Rails Application

For Phase 3 of Flatiron School, we had to build an application using Rails as backend. I think this was when I finally understood just how powerful Rails actually is. It really gives you a whole lot so you can actually focus on the application you are building on instead of thinking about the tiniest workings of your code.

I built a project that I like to call Space World where I seeded the data from an external API that NASA was quick enough to share with me. I am absolutely in love with space and will not miss the opportunity to work around it so I learn more and have fun while I am at it 😉. It looks something like this.

The main page of the application
picture showing index for all the posts listed that I seeded from NASA API.
Index page showing all posts

I used bootstrap 5 (I was familiar with materialize) this time for two reasons:
1) Wanted to get the hang of it;
2) It had real good documentation and a whole lot of variety;

Getting back to Rails, let me share a few things I found interesting while doing this project.

Rails follows MVC design pattern by convention which is a design pattern that divides the responsibilities of an application to make it easier to reason about.
It gets really easy to maneuver about while creating your application if you are familiar with this design pattern.

Models

First things first, you need to establish a proper relationship between your models. Remember, by establishing a carefully thought out relationship, you actually make things easier for yourself later on while going deeper into your application. This was where I struggled for the longest. I initially wanted a whole lot of functionality in my application for the user which made things so complicated for me that I had to end up cutting some of it and just think of the relationship between the following four models:

class Post < ApplicationRecordhas_many :replies, through: :comments
has_many :users, through: :comments
has_many :comments
end
class User < ApplicationRecordhas_many :replies
has_many :posts, through: :comment
has_many :comments
end
class Reply < ApplicationRecordbelongs_to :user
belongs_to :comment
accepts_nested_attributes_for :user
end
class Comment < ApplicationRecordbelongs_to :user
belongs_to :post
has_many :replies
end

I feel like drawing out your models and their relationships makes it easier to understand.

Red arrows depict has many through relationships, purple arrows depict has many and green arrows showcase belongs to relationships.

Phew that looks complicated but it’s actually not. What we are trying to achieve here is a connection between all our models that will help us later when we build nested forms.

For example: if you look at our Post model and think of the functionality you want to give it, then it gets obvious that it should have many replies and comments, this leaves out users, in my application I did not want users to create posts (since I was using an API to seed data) so I connected my users to the posts through comments.

Validations

Another interesting code you can add to your models is validations. The following methods trigger validations:
- create
- save
- update

Using this is a good way to get invalid data out of your application. A simple validation example is:

validates :username, presence: true

When an object is instantiated with .new, validations will not run, rails runs validations only when you .save the instantiated object and returns errors if there are any.
These validations can also be used to form error messages. A simple way to check this is to hop on to ‘rails console’ in your terminal and then instantiated a new object with .new and then .save, if it returns false, you can then call .errors.full_messages on it to read the validation errors caused. These same error messages can be used to in your views to display to the user.

Controllers

Some new things I learnt about controllers is the ability to add private methods to the class. For methods which are not intended as actions, it is best practice to add them to the private section in the controller.

Strong params is another method that gets added to the private methods. The need for strong params makes sure that the user can not create any other unnecessary attribute to the object. The syntax for strong params is something like this:

class PostsController < ApplicationControllerprivate   def post_params
params.require(:post).permit(
:date,
:title,
:explanation
)
end
end

Then it gets easier to just call on post_params when creating or updating an object.

You can also add filters to the controllers. One of the most common filter action is the ‘before_action’. This is mostly required when there is a need to make sure the user is logged in before doing a task. Filters basically halt the ongoing action and make sure a certain task is being done before going ahead.
Other filters that can be added are the “skip_before_action”, “after_action”, “around_action”.

Views

Coming to the views section, something new I learnt is to have as less code in your html.erb files, this is to be followed since most users can then have access to the code via developer tools and make the code vulnerable to manipulation.

Rails creates module helpers that can have code in it which can actually be called in your view files which can come in handy when you have to absolutely write ruby in your view files.

Views can interestingly also be refactored a lot through partials. For example, there usually are two erb files for an object; new.html.erb and edit.html.erb. Instead, in rails you can create a _form.html.erb and then render this form in your new.html.erb and edit.html.erb files by typing the following syntax;

views/posts/edit.html.erb<h1>Edit Form</h1><%= render partial: "form", locals: { post: @post, button_name: "Edit Post" } %>

Your _form.html.erb will have the actual form syntax. The same sort of partials can also be rendered while choosing a layout for your application.

Another interesting thing about rails is the ability to render collections, partials are very useful in rendering collections. When you pass a collection to a partial via the :collection option, the partial will be inserted once for each member in the collection:

<%= render @posts %>

Form_tag and Form_for
form_for prefers, as its first arg, an active record object; it allows to easily make a create or edit form, whereas form_tag is generally used for non-model forms and when we want to create a form that is not associated with a model for example, a query or search.

Devise

Devise is a flexible authentication solution for Rails based on Warden. It:

  • Is Rack based;
  • Is a complete MVC solution based on Rails engines;
  • Allows you to have multiple models signed in at the same time;
  • Is based on a modularity concept: use only what you really need.

Devise gives us many helpers like current_user, user_signed_in?, user_session. You will not need to actually make a user controller and add those manually which is pretty cool.

Through devise you can also add the extremely useful gem omniauth. This helps the user log in through an external website such as google, git hub, facebook, twitter which usually have better security. I used facebook for my application and there were many blogs on how to add it to your application such as the one below.

Overall Rails is pretty amazing and gives you a whole lot of macro so you don’t have to worry too much about manual coding. It’s pretty handy when you want to create larger applications with a lot of functionality. I had a lot of fun learning and practicing through my web application. But with rails, the more you dig deep, the more you realize how much you still don’t know. Isn’t that the fun part though? ;)

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store