Ruby on Rails CRUD and API tutorial | ASSIST Software Romania
get in touch
>

LIKE

SHARE

Facebook Share Tweet LinkedIn Share

FOLLOW

LinkedIn Follow Xing Follow
sebastian-varlan-rails-developer

Rails Developer at ASSIST

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.

Vous souhaitez nous contacter ? 

Si vous êtes intéressés par nos services de développement de logiciel, si vous souhaitez rejoindre notre équipe, ou si vous souhaitez tout simplement en savoir plus sur nous, nous sommes à votre disposition. Contactez-nous ! Écrivez-nous et un membre de l'équipe ASSIST vous répondra dans les plus brefs délais. Nous pourrons certainement vous ASSISTer.

CONTACTEZ-NOUS