Category: Ruby on Rails

  • Cookies and Session

    The Ruby on Rails framework follows the MVC pattern that implements REST architecture. One of the important constraints of REST is statelessness. It implies that each request sent by the client must have enough information for the server to handle and satisfy it, and that the server doesn’t hold on to the request data once it forms the response and disconnects from the client.

    What are Cookies?

    In some situations web applications need to maintain state between multiple requests. When a user successfully logs in, they shouldn’t be asked to log in again when accessing another resource. Rails (in general the applications implementing REST) uses cookies to store data between multiple requests.

    Cookies are small pieces of data stored in the user’s browser. Rails allows you to set, read, and delete cookies. The cookies method in Rails acts as a hash.

    To set a cookie −

    cookies[:username]={ value:"Test User", expires:1.hour.from_now }

    To return the cookie value −

    cookies[:username]

    in this case Test User.

    To delete a cookie, use the following expression:

    cookies.delete(:username)

    What are Sessions?

    Sessions are a wrapper over cookies. Rails encrypts and signs to store more sensitive user-related data securely. Rails stores session data in a cookie by default using ActionDispatch::Session::CookieStore.

    Setting session data −

    session[:user_id][email protected]
    

    Reading session data −

    User.find(session[:user_id])if session[:user_id]

    Deleting session data −

    session.delete(:user_id)

    Flash Messages

    Flash messages in Rails are built on top of the session object. They are used to pass temporary one-time messages (like success or error alerts) from one request to the next.

    Rails provides a flash hash that’s stored in the session. Flash uses the session behind the scenes −

    • It stores the flash hash in session[‘flash’].
    • On the next request, Rails clears the flash data automatically (unless told otherwise).

    You can render the following types of flash messages −

    Flash KeyPurposeDisplay Color
    :noticeFor general success messagesGreen or Blue
    :alertFor warnings or errorsRed
    :errorCustom — often for errorsRed
    :successCustom — for clear successGreen

    Examples −

    flash[:notice]="Successfully logged in"
    flash[:alert]="Invalid username or password"
    flash[:error]="Something went wrong!"
    flash[:success]="Your profile has been updated"

    Example: Cookies, Sessions, and Flash Messages

    Let us put the concept of cookies, session and flash in the following example.

    Start by creating a new Rails application −

    rails new sessiondemo 
    cd sessiondemo
    

    Add a User model and corresponding controller and views by generating the scaffold.

    rails generate scaffold User name:string email:string password:string
    rails db:migrate

    You need to create a Sessions Controller for handling Login/Logout operations

    rails generate controller Sessionsnew create destroy
    

    Add the login and logout routes by editing the routes.rb file in the app/config folder.

    resources :users
    get 'login', to:'sessions#new'
    post 'login', to:'sessions#create'
    delete 'logout', to:'sessions#destroy'
    root "users#index"

    The SessionController class defines the methods for performing Session activities. The new action sets up a cookie as the email of logged user.

    When a user logs in, a new session is created. It also flashes a message letting the user know that the login is successful. The destroy action removes the session variable.

    In app/controllers/sessions_controller.rb −

    classSessionsController<ApplicationControllerdefnew@remembered_email= cookies[:remembered_email]enddefcreate
    		user =User.find_by(email: params[:email])if user && user.password == params[:password]
    			session[:user_id]= user.id
    			flash[:notice]="Welcome, #{user.name}!"if params[:remember_me]=="1"
    
    			cookies[:remembered_email]={ value: user.email, expires:1.week.from_now }else
    			cookies.delete(:remembered_email)end
    redirect_to user_path(user)else flash.now[:alert]="Invalid email or password" render :newendenddefdestroy session.delete(:user_id) flash[:notice]="You have been logged out." redirect_to login_path endend

    Add Helper Methods to ApplicationController −

    classApplicationController<ActionController::Base
    	helper_method :current_user,:logged_in?defcurrent_user@current_user||=User.find_by(id: session[:user_id])enddeflogged_in?
    		current_user.present?endend

    Create Login Form View

    Rails automatically creates the view for the new action.

    Edit the app/views/sessions/new.html.erb as follows −

    <h1>Login</h1><%= form_with url: login_path, method: :post do %>
       <div>
    
      &lt;%= label_tag :email%&gt;&lt;br&gt;&lt;%= text_field_tag :email, @remembered_email %&gt;
    </div> <div>
      &lt;%= label_tag :password%&gt;&lt;br&gt;&lt;%= password_field_tag :password %&gt;
    </div> <div>
      &lt;%= check_box_tag :remember_me,"1"%&gt;
      &lt;%= label_tag :remember_me, "Remember me" %&gt;&lt;/div&gt;&lt;%= submit_tag "Login"%&gt;
    <% end %>

    The Flash Messages are added to the Application Layout.

    Open the app/views/layouts/application.html.erb file to add a logout button when a user is logged in.

    <body><%if flash[:notice]%>
    
      &lt;p style="color: green;"&gt;&lt;%= flash[:notice] %&gt;&lt;/p&gt;
    <% end %> <% if flash[:alert] %>
      &lt;p style="color: red;"&gt;&lt;%= flash[:alert] %&gt;&lt;/p&gt;
    <% end %> <% if session[:user_id] %>
      &lt;p&gt;Logged in as &lt;%=User.find(session[:user_id]).name %&gt; |
      &lt;%= button_to "Logout", logout_path, method: :delete, data: 
        { confirm: "Are you sure you want to log out?" } %&gt;&lt;/p&gt;&lt;%else%&gt;
    <%= link_to "Login", login_path %><%end%> <%= yield %></body>

    You can now test the functionality by starting the Rails server and visiting the /users route to create a new user.

    Rails Cookies and Session1

    Go to /login and log in.

    Rails Cookies and Session2

    Check the “Remember me” box and reload the page later to see your email remembered.

    Rails Cookies and Session3

    Log out to test session and flash behavior.

    Rails Cookies and Session4
  • Controller

    The Rails controller is the logical centre of your application. It coordinates the interaction between the user, the views, and the model. The controller is also a home to a number of important ancillary services.

    • It is responsible for routing external requests to internal actions. It handles people-friendly URLs extremely well.
    • It manages caching, which can give applications orders-of-magnitude performance boosts.
    • It manages helper modules, which extend the capabilities of the view templates without bulking up their code.
    • It manages sessions, giving users the impression of an ongoing interaction with our applications.

    The following diagram explains how the controller interacts with the model and the view layer −

    Ruby on Rails Controller

    The process for creating a controller is very easy, and it’s similar to the process we’ve already used for creating a model.

    Make sure that you have already created the book model and performed migrations

    rails generate model Book title:string author:string price:integer
    rails db:migrate

    We will create the BooksController here −

    rails generate controller Books
    
      create  app/controllers/books_controller.rb
      invoke  erb
      create    app/views/books
      invoke  test_unit
      create    test/controllers/books_controller_test.rb
      invoke  helper
      create    app/helpers/books_helper.rb
      invoke    test_unit

    Notice that you are capitalizing Book and using the singular form. This is a Rails paradigm that you should follow each time you create a controller.

    This command accomplishes several tasks, of which the following are relevant here −

    It creates a file called app/controllers/book_controller.rb. If you look at book_controller.rb, you will find it as follows −

    classBooksController<ApplicationControllerend
    • Controller classes inherit from ApplicationController, which is the other file in the controllers folder: application.rb.
    • The ApplicationController contains code that can be run in all your controllers and it inherits from Rails ActionController::Base class.

    In the MVC architecture, a route maps a request to a controller action. A controller action performs the necessary work to handle the request, and prepares any data for the view. A view displays data in a desired format.

    We need to define actions in the BooksController class to handle the requests. Actions are instance methods in the class. Note that it is upto you what name you want to give to these action methods, but better to give relevant names.

    By default, the rails generate controller command creates the controller file (books_controller.rb) but does not include any actions unless explicitly specified. Let us define index(), show() and create() actions in the BooksController class.

    classBooksController<ApplicationControllerdefindexenddefshowenddefcreateendend

    Note that you can generate a controller with specific actions (e.g., index, show, create, etc.), if you include them in the command:

    rails generate controller Books index show create
    

    Implementing the create Method

    The create action is expected to be invoked by the router in response to POST /books request. It creates a new book object and returns the JSON response of newly created object.

    defcreate@book=Book.new(book_params)[email protected]
    
      render json:@book, status::createdelse
      render json:@book.errors, status::unprocessable_entityendend</pre>

    The first line creates a new instance variable called @book that holds a Book object built from the data, the user submitted. The book_params method is used to collect all the fields from object :books. The data was passed from the new method to create using the params object.

    The next line is a conditional statement that renders the book data in JSON if the object saves correctly to the database. If it doesn't save, the user is sent back error message.

    Implementing the show Method

    The show action displays the details of a book object of a certain ID passed by GET /books/:id request.

    defshow@book=Book.find(params[:id])
    
    render json:@bookend</pre>

    The show method's @book = Book.find(params[:id]) line tells Rails to find only the book that has the id defined in params[:id].

    The params object is a container that enables you to pass values between method calls. For example, when you're on the page called by the list method, you can click a link for a specific book, and it passes the id of that book via the params object so that show can find the specific book.

    Implementing the index Method

    The index method gives you a list of all the books in the database. This functionality will be achieved by the following lines of code. Edit the following lines in book_controller.rb file.

    defindex@books=Book.all
    
    render json:@booksend</pre>

    The books_controller.rb file has the code as follows −

    classBooksController<ApplicationControllerdefindex@books=Book.all
    
    render json:@booksenddefshow@book=Book.find(params[:id])
    render json:@bookenddefcreate@book=Book.new(book_params)[email protected]
      render json:@book, status::createdelse
      render json:@book.errors, status::unprocessable_entityendendprivatedefbook_params
    params.require(:book).permit(:title,:author,:price)endend</pre>

    Note that the book_params method defined above is a private method in the controller that ensures only the allowed attributes of a Book record are accepted from user input. It prevents mass assignment vulnerabilities, which could allow a user to update fields they shouldn’t have access to.

    Rails also generates config/routes.rb file. Modify it to define RESTful routes:

    Rails.application.routes.draw do
      resources :booksend

    You will learn more about routes in Rails in one of the subsequent chapters.

    Test the Controller

    To verify if the actions defined in BooksController work as desired, start your Rails server:

    rails server
    

    Use the Postman tool to test endpoints of your application:

    POST http://localhost:3000/books → to create a new book
    

    Set the Content-Type header application/json and enter the following JSON expression as body:

    {"book":{"title":"FUNDAMENTALS OF COMPUTERS","author":"Rajaraman","price":475}}

    Execute the POST action. This adds a new record in the books table:

    GET/books/:1 → Fetch a specific book with id=1

    Postman's response pane will display the details of specified book:

    GET/books → list all the books in the model 
    

    The responses pane displays the JSON representation of all the books available.

    You can also implement the UPDATE and DELETE operations in the BooksController by adding these action methods.

    defupdate@book=Book.find(params[:id])[email protected](book_params)
    
      render json:@bookelse
      render json:@book.errors, status::unprocessable_entityendenddefdestroy@book=Book.find(params[:id])@book.destroy
    head :no_contentend</pre>

    What is Next?

    You have created almost all the methods, which will work on backend. Next we will define routes (URLs) for actions.

  • Active Model

    In the earlier chapters of this tutorial, we explained the Active Record ORM in Ruby on Rails framework. Active Record is an ORM (Object Relational Mapper) that connects objects whose data requires persistent storage to a relational database. One of the functionality of Active Record is to form Active Model. In this chapter, we will explore the features of Rails Active Model.

    Relation between Active Model and Active Record

    The relation between Active Model and Active Record can be stated as follows −

    • Active Record includes Active Model.
    • Every Active Record object has all the capabilities of Active Model plus persistence.

    Hence, you will use the Active Record when you need to persist data in a database, whereas you need to use the Active Model when you need form-like models (e.g., ContactForm, SearchForm, Payment) that don’t need to be stored in the database.

    Rails Active Model Features

    Active Model is a library containing various modules that presents a set of interfaces and minimal functionalities for building model-like classes without having to use a database.

    Features of Active Model include −

    • Validations (validates)
    • Callbacks (before_validation, etc.)
    • Naming and conversion (e.g., model_name)
    • Serialization (e.g., to_json, to_xml)
    • Error handling (errors.add, errors.full_messages)
    • Dirty tracking (attribute_changed?)

    Note − Active Model allows non-persistent Ruby objects (i.e., not backed by a DB) to behave like Active Record objects in terms of form handling, validation, and serialization.

    Here are some more features of Rails Active Model −

    • ActiveModel::API to interact with Action Pack and Action View by default, and is the recommended approach to implement model-like Ruby classes.
    • The Active Model class has Attributes with which you can define data types, set default values. To use Attributes, include the module in your model class and define your attributes.
    • Inside the Active Model class, you may have one or more callback functions to hook into model lifecycle events, such as before_update and after_create.
    • ActiveModel::Serialization provides basic serialization for your object. An attribute hash (must be strings, not symbols) hash should contain the attributes you want to serialize.
    • Another feature is ActiveModel::Validations that adds the ability to validate objects and it is important for ensuring data integrity and consistency within your application.

    Example: Active Model in Rails Application

    Let us use Active Model in the following Rails application. To start with, create an application and declare a Book scaffold as below −

    rails new myapp
    cd myapp
    rails generate scaffold Book title:string author:string
    rails db:migrate

    Create the Active Model

    Create a forms folder under the app folder in your project directory and declare the BookForm class acting as the Active Model −

    # app/forms/book_form.rbclassBookFormincludeActiveModel::ModelincludeActiveModel::Attributes
    
    	attribute :title,:string
    	attribute :author,:string
    
    	validates :title,:author, presence:truedefsavereturnfalseunless valid?Book.create(title: title, author: author)endend

    Update the Controller

    Update the controller to use BookForm. Open the BooksController class and modify the create action −

    # app/controllers/books_controller.rbdefnew@book_form=BookForm.newenddefcreate@book_form=BookForm.new(book_form_params)if@book_form.save
    		redirect_to books_path, notice:"Book was successfully created."else
    		render :new, status::unprocessable_entityendend

    Update the Form View

    Rails has already created a view as new.html.erb file. Open it and edit the same to include the following code −

    <%= form_with model: @book_form, url: books_path, local: true do |form| %>
       <% if @book_form.errors.any? %>
    
      &lt;div id="error_explanation"&gt;&lt;h2&gt;&lt;%= pluralize(@book_form.errors.count, "error") %&gt; 
         prohibited this book from being saved:&lt;/h2&gt;
         &lt;ul&gt;
            &lt;% @book_form.errors.full_messages.each do |msg| %&gt;
            &lt;li&gt;&lt;%= msg %&gt;&lt;/li&gt;&lt;%end%&gt;
         &lt;/ul&gt;&lt;/div&gt;&lt;%end%&gt;
    <div class="field"><%= form.label :title %>
      &lt;%= form.text_field :title%&gt;
    </div><div class="field"><%= form.label :author %>
      &lt;%= form.text_field :author%&gt;
    </div><div class="actions"><%= form.submit "Create Book"%> </div><%end%>

    That’s it. Save the changes and run the Rails server. Visit http://localhost:3000/books/new to display a New Book form.

    Rails Active Model1

    Try clicking the Create Book button without entering any data −

    Rails Active Model2

    The error messages will be flashed as below −

    Rails Active Model3

    This time around, enter the title and author fields and submit the data. Rails will display a confirmation as below −

    Rails Active Model4

    In this example, we used the Book model (Active Record) which is mapped to the books table in the database. On the other hand, BookForm is the Active Model object. The attributes of the Active Model are not stored persistently in the database. It is used for validation and abstraction.

  • Migrations

    Rails Migration allows you to use Ruby to define changes to your database schema, making it possible to use a version control system to keep things synchronized with the actual code. Instead of writing schema modifications in pure SQL, you can use a Ruby Domain Specific Language (DSL) to make required changes to your table structure.

    This has many uses, including –

    • Teams of Developers − If one person makes a schema change, the other developers just need to update, and run “rake migrate”.
    • Production Servers − Run “rake migrate” when you roll out a new release to bring the database up to date as well.
    • Multiple Machines − If you develop on both a desktop and a laptop, or in more than one location, migrations can help you keep them all synchronized.

    Migration acts as a new ‘version’ of the database. When you generate a model, a schema has nothing in it. Each migration modifies it to add or remove tables, columns, or indexes.

    What Can Rails Migration Do?

    • create_table(name, options)
    • drop_table(name)
    • rename_table(old_name, new_name)
    • add_column(table_name, column_name, type, options)
    • rename_column(table_name, column_name, new_column_name)
    • change_column(table_name, column_name, type, options)
    • remove_column(table_name, column_name)
    • add_index(table_name, column_name, index_type)
    • remove_index(table_name, column_name)

    Migrations support all the basic data types − The following is the list of data types that migration supports −

    • string − for small data types such as a title.
    • text − for longer pieces of textual data, such as the description.
    • integer − for whole numbers.
    • float − for decimals.
    • datetime and timestamp − store the date and time into a column.
    • date and time − store either the date only or time only.
    • binary − for storing data such as images, audio, or movies.
    • Boolean − for storing true or false values.

    Valid column options are − The following is the list of valid column options.

    • comment − Adds a comment for the column.
    • collation − Specifies the collation for a string or text column.
    • default − Allows to set a default value on the column. Use nil for NULL. (:default => “blah”)
    • limit − Sets the maximum number of characters for a string column and the maximum number of bytes for text/binary/integer columns. (:limit => “50”)
    • null − Allows or disallows NULL values in the column. (:null => false)
    • precision − Specifies the precision for decimal/numeric/datetime/time columns.
    • scale − specifies the scale for the decimal and numeric columns.

    Create the Migrations

    In the previous chapter, you have created Book and Subject models with the following commands −

    malhar@ubuntu:~/library$ rails generate model Book title:string price:float subject:references
    malhar@ubuntu:~/library$ rails generate model Subject name:string

    Note that using subject:references in the Book model automatically creates a subject_id foreign key column in the books table.

    Migration files are created inside the db/migrate folder, one for each migration class. The name of the file is of the form YYYYMMDDHHMMSS_create_books.rb, which has the following code −

    classCreateBooks<ActiveRecord::Migration[8.0]defchange
    
    create_table :booksdo|t|
      t.string :title
      t.float :price
      t.references :subject, null:false, foreign_key:true
      t.timestamps
    endendend</pre>

    Similarly, the create_subjects.rb file in db\migrate folder has the following code −

    classCreateSubjects<ActiveRecord::Migration[8.0]defchange
    
    create_table :subjectsdo|t|
      t.string :name
      t.timestamps
    endendend</pre>

    Make sure that you have created associations between Book and Subject model. The Book class in book.rb file has belongs_to relation with subjects

    classBook<ApplicationRecord
      belongs_to :subjectend

    Similarly, there is a has_many relationship between Book and subjects (subject.rb)

    classSubject<ApplicationRecord
      has_many :booksend

    NOTE − Before running the migration generator, it is recommended to clean the existing migrations generated by model generators.

    The db:migrate command

    Now that you have created all the required migration files. It is time to execute them against the database. To do this, go to a command prompt and go to the library directory in which the application is located, and then run the rails migrate command as follows −

    malhar@ubuntu:~/library$ rails db:migrate==20250305181938CreateBooks: migrating ======================================-- create_table(:books)->0.0188s
    ==20250305181938CreateBooks: migrated (0.0054s)=================================20250305182034CreateSubjects: migrating ===================================-- create_table(:subjects)->0.0069s
    ==20250305182034CreateSubjects: migrated (0.0084s)==========================

    Rails creates db\schema.rb file to define the structure of the tables in the database.

    ActiveRecord::Schema[8.0].define(version:2025_03_05_182034)do
      create_table "books", force::cascadedo|t|
    
    t.string "title"
    t.float "price"
    t.integer "subject_id", null:false
    t.datetime "created_at", null:false
    t.datetime "updated_at", null:false
    t.index ["subject_id"], name:"index_books_on_subject_id"end
    create_table "subjects", force::cascadedo|t|
    t.string "name"
    t.datetime "created_at", null:false
    t.datetime "updated_at", null:falseend
    add_foreign_key "books","subjects"end

    The migration step creates a db/seeds.rb file is used to populate the database with initial or default data when setting up a Rails application.

    Edit the file and add the following statement in it −

    Subject.create([{ name:"Physics"},{ name:"Mathematics"},{ name:"Chemistry"},{ name:"Psychology"},{ name:"Geology"}])

    and then run −

    malhar@ubuntu:~/library$ rails db:seed

    This inserts the records in the Subject table.

    generate migration

    This command is used to modify the structure of an existing table, such as adding or removing a column.

    Adding Columns

    When you want to add a new column to an existing table in your database, you can use a migration with the format "AddColumnToTable" followed by a list of column names and types.

    To add a new column named author in the book model, use the following command −

    malhar@ubuntu:~/library$ rails generate migration AddAuthorToBooks author:string

    This creates a migration file −

    classAddAuthorToBooks<ActiveRecord::Migration[8.0]defchange
    
    add_column :books,:author,:stringendend</pre>

    You then apply it using the migrate command again:

    malhar@ubuntu:~/library$ rails db:migrate

    Removing Columns

    Similarly, if the migration name is of the form "RemoveColumnFromTable" and is followed by a list of column names

    malhar@ubuntu:~/library$ rails generate migration RemoveAuthorFromBooks author:string

    The change() Method

    Whenever a model structure is altered, the migration command defines the change() method to perform corresponding action (add_column, remove_column etc). It supports the following actions −

    • add_column
    • add_foreign_key
    • add_index
    • add_reference
    • create_join_table
    • create_table
    • drop_table
    • remove_column
    • remove_foreign_key
    • remove_index
    • remove_reference
    • remove_timestamps
    • rename_column
    • rename_index
    • rename_table

    You can also use the up and down methods instead of the change method (change method was introduced in Rails 5.0, and is the standard way to modify the migrations, although up/down methods are still supported but not recommended).

    The method up is used when migrating to a new version, down is used to roll back any changes if needed.

    Other Migration Commands

    In addition to the rails db:migrate command, the following migration commands are useful.

    Rolling Back

    If you have made a mistake in the model definition, rather than tracking down the version number associated with the previous migration you can run:

    malhar@ubuntu:~/library$ rails db:rollback

    This will roll back the ldatabase to the latest migration, either by reverting the change method or by running the down method. If you need to undo several migrations you can provide a STEP parameter:

    malhar@ubuntu:~/library$ rails db:rollbackSTEP=2

    Setting Up the Database

    The rails db:setup command will create the database, load the schema, and initialize it with the seed data.

    Resetting the Database

    The rails db:reset command will drop the database and set it up again. This is equivalent to rails db:drop db:setup command.

  • Active Record Query

    Read this chapter to learn the different ways to retrieve data from the database using Active Record.

    You generally need to execute the SELECT query in raw SQL to retrieve data from the tables in a database of any type (such as MySQL, PostgreSQL, Oracle SQLite etc.). In most cases, the Rails ORM implemented by Active Record insulates you from the need to use raw SQL.

    An Active Record helps you perform query operation in database-agnostic manner. So that, you don’t need to change the Rails code even if the database type is changed.

    For this chapter, we shall use the employees table populated with a sample data.

    First of all, generate the Employee model and migrate the same.

    rails generate model Employee emp_id: string email: string first_name: 
    string last_name: string ph_no: string  salary: integer
    rails db: migrate
    

    Populate the Table

    Open the console corresponding to the database in use (for example SQLite) and populate the employees table with the following data:

    INSERTINTO employees (emp_id, email, first_name, last_name, ph_no, salary)VALUES(1,'[email protected]','John','Doe','+11536198741',14320),(2,'[email protected]','Jane','Doe','+11536219842',12050),(3,'[email protected]','Michael','Smith','+11536298753',11340),(4,'[email protected]','Emily','Jones','+11536376482',9800),(5,'[email protected]','David','Lee','+11536492837',15430)

    While in the Rails application directory, open the Rails Console and verify that the Employee model has the above data by calling the all method. Observer that it internally executes the SELECT query to fetch all records.

    library(dev)>Employee.all
    SELECT"employees".*FROM"employees"

    Methods to Retrieve Objects

    Rails Active Record query interface provides different methods to retrieve objects. Let us learn about the most frequently used methods.

    The find() Method

    With the find() method, you can retrieve the object corresponding to the specified primary key that matches any supplied options. For example, the following statement fetched the employee with id = 2

    library(dev)>Employee.find(2)SELECT"employees".*FROM"employees"WHERE"employees"."id"=2LIMIT1

    The console also echoes the corresponding SELECT query.

    If no matching record is found, then the find method will raise an ActiveRecord::RecordNotFound exception.

    To fetch multiple objects, call the find method and pass in an array of primary keys.

    library(dev)>Employee.find([1,3])

    The SQL equivalent query is as follows:

    SELECT"employees".*FROM"employees"WHERE"employees"."id"IN(1,3)

    The take() Method

    Rails will not apply any implicit ordering with the take method that retrieves a given record. Without any arguments, the very first record in the table is retrieved, as can be observed from the SQL query.

    library(dev)>Employee.take
    SELECT"employees".*FROM"employees"LIMIT1

    You can specify the number of records to be retrieved as an integer argument. For example, the following command returns first four records.

    library(dev)>Employee.take(4)SELECT"employees".*FROM"employees"LIMIT4

    The first() Method

    The first method finds the first record ordered by primary key. Accordingly, it adds the ORDER BY clause in the SELECT query internally executed by Rails.

    library(dev)>Employee.first
    SELECT"employees".*FROM"employees"ORDERBY"employees"."id"ASCLIMIT1

    The last() Method

    On the other hand, the last method retrieves the last record ordered by primary key.

    library(dev)>Employee.last
    SELECT"employees".*FROM"employees"ORDERBY"employees"."id"DESCLIMIT1

    The last method returns nil if no matching record is found and no exception will be raised.

    The find_by Method

    The find_by method finds the first record matching some conditions. For example, use the following command to find the record with first name as Jane.

    library(dev)>Employee.find_by first_name:"Jane"SELECT"employees".*FROM"employees"WHERE"employees"."first_name"='Jane'LIMIT1

    As you can see, the SELECT query adds the WHERE clause.

    You can also achieve the same effect by the where() method, passing the condition as argument.

    library(dev)>Employee.where(first_name:"Jane").take
      EmployeeLoad(0.2ms)SELECT"employees".*FROM"employees"WHERE"employees"."first_name"='Jane'LIMIT1

    The find_each() Method

    You can also retrieve multiple objects. The find_each() method is a memory-friendly technique to retrieve a batch of records and then yields each record to the block individually as a model.

    You can use the rails runner command to echo the records on the command terminal.

    rails runner "Employee.find_each { |e| puts e.first_name }"JohnJaneMichaelEmilyDavid

    You may also do the same inside the rails console. Have a look at the equivalent SQL query.

    library(dev)>Employee.find_each {|e| puts e.last_name }SELECT"employees".*FROM"employees"ORDERBY"employees"."id"ASCLIMIT1000

    Conditional Retrieval

    You can use the where() method for conditional retrieval. You can execute a parameterized SELECT query by using the ? symbol as a place holder.

    library(dev)>Employee.where("last_name = ?","Smith")SELECT"employees".*FROM"employees"WHERE(last_name ='Smith')

    The params Keyword

    You can use array conditions in the Employee model while incorporating the params keyword, and pass params as argument to where() method.

    Here, the last_name is defined as a parameter. Rails retrieves objects matching with the condition. Use of params helps in avoiding SQL injection.

    library(dev)> params ={ last_name:"Smith"}=>{:last_name=>"Smith"}
    library(dev)>Employee.where(last_name: params[:last_name])SELECT"employees".*FROM"employees"WHERE"employees"."last_name"='Smith'

    Here is another example. All the objects with last_name column having the given characters are returned. As in SQL, using LIKE keyword is defined in Rails Active Record class.

    library(dev)> params ={ last_name:"Do"}=>{:last_name=>"Do"}
    library(dev)>Employee.where("last_name LIKE ?", params[:last_name]+"%")EmployeeLoad(0.3ms)SELECT"employees".*FROM"employees"WHERE(last_name LIKE'Do%')

    The order() Method

    You know that the SELECT query has the ORDER BY clause. Active Record interface implements the same with its order() method. You need to pass the expression on which the query result should be ordered.

    The following statement retrieves the employee objects on the ascending order of salary:

    library(dev)>Employee.order(:salary)SELECT"employees".*FROM"employees"ORDERBY"employees"."salary"ASCLIMIT11

    Add the desc keyword to generate the SELECT query with ORDER BY DESC clause:

    library(dev)>Employee.order(first_name::desc)SELECT"employees".*FROM"employees"ORDERBY"employees"."first_name"DESCLIMIT11

    The select() Method

    The Model.find method selects all the fields, which equivalent to SELECT * from table. To select only a subset of fields from the result set, you can specify the subset via the select method.

    library(dev)>Employee.select(:first_name,:last_name,:salary)SELECT"employees"."first_name","employees"."last_name","employees"."salary"FROM"employees"LIMIT11

    Alternatively, you can pass a string with desired column names separated by a single space.

    library(dev)>Employee.select("first_name last_name salary")

    To translate the SELECT query with the DISTINCT clause, append the distinct keyword to the select() call.

    library(dev)>Employee.select(:last_name).distinct
    SELECTDISTINCT"employees"."last_name"FROM"employees"

  • Active Record Associations

    Relational databases have tables related to each other, and their relationship is established with primary and foreign keys. In Rails, the Active Record associations allow you to define relationships between models. Associations indicate how your models relate to each other. When you set up an association between models, Rails migration defines the Primary Key and Foreign Key relationships, ensuring the consistency and integrity of the database.

    Rails supports six types of associations.

    • belongs_to
    • has_one
    • has_many
    • has_many :through
    • has_one :through
    • has_and_belongs_to_many

    belongs_to Association

    Consider a case of Book and Author models, where each book can be assigned to exactly one author. A belongs_to association reflects the relationship between the two.

    Generate the models with the following commands −

    rails generate model Author name:string
    
    rails generate model Book title:string author:references

    Rails generates the Book model with a foreign key column (author_id) and sets up the belongs_to association.

    classBook<ApplicationRecord
      belongs_to :authorend

    The database server creates the tables books and authors with the relationship expressed by primary and foreign keys.

    Belongs to Association

    The belongs_to association means that this model’s table contains a column which represents a reference to another table. Use belongs_to in combination with a has_one or has_many to set up one-directional or bi-directional relationship.

    has_one Association

    has_one association is useful when one other model has a reference to this model. That model can be fetched through this association. For example, if each supplier in your application has only one account.

    Open the command prompt and use the following commands to generate the models −

    rails generate model Supplier name:string
    
    rails generate model Account account_number:string supplier:references

    Edit the supplier.rb script and define the haas_one association with account model.

    classSupplier<ApplicationRecord
      has_one :accountend

    In the underlying database, the relationship between suppliers and accounts tables is reflected by the following figure −

    Has one Association

    The has_one association creates a one-to-one match with another model. says that the other class contains the foreign key. This relation can be bi-directional when used in combination with belongs_to on the other model.

    has_many Association

    has_many association is similar to has_one, but indicates a one-to-many relationship with another model. This association indicates that each instance of the model has zero or more instances of another model.

    This is how the has_many association is established between Author and multiple instances of Book model.

    classAuthor<ApplicationRecord
      has_many :booksend

    The equivalent relationship diagram is as follows −

    Has Many Association

    The has_many establishes a one-to-many relationship between models, allowing each instance of the declaring model (Author) to have multiple instances of the associated model (Book).

    Unlike a has_one and belongs_to association, the name of the other model is pluralized when declaring a has_many association.

    has_many :through Association

    has_many :through association is often used to set up a many-to-many relationship with another model through an intermediate model. This association indicates that the declaring model can be matched with zero or more instances of another model by proceeding through a third model.

    Consider a situation where a Doctor can have multiple Patients and a Patient can have multiple Doctors through Appointments, you can use a has_many :through association.

    Generate the following models with these commands −

    rails generate model Doctor name:string specialization:string
    rails generate model Patient name:string age:integer
    rails generate model Appointment doctor:references patient:references appointment_date:datetime

    Now, create the associations. Edit the doctor.db script in app/models directory.

    classDoctor<ApplicationRecord
      has_many :appointments
      has_many :patients, through::appointmentsend

    The patient model also should have the has_many association with appointments and doctors (note the use of plurals) models

    classPatient<ApplicationRecord
      has_many :appointments
      has_many :doctors, through::appointmentsend

    Lastly associate the Appointment model with Doctor and Patient models with belongs_to association.

    classAppointment<ApplicationRecord
      belongs_to :doctor
      belongs_to :patientend

    has_one :through Association

    has_one :through association sets up a one-to-one relationship with another model through an intermediary model. This association indicates that the declaring model can be matched with one instance of another model by proceeding through a third model.

    • Employee, Office, and Company
    • An Employee works in an Office.
    • Each Office belongs to a Company.
    • An Employee belongs to a Company through their Office.

    If the models are set up as follows −

    rails generate model Company name:string
    rails generate model Office location:string company:references
    rails generate model Employee name:string office:references

    The Employee model is associated with Company with has_one:though type, and there’s a belongs_to association between Employee and Office models.

    classEmployee<ApplicationRecord
      belongs_to :office
      has_one :company, through::officeend

    has_and_belongs_to_many Association

    has_and_belongs_to_many association creates a direct many-to-many relationship with another model, with no intervening model. This association indicates that each instance of the declaring model refers to zero or more instances of another model.

    For example, consider an application with Assembly and Part models, where each assembly can contain many parts, and each part can be used in many assemblies.

    Generate the models −

    rails generate model Assembly name:string
    rails generate model Part name:string

    Establish the associations −

    classAssembly<ApplicationRecord
      has_and_belongs_to_many :partsendclassPart<ApplicationRecord
      has_and_belongs_to_many :assembliesend

    The has_and_belongs_to_many association creates a direct many-to-many association. Even though a has_and_belongs_to_many does not require an intervening model, it does require a separate table to establish the many-to-many relationship between the two models involved.

  • Validation

    It is important that the state of an object of Active Record class is validated before saving the same in the underlying database. This is essential to ensure the integrity of the data. For example, your model might have email as one of the attributes. It must be ensured that the user enters a valid email address before saving the record.

    Rails provides model-level validations to ensure that only valid data is saved into your database. There are many built-in helpers, and you can create your own validation methods as well.

    Rails runs the validations before saving a new object or updating an existing object to the database. If any validations fail, the object will be marked as invalid and Active Record will not perform the INSERT or UPDATE operation.

    Validation takes place when any of the following methods of Active Record are called:

    • create
    • create!
    • save
    • save!
    • update
    • update!

    Methods with exclamation mark(!) at the end raise an exception when a record is invalid.

    You can also run the save method by skipping the validation.

    save(validate:false)

    Let us first declare a Person model as below:

    rails generate model Person name:string age: integer
    

    Then migrate this model

    rails db:migrate

    In the person.rb, add the validation rule aas:

    classPerson<ApplicationRecord
      validates :name, presence:trueend

    Open the Ruby console, and declare a Person object

    library(dev)> p =Person.new=>#<Person:0x00000243d3c9af40...Checkif the object is valid
    library(dev)> p.valid?=>false

    Declare another object and check the validity

    library(dev)> p =Person.new(name:"Ravi", age:21)=>#<Person:0x00000243cf159ec8...
    library(dev)> p.valid?=>true

    Modify the model to add another validity rule, age shoulf be numeric and greater than 0.

    classPerson<ApplicationRecord
      validates :name, presence:true
      validates :age, numericality:{ greater_than:0}end

    If you declare an object as follows, and check if it is valid

    library(dev)> p =Person.new(name:"Ravi", age:0)=>#<Person:0x0000026df640c228...
    library(dev)> p.valid?=>false

    The save method on invalid object returns false

     library(dev)> p.save
    =>false

    If you try to skip the validation while running the save operation, Rails throws an error.

    library(dev)> p.save!(library):4:in `<main>':Validation failed:Age must be greater than 0(ActiveRecord::RecordInvalid)

    Validates Method

    You can add validations to a model using the validates method inside the model class. This ensures that data meets certain conditions before being saved to the database.

    Iin Rails, validates is a class method, provided by ActiveModel::Validations. It is used to declare validation rules for a model’s attributes.

    classPerson<ApplicationRecord
      validates :name, presence:trueend

    The method should have the parameters:

    • *attributes − Takes one or more attribute names (like :title).
    • **options − Takes a hash of validation rules (presence: true, length: { minimum: 3 }, etc.).

    Validation Helpers

    There are many pre-defined validation helpers to be used inside your class definitions. Each helper accepts an arbitrary number of attribute names. The :on and :message options define when the validation should be run and what is the error message when the validation fails.

    Presence Validation

    This validation ensures that a particular field is not empty. In the above Person model, name cannot be empty.

    classPerson<ApplicationRecord
      validates :name, presence:trueend

    Length Validation

    This validation is commonly used to restrict the length of a string field. For example, if the Person model has a password field and you want to ensure it to be at least 8 characters long, you would write the following code −

    classPerson<ApplicationRecord
      validates :password, length:{ minimum:8}end

    The other length constraint options are:

    • :minimum – The attribute cannot have less than the specified length.
    • :maximum – The attribute cannot have more than the specified length.
    • :in (or :within) – The attribute length must be included in a given interval.
    • :is – The attribute length must be equal to the given value.

    Numericality Validation

    Use this validation to ensure that a particular field is a number. For example,

    classperson<ApplicationRecord
      validates :age, numericality:{ greater_than_or_equal_to:18}end

    This will ensure the age field is a number greater than or equal to 18.

    Following options can be used to specify the validation rules:

    • :greater_than – Specifies the value must be greater than the supplied value.
    • :greater_than_or_equal_to – Specifies the value must be greater than or equal to the value.
    • :equal_to – Specifies the value must be equal to the supplied value.
    • :less_than – Specifies the value must be less than the supplied value.
    • :less_than_or_equal_to – Specifies the value must be less than or equal to the supplied value.
    • :other_than – Specifies the value must be other than the supplied value.
    • :in – Specifies the value must be in the supplied range.
    • :odd – Specifies the value must be an odd number.
    • :even – Specifies the value must be an even number.
    • :only_integer – specifies the value “must be an integer”.

    Confirmation Validation

    You should use this helper when you have two text fields that should receive exactly the same content. For example, the Person model has a field named as email and you want to confirm an email address.

    classPerson<ApplicationRecord
      validates :email, confirmation:trueend

    Comparison Validation

    This validation helps you perform a comparison between any two comparable values.

    classPerson<ApplicationRecord
      validates :age, comparison:{ greater_than::min_age}end

    Options available:

    • :greater_than – Specifies the value must be greater than the supplied value.
    • :greater_than_or_equal_to – Specifies the value must be greater than or equal to the supplied value.
    • :equal_to – Specifies the value must be equal to the supplied value.
    • :less_than – Specifies the value must be less than the supplied value.
    • :less_than_or_equal_to – Specifies the value must be less than or equal to the supplied value
    • :other_than – Specifies the value must be other than the supplied value.

    Inclusion Validation

    This helper validates that the attributes’ values are included in a given set. In fact, this set can be any enumerable object.

    classStudent<ApplicationRecord
      validates :subject, inclusion:{in:%w(PhyCheMaths}end

    Exclusion Validation

    This helper is the opposite of inclusion as it validates that the attributes’ values are not included in a given set.

    Uniqueness Validation

    This validator ensures that the attribute’s value is unique right before the object gets saved.

    classPerson<ApplicationRecord
      validates :RollNo, uniqueness:trueend

    Multiple Validations

    You can use multiple validations on a single field by chaining validations together.

     validates :userid,:presence=>true,:length=> length:{minimum:10, maximum:50},:uniqueness=>true,:confirmation=>true

    Validation methods with older Rails syntax (before Rails 3) are still supported for backward compatibility. Examples:

    • validates_presence_of
    • validates_numericality_of
    • validates_length_of
    • validates_inclusion_of
    • validates_confirmation_of

    Custom Validation

    In addition to the built-in validation methods, Rails also allows you to create custom validations. For example, if you want to ensure that the name attribute in the Person model is always capitalized, you could write a custom validation method:

    classPerson<ApplicationRecord
      validate :CustomValidatorprivatedefCustomValidator
    
      errors.add(:name,"must be capitalized")unless name.nil?|| name == name.capitalize
    endend</pre>
  • Active Records

    Rails Active Record is the Object/Relational Mapping (ORM) layer supplied with Rails. It closely follows the standard ORM model, which is as follows −

    • Tables map to classes,
    • Rows map to objects and
    • Columns map to object attributes.

    Rails Active Records provide an interface and binding between the tables in a relational database and the Ruby program code that manipulates database records. Ruby method names are automatically generated from the field names of database tables.

    Each Active Record object has CRUD (Create, Read, Update, and Delete) methods for database access. This strategy allows simple designs and straightforward mappings between database tables and application objects.

    • Each entity (such as book) gets a table in the database named after it, but in the plural (books).
    • Each such entity-matching table has a field called id, which contains a unique integer for each record inserted into the table.
    • Given entity x and entity y, if entity y belongs to entity x, then table y has a field called x_id.
    • The bulk of the fields in any table store the values for that entity’s simple properties (anything that’s a number or a string).

    Creating Active Record Files (Models)

    To create the Active Record files for our entities for library application, introduced in the previous chapter, issue the following command from the top level of the application directory.

    Assuming that you have created a new Rails app named Library −

    malhar@ubuntu:~/library$ rails generate model Book
    
      invoke  active_record
      create    db/migrate/20250226073251_create_books.rb
      create    app/models/book.rb
      invoke    test_unit
      create      test/models/book_test.rb
      create      test/fixtures/books.yml

    Similarly, generate Subject model −

    malhar@ubuntu:~/library$ rails generate model Subject
    
      invoke  active_record
      create    db/migrate/20250226073318_create_subjects.rb
      create    app/models/subject.rb
      invoke    test_unit
      create      test/models/subject_test.rb
      create      test/fixtures/subjects.yml

    You’re telling the generator to create models called Book and Subject to store instances of books and subjects. Notice that you are capitalizing Book and Subject and using the singular form. This is a Rails paradigm that you should follow each time you create a model.

    When you use the generate tool, Rails creates the actual model file that holds all the methods unique to the model and the business rules you define, a unit test file for performing test-driven development, a sample data file (called fixtures) to use with the unit tests, and a Rails migration that makes creating database tables and columns easy.

    Apart from creating many other files and directories, this will create files named book.rb and subject.rb containing a skeleton definition in the app/models directory.

    Content available in book.rb −

    classBook<ActiveRecord::Baseend

    Content available in subject.rb

    classSubject<ActiveRecord::Baseend

    Creating Associations between Models

    When you have more than one model in your rails application, you would need to create connection between those models. You can do this via associations.

    Active Record supports three types of associations −

    • one-to-one − A one-to-one relationship exists when one item has exactly one of another item. For example, a person has exactly one birthday or a dog has exactly one owner.
    • one-to-many − A one-to-many relationship exists when a single object can be a member of many other objects. For instance, one subject can have many books.
    • many-to-many − A many-to-many relationship exists when the first object is related to one or more of a second object, and the second object is related to one or many of the first object.

    You indicate these associations by adding declarations to your models: has_onehas_manybelongs_to, and has_and_belongs_to_many.

    Now, you need to tell Rails what relationships you want to establish within the library data system. To do so, modify book.rb and subject.rb to look like this −

    classBook<ActiveRecord::Base
       belongs_to :subjectend

    We have used a singular subject in the above example, because one Book can belong to a single Subject.

    classSubject<ActiveRecord::Base
       has_many :booksend

    We have used plural books here, because one subject can have multiple books.

    Implementing Validations on Models

    The implementation of validations is done in a Rails model. The data you are entering into the database is defined in the actual Rails model, so it only makes sense to define what valid data entails in the same location.

    The validations are −

    • The value of title field should not be NULL.
    • The value of price field should be numeric.

    Open book.rb in the app\model subdirectory and put the following validations −

    classBook<ActiveRecord::Base
       belongs_to :subject
       validates_presence_of :title
       validates_numericality_of :price,:message=>"Error Message"end
    • validates_presence_of − protects “NOT NULL” fields against missing user input.
    • validates_numericality_of − prevents the user, entering non numeric data.

    Besides the validations mentioned above, there are other common validations.

    Built in Validation Methods

    Rails provides many inbuilt validation helpers as follows:

    • validates_length_of : used to check length requirements of the attribute. For example:
    validates_length_of :password,:minimum=>8,:maximum=>20
    • validates_inclusion_of : checks to see if an attribute is in a list of choices. For example:
    validates_inclusion_of :status,:usertype=>['admin','manager','developer','tester']
    • validates_associated: is used to check associations with other models. For example:
    classSubject<ApplicationRecord
    
    has_many :books
    validates_associated :booksend</pre>
    • validates_confirmation_of : is used to validate a password or email address field with a confirmation.
    validates_confirmation_of :user_name,:password

    It is also possible to check multiple validations in one statement. For example,

    validates :userid,:presence=>true,:length=> length:{minimum:10, maximum:50},:uniqueness=>true,:confirmation=>true

    What is Next?

    In the next chapter, we will learn Rails Migration, which allows you to use Ruby to define changes to your database schema, making it possible to use a version control system to keep things synchronized with the actual code.

  • Database Setup

    Before starting with this chapter, make sure your database server is up and running. Ruby on Rails recommends to create three databases – a database each for development, testing, and production environment. According to convention, their names should be −

    • library_development
    • library_production
    • library_test

    You should initialize all three of them and create a user and password for them with full read and write privileges.

    We shall learn how to set up MySQL and PostgreSQL databases for use with your Rails app.

    Install MySQL/PostgreSQL

    On Ubuntu (or inside WSL on Windows), install MySQL with following command −

    sudo apt install mysql-server mysql-client
    

    This installs the MySQL database server, and the client for interacting with MySQL.

    After installation, start and enable the MySQL service −

    sudo systemctl start mysql
    sudo systemctl enable mysql
    

    To install PostgreSQL, use the command −

    sudo apt install postgresql postgresql-contrib
    

    This installs PostgreSQL along with additional contributed utilities. Start and enable the server with the following command:

    Start PostgreSQL −

    sudo systemctl start postgresql
    sudo systemctl enable postgresql
    

    For Windows, install MySQL by downloading the installer ((mysql-installer-community-8.0.41.0.msi)) from https://dev.mysql.com/downloads/installer/.

    To install PostgreSQL, download and run the installer (postgresql-17.4-1-windows-x64.exe) from https://www.postgresql.org/download/windows/.

    Database Setup for MySQL

    you can manually create the databases inside a MySQL console, using the root user ID for our application.

    mysql>createdatabase library_development;
    Query OK,1row affected (0.01 sec)
    
    mysql>grantallprivilegeson library_development.*to'root'@'localhost' identified by'password';
    Query OK,0rows affected (0.00 sec)
    
    mysql> FLUSH PRIVILEGES;
    Query OK,0rows affected (0.00 sec)

    You can do the same thing for two more databases library_production and library_test.

    When you create a new Rails application from the command line, you can specify the database type with -d option

    rails new library -d mysql
    

    Configuring database.yml

    At this point, you need to let Rails know about the user name and password for the databases. You do this in the file database.yml, available in the library\config subdirectory of Rails Application you created. This file has live configuration sections for MySQL databases. In each of the sections you use, you need to change the username and password lines to reflect the permissions on the databases you’ve created.

    default: &default
      adapter: mysql2
      encoding: utf8mb4
      pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
      username: root
      password:
      socket: /var/run/mysqld/mysqld.sock
    development:
      <<: *defaultdatabase: library_development
    test:
      <<: *defaultdatabase: library_test
    production:
      primary: &primary_production
    
    &lt;&lt;: *defaultdatabase: library_production
    username: library
    password: &lt;%= ENV["LIBRARY_DATABASE_PASSWORD"]%&gt;
    cache:
    &lt;&lt;: *primary_production
    database: library_production_cache
    migrations_paths: db/cache_migrate
    queue:
    &lt;&lt;: *primary_production
    database: library_production_queue
    migrations_paths: db/queue_migrate
    cable:
    &lt;&lt;: *primary_production
    database: library_production_cable
    migrations_paths: db/cable_migrate

    Database Setup for PostgreSQL

    If you want to use the PostgreSQL database for your library project, you can create the required databases with PgAdmin the popular PostgreSQL management tool.

    Database Setup for PostgreSQL

    Similarly, create the test and production databases.

    Create a new Rails project named as library with RubyMine, and choose PostgreSQL database.

    Database PostgreSQL

    Configuring database.yml

    When the application is created, the file database.yml, available in the library\config subdirectory of Rails Application you created. This file has live configuration sections for PostgreSQL databases. In each of the sections, you need to change the username and password lines to reflect the permissions on the databases you’ve created.

    default: &default
      adapter: postgresql
      encoding: unicode
      pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
    
    development:
      <<: *defaultdatabase: library_development
      username: library
      password:
      host: localhost
      port: 5432
    
    test:
      <<: *defaultdatabase: library_test
    
    production:
      primary: &primary_production
    
    &lt;&lt;: *defaultdatabase: library_production
    username: library
    password: &lt;%= ENV["LIBRARY_DATABASE_PASSWORD"]%&gt;
    cache:
    &lt;&lt;: *primary_production
    database: library_production_cache
    migrations_paths: db/cache_migrate
    queue:
    &lt;&lt;: *primary_production
    database: library_production_queue
    migrations_paths: db/queue_migrate
    cable:
    &lt;&lt;: *primary_production
    database: library_production_cable
    migrations_paths: db/cable_migrate

    What is Next?

    The next two chapters explain how to model your database tables and how to manage those using Rails Migrations.

  • Examples


    In this chapter, we will create a simple but operational online library system for holding and managing the books.

    This application has a basic architecture and will be built using two ActiveRecord models to describe the types of data that is stored −

    • Books, which describes an actual listing.
    • Subject, which is used to group books together.

    Workflow for Creating Rails Applications

    A recommended work flow for creating Rails Application is as follows −

    • Use the rails command to create the basic skeleton of the application.
    • Create a database on the PostgreSQL server to hold your data.
    • Configure the application to know where your database is located and the login credentials for it.
    • Create Rails Active Records (Models), because they are the business objects you’ll be working with in your controllers.
    • Generate Migrations that simplify the creating and maintaining of database tables and columns.
    • Write Controller Code to put a life in your application.
    • Create Views to present your data through User Interface.

    So, let us start with creating our library application.

    Creating an Empty Rails Web Application

    Rails is both a runtime web application framework and a set of helper scripts that automate many of the things you do when developing a web application. In this step, we will use one such helper script to create the entire directory structure and the initial set of files to start our Library System application.

    • Go into ruby installation directory to create your application.
    • Run the following command to create a skeleton for library application. It will create the directory structure in the current directory.
    tp> rails new library
    

    This will create a subdirectory for the library application containing a complete directory tree of folders and files for an empty Rails application. Check a complete directory structure of the application. Check Rails Directory Structure for more detail.

    Most of our development work will be creating and editing files in the library/app subdirectories. Here’s a quick run down of how to use them −

    • The controllers subdirectory is where Rails looks to find controller classes. A controller handles a web request from the user.
    • The views subdirectory holds the display templates to fill in with data from our application, convert to HTML, and return to the user’s browser.
    • The models subdirectory holds the classes that model and wrap the data stored in our application’s database. In most frameworks, this part of the application can grow pretty messy, tedious, verbose, and error-prone. Rails makes it dead simple.
    • The helpers subdirectory holds any helper classes used to assist the model, view, and controller classes. This helps to keep the model, view, and controller code small, focused, and uncluttered.

    Starting Web Server

    Rails web application can run under virtually any web server, but the most convenient way to develop a Rails web application is to use the built-in WEBrick web server. Let’s start this web server and then browse to our empty library application −

    This server will be started from the application directory as follows. It runs on port number 3000.

    tp> cd ruby\library 
    tp\ruby\library\> Rails server
    

    It generates the auto code to start the server as shown below −

    Rails Server

    This will start your WEBrick web server.

    Now open your browser and browse to http://127.0.0.1:3000. If everything is gone fine, then you should see a greeting message from WEBrick, otherwise there is something wrong with your setting. If everything goes well it will generate the output as follows.

    Web Server

    What is next?

    The next chapter explains how to create databases for your application and what is the configuration required to access these created databases.

    Further, we will see what Rails Migration is and how it is used to maintain database tables.