Ruby on Rails CRUD and API tutorial

February 11, 2016
5 min read
Ruby on Rails CRUD and API tutorial

We organized this Saturday a Ruby on Rails Workshop, where the main goal was everyone to understand the basic principles of Rails, by developing a simple application with basic features: CRUD using MySQL database and a basic API using Grape gem. We thought it will be useful for our readers if we share this simple application and try to better explain by publishing a step by step tutorial.

Creating CRUD is a very common task in WEB development. CRUD is standard for:

  • Create
  • Read
  • Update
  • Delete

In this tutorial we will create a Rails CRUD grid, a API CRUD and demonstrate how Rails communicate with a MYSQL database.

So let's get started!

Create a new Rails Application through console:


	rails new crud_api

Open the application generated in a IDE, search for Gemfile file and add the following gem:


	gem 'grape'

Open config/application.rb and add:


    config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
    config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')]

Run from console:


	bundle install

Open config/database.yml and set your MYSQL settings. Open app/views/layouts/application.html.erb and insert this lines in head:


	<%= stylesheet_link_tag    'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css' %>
 	<%= stylesheet_link_tag    'https://cdn.datatables.net/s/dt/dt-1.10.10,r-2.0.0/datatables.min.css' %>

this lines before </body>


	<%= javascript_include_tag 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js' %>
	<%= javascript_include_tag 'https://cdn.datatables.net/s/dt/dt-1.10.10,r-2.0.0/datatables.min.js' %>

And replace <%= yield %> with this code:


<div class="container">
<div class="row">
<div class="col-md-12"><% if flash[:notice] %>
<div class="alert alert-success"><%= flash[:notice] %></div>
<% end %> <%= yield %></div>
</div>
</div>

Go to app/assets/javascripts/application.js and add the javascript code that load the jQuery DataTable:


var ready = function() {

    $('#products').DataTable({
        "columnDefs": [
            { "width": "19%", className: "dt-body-center", "targets": -1 },
            { "width": "10%", "targets": 0 },
            { "width": "7%", "targets": 1 },
            { "width": "20%", "targets": 2 },
            { "width": "20%", "targets": 3 },
        ]
    });

}

$(document).ready(ready);
$(document).on('page:load', ready);

Create a new controller from command line:


	rails g controller products index show new create edit update destroy

Create a new model from command line:


	rails g model product name:string price:decimal short_description:text full_description:text

Go to app/controllers/products_controller.rb and write this methods:


class ProductsController < ApplicationController

  # GET method to get all products from database
  def index
    @products = Product.all
  end

  # GET method to get a product by id
  def show
    @product = Product.find(params[:id])
  end

  # GET method for the new product form
  def new
    @product = Product.new
  end

  # POST method for processing form data
  def create
    @product = Product.new(product_params)
    if @product.save
      flash[:notice] = 'Product added!'
      redirect_to root_path
    else
      flash[:error] = 'Failed to edit product!'
      render :new
    end
  end

   # GET method for editing a product based on id
  def edit
    @product = Product.find(params[:id])
  end

  # PUT method for updating in database a product based on id
  def update
    @product = Product.find(params[:id])
    if @product.update_attributes(product_params)
      flash[:notice] = 'Product updated!'
      redirect_to root_path
    else
      flash[:error] = 'Failed to edit product!'
      render :edit
    end
  end

  # DELETE method for deleting a product from database based on id
  def destroy
    @product = Product.find(params[:id])
    if @product.delete
      flash[:notice] = 'Product deleted!'
      redirect_to root_path
    else
      flash[:error] = 'Failed to delete this product!'
      render :destroy
    end
  end

  # we used strong parameters for the validation of params
  def product_params
    params.require(:product).permit(:name, :price, :old_price, :short_description, :full_description)
  end

end

Open app/models/product.rb and let's make some validations on the name, price and short description fields:


  validates :name, presence: true
  validates :price, presence: true, numericality: {:greater_than => 0}
  validates :short_description, presence: true

Now we have a controller and a model, in order to access the application in browser let's add the routes, so open config/routes.rb and add:


  resources :products
  root 'products#index'

The views you can find on github at:

Now the API part, create a folder named api in app, and inside api create products folder. So the structure will be app/api/products. Here create products_api.rb file and insert this code:


module Products
  class ProductsAPI < Grape::API

    format :json

    desc "Product List", {
        :notes => <<-NOTE
        Get All Products
         __________________
        NOTE
    }

    get do
      Product.all
    end


    desc "Product By Id", {
        :notes => <<-NOTE
        Get Product By Id
         __________________
        NOTE
    }

    params do
      requires :id, type: Integer, desc: "Product id"
    end

    get ':id' do
      begin
        product = Product.find(params[:id])
      rescue ActiveRecord::RecordNotFound
        error!({ status: :not_found }, 404)
      end
    end

    desc "Delete Product By Id", {
        :notes => <<-NOTE
        Delete Product By Id
         __________________
        NOTE
    }

    params do
      requires :id, type: Integer, desc: "Product id"
    end

    delete ':id' do
      begin
        product = Product.find(params[:id])
        { status: :success } if product.delete
      rescue ActiveRecord::RecordNotFound
        error!({ status: :error, message: :not_found }, 404)
      end
    end

    desc "Update Product By Id", {
        :notes => <<-NOTE
        Update Product By Id
                        __________________
        NOTE
    }

    params do
      requires :id, type: Integer, desc: "Product id"
      requires :name, type: String, desc: "Product name"
      requires :price, type: BigDecimal, desc: "Product price"
      optional :old_price, type: BigDecimal, desc: "Product old price"
      requires :short_description, type: String, desc: "Product old price"
      optional :full_description, type: String, desc: "Product old price"
    end

    put ':id' do
      begin
        product = Product.find(params[:id])
        if product.update({
                              name: params[:name],
                              price: params[:price],
                              old_price: params[:old_price],
                              short_description: params[:short_description],
                              full_description: params[:full_description]
                          })
          { status: :success }
        else
          error!({ status: :error, message: product.errors.full_messages.first }) if product.errors.any?
        end


      rescue ActiveRecord::RecordNotFound
        error!({ status: :error, message: :not_found }, 404)
      end
    end


    desc "Create Product", {
        :notes => <<-NOTE
        Create Product
         __________________
        NOTE
    }

    params do
      requires :name, type: String, desc: "Product name"
      requires :price, type: BigDecimal, desc: "Product price"
      optional :old_price, type: BigDecimal, desc: "Product old price"
      requires :short_description, type: String, desc: "Product old price"
      optional :full_description, type: String, desc: "Product old price"
    end

    post do
      begin
        product =  Product.create({
                                      name: params[:name],
                                      price: params[:price],
                                      old_price: params[:old_price],
                                      short_description: params[:short_description],
                                      full_description: params[:full_description]
                                  })
        if product.save
          { status: :success }
        else
          error!({ status: :error, message: product.errors.full_messages.first }) if product.errors.any?
        end


      rescue ActiveRecord::RecordNotFound
        error!({ status: :error, message: :not_found }, 404)
      end
    end
  end
end

Now go back to config/routes.rb and add:


	mount Products::ProductsAPI => '/api/products'

Run db:migrate from console to run the migrations:


	rake db:migrate

You can check the application on our Github page. If you have any question please ask below.

Share on:

Want to stay on top of everything?

Get updates on industry developments and the software solutions we can now create for a smooth digital transformation.

* I read and understood the ASSIST Software website's terms of use and privacy policy.

Frequently Asked Questions

1. What is ASSIST Software's development process?  

The Software Development Life Cycle (SDLC) we employ defines the following stages for a software project. Our SDLC phases include planning, requirement gathering, product design, development, testing, deployment, and maintenance.

2. What software development methodology does ASSIST Software use?  

ASSIST Software primarily leverages Agile principles for flexibility and adaptability. This means we break down projects into smaller, manageable sprints, allowing continuous feedback and iteration throughout the development cycle. We also incorporate elements from other methodologies to increase efficiency as needed. For example, we use Scrum for project roles and collaboration, and Kanban boards to see workflow and manage tasks. As per the Waterfall approach, we emphasize precise planning and documentation during the initial stages.

3. I'm considering a custom application. Should I focus on a desktop, mobile or web app?  

We can offer software consultancy services to determine the type of software you need based on your specific requirements. Please explore what type of app development would suit your custom build product.   

  • A web application runs on a web browser and is accessible from any device with an internet connection. (e.g., online store, social media platform)   
  • Mobile app developers design applications mainly for smartphones and tablets, such as games and productivity tools. However, they can be extended to other devices, such as smartwatches.    
  • Desktop applications are installed directly on a computer (e.g., photo editing software, word processors).   
  • Enterprise software manages complex business functions within an organization (e.g., Customer Relationship Management (CRM), Enterprise Resource Planning (ERP)).

4. My software product is complex. Are you familiar with the Scaled Agile methodology?

We have been in the software engineering industry for 30 years. During this time, we have worked on bespoke software that needed creative thinking, innovation, and customized solutions. 

Scaled Agile refers to frameworks and practices that help large organizations adopt Agile methodologies. Traditional Agile is designed for small, self-organizing teams. Scaled Agile addresses the challenges of implementing Agile across multiple teams working on complex projects.  

SAFe provides a structured approach for aligning teams, coordinating work, and delivering value at scale. It focuses on collaboration, communication, and continuous delivery for optimal custom software development services. 

5. How do I choose the best collaboration model with ASSIST Software?  

We offer flexible models. Think about your project and see which models would be right for you.   

  • Dedicated Team: Ideal for complex, long-term projects requiring high continuity and collaboration.   
  • Team Augmentation: Perfect for short-term projects or existing teams needing additional expertise.   
  • Project-Based Model: Best for well-defined projects with clear deliverables and a fixed budget.   

Contact us to discuss the advantages and disadvantages of each model. 

ASSIST Software Team Members

See the past, present and future of tech through the eyes of an experienced Romanian custom software company. The ASSIST Insider newsletter highlights your path to digital transformation.

* I read and understood the ASSIST Software website's terms of use and privacy policy.

Follow us

© 2025 ASSIST Software. All rights reserved. Designed with love.