Detailed understanding of rails. How it works
What is Ruby on Rails
It’s most popular server-side web application framework ( written in Ruby ) to build web applications. Build from simple to complex applications, there is no limits to what you can accomplish using Rails!. Ruby on Rails as framework it has collection of code, tools & utilities that give you a specific structure to work with when you’re writing software. Rails makes it much easier and more fun. It’s a open source and opinionated software.
Rails philosophy - two major principles
1. DRY - Don’t Repeat Yourself means not writing the same information over and over again, so that our code becomes more maintainable, more extensible, and less buggy.
2. Convention Over Configuration - It provides a default way of doing things. It’s is opinionated gives you everything you need to create a web application and follows all the best practices. you’ll be more productive & gets things done faster.
MVC Architecture
Rails uses MVC architecture. MVC stands for Model, View, Controller. It separates an application’s data, user interface, and control logic to a whole new level and also Improves scalability, ease of maintenance, reusability
MVC - Model, View, Controller and Rails App Structure
General flow of Rails application:
-> Request made at browser
-> Request received at router of rails application
-> Request routed to appropriate action in a controller
-> Controller#action either renders a view template or communicates with model
-> Model communicates with database
-> Model sends back information to controller
-> Controller renders view
CRUD
CRUD refers to Create, Read, Update and Delete.
- Create - Create a brand new entity.
- READ - Read something from the database
- Update - Change values of an already existing entity.
- Delete - Delete an entity from the database.
Scaffold Generators
Scaffold generator command creates entire CRUD operation for you. for example: if we want to create articles with two attributes. It creates articles model (with two attributes), articles controller, views for articles and migration file to create articles table:
1rails generate scaffold Article title:string description:text
Command to see routes presented in a viewer-friendly way:
1rails routes --expanded
The line resources :articles in the config/routes.rb file provides the following routes:
index of articles (GET request)
new article (GET)
create article (POST)
edit article (GET)
update article (PUT and PATCH)
show article (GET)
delete article (DELETE)
From UI perspective ->
index lists all the articles in the articles table in the database of the app
new article deals with the form to enter in new article details
create handles the submission of the items in the new article form
edit article deals with the form to enter edited information for an existing article
update article deals with the submission of the edit article form
show article displays an individual article based on selection
delete article deletes an article from the articles table
Work Flow under the hood
Routing:
To set a route, navigate to config/routes.rb file. Let’s make route for “/articles” in the app which renders all articles
1get "/articles" => "articles#index"
Model :
Model communicates to database. All DB related code goes into model folder.
In Rails app, model part is Active Record class. In Rails Models are stored in app/models. Rails encourages us to have model names as singular noun.
In above example for articles model
Model name: article
Class name: Article -> Capitalized A and singular, CamelCase
File name: article.rb -> singular and all lowercase, snake_case
Creating the Article model
1rails generate model Article title:string description:text
With that command we told Rails that we want an Article model, together with a title attribute of type string, and a description attribute of type text. Those attributes are automatically added to the articles table in the database and mapped to the Article model.
Migrations
Migrations are Ruby classes that are designed to make it simple to create and modify database tables. As we’ve just seen, rails generate model created a database migration file inside the db/migrate directory.
Rails provide generators to generate migration
example: let’s generate migration for creating articles.
1rails generate migration create_articles title:string description:text
Example of a generated migration file.
1class CreateArticles < ActiveRecord::Migration2 def change3 create_table :articles do |t|4 t.string :title5 t.text :description67 t.timestamps8 end9 end10end
Active Record automatically adds timestamps. so that table has fields named created_at and updated_at.
To run the migration file, run the following command from the terminal:
1rails db:migrate
The first time you run the migration file, it will create the database, the articles table and a schema.rb file.
To rollback or undo the changes made by the last migration file that was run, you may use the following command:
1rails db:rollback
If you have run the rollback step, then you can update the previous migration file. Just remove t.timestamps from it. so that we will add them later
To run the newly edited migration file again, you can run
1rails db:migrate
Note: This above line will only work if you had rolled back the prior migration.
To generate a new migration file to add or make changes to your articles table you can generate a new file:
1rails generate migration name_of_migration_file
Then within the def change method in the migration file you can add the things you need.
1add_column :articles, :created_at, :datetime2add_column :articles, :updated_at, :datetime
You can run the newly created migrations file by running rails db:migrate from the command line and check out the schema.rb file to check that the changes were reflected properly.
Rails Console
The console command lets you interact with your Rails application from the command line. On the underside, rails console uses IRB, so if you’ve ever used it, you’ll be right at home. This is useful for testing out quick ideas with code and changing data server-side without touching the website.
Command to run the console is
1rails console
or shortcut for the above command use
1rails c
You can test out your connection to the articles table by typing the following command from within your rails console:
1Article.all
If you get an empty collection/array-like structure as a response, you’re good to go.
To create a new article, you can use any of the following methods:
1Article.create(title: "first article", description: "Description of first article")
or
1article = Article.new2article.title = "second article"3article.description = "description of second article"4article.save
or
1article = Article.new(title: "third article", description: "description of third article")2article.save
To check all the articles that exist in your articles table, you can use the following command:
1Article.all
Reloading console
1reload!
Once in the console, you can exit it at any time by typing in
1exit
followed by enter/return.
Validations
Validations enforce constraints on your model so you can have greater control on what you are allowing as data to be saved in your database/tables.
1class Ariticle < ApplicationRecord2validates :title, presence: true, length: { minimum: 6, maximum: 100 }3validates :description, presence: true, length: { minimum: 10, maximum: 300 }4end
Controllers
The controller handles the application logic of your program, acts between the application’s data, the view, and the web browser. In this role, a controller performs a number of tasks including:
- deciding how to handle a particular request (for example, whether to render a full page or just one part of it)
- retrieving data from the model to be passed to the view
- gathering information from a browser request and using it to create or update data in the model
In Rails app, controller part is Action Controller class.
Controller (ruby class) inherits from ApplicationController, and has methods called actions, like new, create, update, and destroy.
Every Rails application comes with an ApplicationController (which lives in app/controllers/application_controller.rb) that inherits from ActionController::Base. All our controllers will inherit from the ApplicationController,
In our application, to list all Articles on the /articles page
1class ArticlesController < ApplicationController2 def index3 @articles = Article.all4 end5end
generator command to generate controller
1rails generate controller Articles
Parameters
To access data sent by user or other parameters in controller actions we use params hash (objects are called hash in ruby). Rails provide all that data to us in params hash.
Strong Parameters
We don’t want our users to be able to modify all values in params hash. So, strong parameter forbids the modification of params hash by user, until it is permitted. We can permit only specific data to be changed in params hash. Of course this is all because of security reasons.
1def person_params2 params.require(:person).permit(:name, :age)3end
Private Methods
Private methods can only be used within the class definition. Think of it as internal helper method. Also it can be used to keep some info secure and private.
Strong parameter is defined as private method.
Session
Rails application has a session for each user where we can store small amount of data that will be persisted between requests. Session is only available in controller.
Rails will not allow you to pass the session ID in the URL as this is less secure. You must use cookie, All session stores use a cookie to store a unique ID for each session.
1class SessionsController < ApplicationController2 # Create a session when user logs in3 def create4 if user = User.authenticate(params[:username, params[:password]])5 session[:current_user_id] = user.id6 redirect_to root_url7 end8end
View
View is the part responsible for whatever is seen on the browser. By default rails uses embedded Ruby (erb) for views. But we can change that, for example we can use React JS as view part.
Just like how HTML is combined into Elements, Tags, and Attributes. ERB is composition of three Rails elements namely Templates, Partials(to break and manage code into manageable chunks), Layouts.
This convention may sound complicated, but it’s actually quite intuitive. For example, consider the StoriesController class defined earlier. Invoking the show method for this controller would, by default, attempt to display the ActionView template that lived in the app/views/stories directory. Assuming the page was a standard HTML page (containing some ERb code), the name of this template would be show.html.erb.
Testing
Rails makes it super easy to write your tests. It starts by producing skeleton test code while you are creating your models and controllers.
By running your Rails tests you can ensure your code adheres to the desired functionality even after some major code refactoring.
Testing support was woven into the Rails fabric from the beginning. It wasn’t an “oh! let’s bolt on support for running tests because they’re new and cool” epiphany.
Their are mainly 3 types of test:
- Unit Test (Model Test) - Tests individual units of app, checks for validations like presence, length, uniqueness, validity.
- Functional Test (Controller Test) - Checks if a function is working for ex - before_action. Checks for presence of routes and accessibility of actions.
- Integration Test - Test an entire feature from start to finish. ex - A user signup for app.
Here we will only discuss basics of Unit Testing (Model testing), rest you can learn in detail from here.
Their are mainly 3 types of test:
- Unit Test (Model Test) - Tests individual units of app, checks for validations like presence, length, uniqueness, validity.
- Functional Test (Controller Test) - Checks if a function is working for ex - before_action. Checks for presence of routes and accessibility of actions.
- Integration Test - Test an entire feature from start to finish. ex - A user signup for app.
Here we will only discuss basics of Unit Testing (Model testing), rest you can learn in detail from here.
Validations by Unit testing
Created category_test test file and wrote a test to check for the validity of a newly created category object
1require "test_helper"2class CategoryTest < ActiveSupport::TestCase3 def setup4 @category = Category.new(name: "sports")5 end67 test "category should be valid" do8 assert @category.valid?9 end1011 test "name should be valid" do12 @category.name = " "13 assert_not @category.valid?14 end1516 test "name should be unique" do17 @category.save18 category2 = Category.new(name: "sports")1920 assert_not category2.valid?21 end2223 test "name should not be too long" do24 @category.name = "mynameisswastikyadav"25 assert_not @category.valid?26 end2728 test "name should not be too short" do29 @category.name = "hi"30 assert_not @category.valid?31 end32end
assert - Ensures that test is true.
assert_not - Ensures that test is false.
Rails adds some custom assertions of its own to the minitest framework
By now you’ve caught a glimpse of some of the assertions that are available. Assertions are the worker bees of testing. They are the ones that actually perform the checks to ensure that things are going as planned.
Check all avaible assertions here
I hope above document helps in better understanding of basic work flow. Thank You