Thursday, 16 March 2017

How to verify facebook token and gmail acceess token and fetch user info.

Suppose that we didn't have facebook app_id, app_secret or gmail client_id and client_secret but we have to verify the provided token.

In this blog, we will verify token with using open graph api's of facebook. For sending a request we will use HTTParty.

Now in controller,

For Facebook -


    def verify_facebook_token
      token = params[:token]   
      response = HTTParty.get("https://graph.facebook.co/me?fields=email,name&access_token=#{token}")
          if response.code == 200
            user_data = JSON.parse(response.body)
      end       
    end

For Gmail -


    def verify_gmail_token
      token = params[:token]   
      response = HTTParty.get("https://www.googleapis.com/oauth2/v2/userinfo", headers: {"Access_token" => token, "Authorization" => "OAuth #{token}"})
          if response.code == 200
            user_data = JSON.parse(response.body)
      end       
    end


Above method return result like this -

    {"email"=>"er.sonukr@gmail.com", "name"=>"Sonu", "id"=>"416806898668956"}

Note - Gmail provides three types of token. i.e. id_token, access_token, refresh_token. We have to use access_token for userinfo api's.

Sunday, 12 March 2017

How to make a class method and callback in ruby module



1) Callback in module -

Let's assume we have two model Provider and Consumer. Both model have same callback of before_create :generate_refresh_token. So, in this case we can make a module.

Let's create a module in models/concerns/token_generator.rb

   
    module TokenGenerator

      extend ActiveSupport::Concern

      included do
        before_create :generate_refresh_token
      end

   
      def generate_token
        SecureRandom.urlsafe_base64
      end           
   
      private

      def generate_refresh_token
        if self.refresh_token.blank?
          begin
        self.refresh_token = generate_token
          end while self.class.exists?(refresh_token: self.refresh_token)
        end
      end

    end


Now, in include above module in models Consumer.rb and Provider.rb

    class Consumer < ApplicationRecord

      #==== Modules ==================
      include TokenGenerator

    end


    class Provider < ApplicationRecord

      #==== Modules ==================
      include TokenGenerator

    end


2) Class method in module

Now, suppose that we have same class method of regenerate_refresh_token in both models. From this method we want to find the object and regenerate refresh token and update the same attribute.


So, in models/concerns/token_generator.rb


      def self.included(resource)
        def resource.regenerate_refresh_token(refresh_token)
          resource = self.where(refresh_token: refresh_token).take
          if resource
        resource.update_attributes(refresh_token: resource.generate_token)
        resource
          end
        end
      end


Now we can call above method as a class method like

        Consumer.regenerate_refresh_token

            OR

        Provider.regenerate_refresh_token           

Thursday, 2 March 2017

How to use Docker

In this blog, We are going to explain the concepts of Docker and integrate it with Rails app.

Let's first understand what is Docker ?

    Docker is a bit like a virtual machine. But unlike a virtual machine, rather than creating a whole virtual operating system, Docker allows applications to use the same Linux kernel as the system that they're running on and only requires applications be shipped with things not already running on the host computer. This gives a significant performance boost and reduces the size of the application.

    Docker is a tool designed to make it easier to create, deploy, and run applications by using containers.

Now, You are thinking what are containers?

    Operating system (OS) virtualization has grown in popularity over the last decade as a means to enable software to run predictably and well when moved from one server environment to another. Containers provide a way to run these isolated systems on a single server/host OS.

    Containers sit on top of a physical server and its host OS, e.g. Linux or Windows. Each container shares the host OS kernel and, usually, the binaries and libraries, too. Shared components are read-only, with each container able to be written to through a unique mount. This makes containers exceptionally “light” – containers are only megabytes in size and take just seconds to start, versus minutes for a VM.

    The benefits of containers often derive from their speed and lightweight nature; many more containers can be put onto a server than onto a traditional VM. Containers are “shareable” and can be used on a variety of public and private cloud deployments, accelerating dev and test by quickly packaging applications along with their dependencies. Additionally, containers reduce management overhead. Because they share a common operating system, only a single operating system needs care and feeding (bug fixes, patches, etc). This concept is similar to what we experience with hyper-visor hosts; fewer management points but slightly higher fault domain. Also, you cannot run a container with a guest operating system that differs from the host OS because of the shared kernel – no Windows containers sitting on a Linux-based host.


We can conclude, how Containers are differ from Virtual Machines ?

    Using containers, everything required to make a piece of software run is packaged into isolated containers. Unlike VMs, containers do not bundle a full operating system - only libraries and settings required to make the software work are needed. This makes for efficient, lightweight, self-contained systems that guarantees software will always run the same, regardless of where it’s deployed.

Install Docker in you system -

    Here we are going to install Docker in Ubuntu 16.10. If you have different Os please refer Get Docker

    You can download this docker.sh script and keep it in home directory and install by running -

        $ sh docker.sh

    OR

    You can install docker by running these command manually -

    $ sudo apt-get install -y --no-install-recommends \
        apt-transport-https \
        ca-certificates \
        curl \
        software-properties-common

    $ curl -fsSL https://apt.dockerproject.org/gpg | sudo apt-key add -
        apt-key fingerprint 58118E89F3A912897C070ADBF76221572C52609D

    $ sudo add-apt-repository \
           "deb https://apt.dockerproject.org/repo/ \
           ubuntu-$(lsb_release -cs) \
           main"

    $ sudo apt-get update
   
    $ sudo apt-get -y install docker-engine

    $ sudo apt-get update


Verify that Docker installed correctly by running the hello-world image.

   
    $ sudo docker run hello-world


Integrate Docker with Rails application

    Go to your app directory and make a file Dockerfile. In which we install all the system dependencies packages.

    In Dockerfile


        FROM ubuntu:latest
        MAINTAINER Sonu Kumar <er.sonukr@gmail.com>
        # Ignore APT warnings about not having a TTY
        ENV DEBIAN_FRONTEND noninteractive
        # Ensure UTF-8 locale
        RUN locale-gen en_US.UTF-8
        ENV LANG en_US.UTF-8
        ENV LC_ALL en_US.UTF-8
        RUN dpkg-reconfigure locales
        # Set the Ruby version of your preference
        ENV RUBY_VERSION 2.3.0
        # Install build dependencies
        RUN apt-get update -qq && \
            apt-get install -y -qq \
              build-essential \
              ca-certificates \
              curl \
              git \
              libcurl4-openssl-dev \
              libffi-dev \
              libgdbm-dev \
              libpq-dev \
              libreadline6-dev \
              libssl-dev \
              libtool \
              libxml2-dev \
              libxslt-dev \
              libyaml-dev \
              software-properties-common \
              wget \
              zlib1g-dev \
              mysql-client \
              libmysqlclient-dev \
              libsqlite3-dev \
              imagemagick \
              libmagickwand-dev \
              nodejs \
              zip
        # Install ruby via ruby-build
        RUN echo 'gem: --no-document --no-ri' >> /usr/local/etc/gemrc &&\
            mkdir /src && cd /src && git clone https://github.com/sstephenson/ruby-build.git &&\
            cd /src/ruby-build && ./install.sh &&\
            cd / && rm -rf /src/ruby-build && ruby-build $RUBY_VERSION /usr/local
        # Install bundler currently  we're using this but we should not.
        RUN gem install bundler
        ENV APPLICATION_NAME=Your_app_name
        # Clean up APT and temporary files when done
        RUN apt-get clean -qq && \
            rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
        RUN mkdir -p /$APPLICATION_NAME
        WORKDIR /$APPLICATION_NAME
        ADD Gemfile /$APPLICATION_NAME/Gemfile
        ADD Gemfile.lock /$APPLICATION_NAME/Gemfile.lock
        RUN bundle install
        ADD . /$APPLICATION_NAME


Above file prepare all the system dependencies of our application.

Now, make another file in docker-compose.yml. These settings will download the image and will create containers. Here, I am using services for mysql and memcached. You can use different services as per your application requirements.

    In docker-compose.yml



        version: '2'
        services:
          db:
            restart: always
            image: 'mysql:5.7'
            environment:
              MYSQL_ROOT_PASSWORD: *******
            ports:
              - "3306:3306"
            volumes:
              - "../shared/.mysql-data:/var/lib/mysql"

        memcached:
            restart: always
            image: memcached
            ports:
              - "11211:11211"

       
        web:
            depends_on:
              - 'db'
              - 'memcached'
            build: .
            environment:
              RAILS_ENV: development
              MEMCACHED_HOST: memcached
            command: bundle exec rails s -p 3000 -b '0.0.0.0'
            volumes:
              - .:/your_app
            ports:
              - "3000:3000"

We have to configure our database.yml for using above host. So, add host as db in database.yml

        In database.yml


            development: &default
              adapter: mysql2
              encoding: utf8mb4
              collation: utf8mb4_unicode_ci
              reconnect: true
              database: docker_development
              pool: 15
              reaping_frequency: 25
              username: root
              password: ********
              host: db
              port: 3306

Now, we have to build docker services

   
    $ sudo docker-compose build

Up the docker infrastructure by running. It will run you rails server also 

    $ sudo docker-compose up

You can run all rake commands by preceding docker-compose exec web

    ex-

        docker-compose exec web rake db:create
       
        docker-compose exec web rails c
       
        docker-compose exec web mysql -u root -p

        docker-compose exec web tail -f log/*.log

   





   

   







   

   

Friday, 24 February 2017

Skip password validation of Devise gem.

In general if we need to skip validation we can do it by :

    user.save(validate: false)

validate: false skips validation from all the attributes.

But what if we need skip validation on particular field like password validation of devise gem.

In User.rb

    attr_accessor :skip_password_validation

    private

           def password_required?
                 return false if skip_password_validation
              super
           end

In registrations_controller.rb

    def configure_sign_up_params
        params.require(:user).permit(:email, :password, :password_confirmation, :skip_password_validation)
    end

Now, whenever you want to skip password validation, pass skip_password_validation params as true

    user.skip_password_validation = true
    user.save

It will create User without password.

Thursday, 16 February 2017

Executing ubuntu shell commands in ruby programming


1. system
   
    The system method calls a system program. We have to provide the command as a string argument to this method.
    This will always return value is either true, false or nil.

    Example -
       
        system("df -h")
   
    Above command gives disk information but it will return true.

       Filesystem      Size  Used Avail Use% Mounted on
        udev            1.9G     0  1.9G   0% /dev
        tmpfs           386M  6.4M  380M   2% /run
        /dev/sda1       141G   74G   61G  56% /
        tmpfs           1.9G  523M  1.4G  28% /dev/shm
        tmpfs           5.0M  4.0K  5.0M   1% /run/lock
        tmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup
        /dev/sda5       314G   67M  298G   1% /drive
        cgmfs           100K     0  100K   0% /run/cgmanager/fs
        tmpfs           386M   76K  386M   1% /run/user/1000
         => true

    system eats up all the exceptions. So the main operation never needs to worry about capturing an exception raised from the child process.

2. exec

    By using Kernel#exec replaces the current process by running the external command. The method can take a string as argument. When using     more than one argument, then the first one is used to execute a program and the following are provided as arguments to the program to be invoked.

    Example -

        exec 'date'

    Above command returns system date like this

         =>    Fri Feb 17 10:27:16 IST 2017

3. Backticks

    Backtick returns the standard output of the operation. As opposed to the above approach, the command is not provided through a string,         but by putting it inside a backticks pair.

    Example -

        `date`

    Above command returns system date like this

         =>    "Fri Feb 17 10:32:35 IST 2017\n"

    Backtick operation forks the master process and the operation is executed in a new process. If there is an exception in the sub-process then that exception is given to the main process and the main process might terminate if exception is not handled.

4. %x()

    Using %x is an alternative to the back-ticks style. It allows you to have different delimiter.

    Example -

        %x('date')

     Above command returns system date like this

         => "Fri Feb 17 10:37:14 IST 2017\n"

5. Open3.popen3

    Sometimes the required information is written to standard input or standard error and you need to get control over those as well. Here         Open3.popen3 comes is very usefull

    Example -

        require 'open3'
        cmd = 'git push origin master'
        Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
          puts "stdout is:" + stdout.read
          puts "stderr is:" + stderr.read
        end

6. $?

    You can check process status by running $?.

Thursday, 9 February 2017

Response and exception handling in Rails 5 Api only.


We will use --api argument to tell Rails that we want an API application.

Create a rails 5 api application by running -

    $ rails new todos --api

Now, you can not that Make ApplicationController  inherit from ActionController::API  instead of ActionController::Base and it has not generated view files.

Now, generate a controller by using scaffold -

    $ rails g scaffold User first_name last_name

We will responds with JSON and an HTTP status code 200 by default. For this we will write it in concern.

In app/controllers/concerns/response.rb

    module Response
      def json_response(object, status = :ok)
        render json: object, status: status
      end
    end

Now, Suppose that we have to find a User by id. In this case where the record does not exist, ActiveRecord will throw an exception ActiveRecord::RecordNotFound. We'll rescue from this exception and return a 404 message.

Also, we will rescue ActiveRecord::RecordInvalid for the case of invalid record and it will return HTTP code 422.

So, make a module in app/controllers/concerns/exception_handler.rb -

    module ExceptionHandler
      extend ActiveSupport::Concern

      included do
        rescue_from ActiveRecord::RecordNotFound do |e|
          json_response({message: e.message}, :not_found)
        end

        rescue_from ActiveRecord::RecordInvalid do |e|
          json_response({message: e.message}, :unprocessable_entity)
        end

        rescue_from StandardError do |e|
          json_response({message: e.message}, :unprocessable_entity)
        end
      end
    end

Include these modules in the application controller.

    class ApplicationController < ActionController::API
      include Response
      include ExceptionHandler
    end

Now, in users controller we can use json_response helper for response.

    class UsersController < ApplicationController
      before_action :set_user, only: [:show, :update, :destroy]

      # GET /users
      def index
        @users = User.all
        json_response(@users)
      end

      # GET /users/1
      def show
        json_response(@user)
      end

      # POST /users
      def create
        @user = User.create!(user_params)
        json_response(@user, :created)
      end

      # PATCH/PUT /users/1
      def update
        @user.update(user_params)
        head :no_content
      end

      # DELETE /users/1
      def destroy
        @user.destroy
        head :no_content
      end

      private
      # Use callbacks to share common setup or constraints between actions.
      def set_user
        @user = User.find(params[:id])
      end

      # Only allow a trusted parameter "white list" through.
      def user_params
        params.permit(:first_name, :last_name)
      end
    end

Note that we are using create! instead of create because as we know that create! raise a exception.

You can customize the error message like this -

    def create
      user = User.new(user_params)
      if user.save
        json_response(user)
      else
            json_response({error: 'User has not created'}, :unprocessable_entity)
      end
    end



Saturday, 4 February 2017

Elasticsearch with Rails 5


In this article, we will introduce you to Elasticsearch and show you how to install, configure and start using it with ruby on rails.

Elasticsearch is a platform for distributed search and analysis of data in real time. Its popularity is due to its ease of use, powerful features, and scalability.

Elasticsearch supports RESTful operations. This means that you can use HTTP methods (GET, POST, PUT, DELETE, etc.).

If it is your first time with Elasticsearch and you don't have Elasticsearch install in your system for this you can follow digital ocean documentation or you can simply install by

Update your ubuntu package

    $ sudo apt-get update

Download the latest Elasticsearch version, which is 2.3.1 at the time of writing.

    $ wget https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/deb/elasticsearch/2.3.1/elasticsearch-2.3.1.deb

Then install it with dpkg.

    $ sudo dpkg -i elasticsearch-2.3.1.deb

To make sure Elasticsearch starts and stops automatically with the server, add its init script to the default runlevels

    $ sudo systemctl enable elasticsearch.service

Now that Elasticsearch and its Java dependencies have been installed, it is time to configure Elasticsearch. The Elasticsearch configuration files are in the /etc/elasticsearch directory.

To start editing the main elasticsearch.yml configuration file with nano or your favorite text editor.

    $ sudo nano /etc/elasticsearch/elasticsearch.yml

Remove the # character at the beginning of the lines for cluster.name and node.name to uncomment them, and then update their values

    . . .
    cluster.name: mycluster1
    node.name: "My First Node"
    . . .

These the minimum settings you can start with using Elasticsearch. However, it's recommended to continue reading the configuration part for more thorough understanding and fine-tuning of Elasticsearch.


Now, we will integrate elasticsearch with rails.

To get started, grab the latest Ruby on Rails and add following below gems to your Gemfile.

    gem 'elasticsearch-rails'
    gem 'elasticsearch-model'

Open the model file at app/models/user.rb, and add the Elasticsearch includes. This will allow us to use the Elasticsearch methods on our model, and will also enable the Elasticsearch callbacks for events such as creating, updating, and destroying our model objects, which will keep the Elasticsearch index up to date.

    class User < ActiveRecord::Base
        include Elasticsearch::Model
        include Elasticsearch::Model::Callbacks
    end

Now, we have to call the import method on the User model. This is needed because our search index is empty and we need to populate it with our current data. Any subsequent changes to the User table will automatically be added to the index by the Elasticsearch callbacks, so you wont need to run the import method again, unless changes are made outside of the Rails app.

So, Open up the rails console and run

    User.import

Now, you can start searching the User model. By default this will search all the columns in this model.

    User.search("abc").records