Sunday 23 July 2017

Polymorphic routing to get the path of different resource

Suppose that we have three types of resources and we have three model as Employee, Employer and Manager.

Now we also have separate dashboard action in controller and After sign in we have to redirect to dashboard path according to the resource.

employees controller -

 
 class EmployeesController < ApplicationController
  
   def dashboard
         # some_code
   end 
 end


employers controller -


  
 class EmployersController < ApplicationController
  
   def dashboard
         # some_code
   end 
 end


managers controller -


  
 class ManagersController < ApplicationController
  
   def dashboard
         # some_code
   end 
 end


And routes would look like this:


 resources :employees do
   member do
     get 'dashboard'
   end
 end

 resources :employers do
   member do
     get 'dashboard'
   end
 end

 resources :managers do
   member do
     get 'dashboard'
   end
 end


In this scenario we can use switch case:


 case current_user
 when Manager
   dashboard_manager_path
 when Employer
   dashboard_employer_path
 when Employee
   dashboard_employee_path
 end


Don't you think it can be re-factor!

Rails provides polymorphic_path that makes polymorphic url generation much easier and simpler. There is also a method named polymorphic_url which is the same as the polymorphic_path except that polymorphic_url generate the full url including the host name.


These methods are useful when you want to generate the correct URL or path to a RESTful resource without having to know the exact type of the record in question.

It also provides support for nested resources.

So, we can re-factor our code using ploymorphic_path helper method:


 polymorphic_path([:dashboard, current_user])

Sunday 16 July 2017

Remove particular XML tag with Nokogiri

Suppose that we have XML -


xml_content = <?xml version="1.0"?>
     <book>
        <author>Gambardella, Matthew</author>
        <title>XML Developer's Guide</title>
        <genre>Computer</genre>
        <price>44.95</price>
        <publish_date>2000-10-01</publish_date>
        <description>An in-depth look at creating applications 
        with XML.</description>
     </book>


And we need to remove <genre> tag but keep the inside that tag -


 <?xml version="1.0"?>
    <book>
       <author>Gambardella, Matthew</author>
       <title>XML Developer's Guide</title>
       Computer
       <price>44.95</price>
       <publish_date>2000-10-01</publish_date>
       <description>An in-depth look at creating applications 
       with XML.</description>
    </book>


We can achieve this with Nokogiri -


 
require 'nokogiri'
doc = Nokogiri::XML 'xml_content'
doc.xpath('//genre').each do |tag|
  tag.replace(Nokogiri::XML::Text.new(tag.text, tag.document))
end
doc.inner_html
 

Sunday 9 July 2017

Get synonyms and antonyms of a word in Rails.

In this blog, we will integrate Big Huge Labs Thesaurus API in our Rails app for getting synonyms and antonyms of a word. For this we will use dinosaurus gem.

So, in Gemfile.

 gem 'dinosaurus'

Run bundle.

Before initializing this we have to get an api key for configuration. We can get it from here.

For initializing, create a file dinosaurus.rb in config/initializer and put below code in this file.


 
 Dinosaurus.configure do |config|
   config.api_key = 'your_api_key'
 end 
 

Now, we can use it as

 > Dinosaurus.synonyms_of('word')

 => ["news", "intelligence", "tidings", "discussion", "give-and-take", "parole", "word of honor", "Son", "Word", "Logos", "password",   "watchword", "countersign", "Bible", "Christian Bible", "Book", "Good Book", "Holy Scripture", "Holy Writ", "Scripture", "Word of God",  "arcanum", "computer memory unit", "hypostasis", "hypostasis of Christ", "info", "information", "language", "language unit",   "linguistic unit", "oral communication", "order", "positive identification", "promise", "religious text", "religious writing", "sacred   text", "sacred writing", "secret", "speech", "speech communication", "spoken communication", "spoken language", "statement", "voice   communication", "give voice", "formulate", "phrase", "articulate", "evince", "express", "show"]


  > Dinosaurus.antonyms_of('synonyms')

  => ["antonym"]


You can get synonyms and antonyms together with lookup method. It will return a hash like this


 > Dinosaurus.lookup('word')

  => {"noun"=>{"syn"=>["news", "intelligence", "tidings", "discussion", "give-and-take", "parole", "word of honor", "Son", "Word",   "Logos", "password", "watchword", "countersign", "Bible", "Christian Bible", "Book", "Good Book", "Holy Scripture", "Holy Writ",   "Scripture", "Word of God", "arcanum", "computer memory unit", "hypostasis", "hypostasis of Christ", "info", "information", "language",  "language unit", "linguistic unit", "oral communication", "order", "positive identification", "promise", "religious text", "religious   writing", "sacred text", "sacred writing", "secret", "speech", "speech communication", "spoken communication", "spoken language",   "statement", "voice communication"]}, "verb"=>{"syn"=>["give voice", "formulate", "phrase", "articulate", "evince", "express", "show"]}}

Sunday 2 July 2017

Debugging Rails application in Docker with byebug

During development of any application we need debugging in our application. For this rails provides many tools like byebug. Byebug stop the application inside the code.
But when you are using it with docker, we have to do some simple configuration in our docker-compose.yml file.
As we know that base requirement is to run the whole application within a container. Using docker-compose this is fairly simpleWe need a compose file which covers a web container that runs the rails server command.
When using docker-compose in combination with byebug this needs to be added to make it work properly. 
So, add below code in your docker-compose.yml

 
web: ...
  stdin_open: true
  tty: true
 


Now, we have to run docker-compose in daemon mode and attach to the web container.


  
  
  $ docker-compose up -d

  $ docker attach myapp_web_1
 
 

Monday 26 June 2017

Generate random meaningful word, sentence or paragraph in Rails.

Sometimes we need generate randome meaningful sentences or paragraph for our app. We can acheive it in rails app with literate_randomizer gem.

So, in Gemfile-


gem 'literate_randomizer'


Run bundle

Now, this will provide LiterateRandomizer global Randommizer instance as LiterateRandomizer.global

We can use it simply like this -

    a) Generate word

		> LiterateRandomizer.word
		
		=> "Early"


		
		 > LiterateRandomizer.sentence

		 => "Surely we have believed."


    c) Generate paragraph

		> LiterateRandomizer.paragraph

		 => "Two hours later. ILLINGWORTH laughing and I. Meantime we should open the glare of the moon which. Faced by their own 			downfall. Anything more than actual specimen in this account of the dark indicate vegetable. While we should. Such is like two 			half-breeds from my return to mitigate. A fellow-countryman in his chair. Written upon the precipice we might there was no."


You can do customization in LiterateRandomizer global Randommizer instance.

As example -


	 > LiterateRandomizer.paragraph(:sentences => 2, :words => 5)

	 => "Visitin my house ready for. To-night however which took a!"

Saturday 17 June 2017

Convert speech to text using watson api's in Rails

The Watson api's Speech to Text service of IBM® provides an API that lets you add speech transcription capabilities to your applications. To transcribe the human voice accurately, the service leverages machine intelligence to combine information about grammar and language structure with knowledge of the composition of the audio signal.

To get service credentials, follow these steps:

    1. Log in to Bluemix at https://bluemix.net. If you don't have an account, sign   up here for a 30-day free trial.

    2. Create an instance of the service:

        a) In the Bluemix Catalog, scroll down to Services and select the Speech To Text service from Watson.

        b) Under Add Service, type a unique name for the service instance in the Service name field. For example, type my-service-name. Leave the default values for the other options.

        c) Click Create.

    3. Copy your credentials:

        a) On the left side of the page, click Service Credentials to view your service credentials.

        b) Copy username and password from these service credentials and paste them into the watson.yml file

Make a watson.yml file in config

In watson.yml

default: &default
   auth_url: https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/speech-to-text/api
   watson_url: wss://stream.watsonplatform.net/speech-to-text/api/v1/recognize?watson-token=
   user_name: username
   password: password
   params:
      action: start
      content-type: audio/wav
      continuous: true
      inactivity_timeout: -1
      interim_results: true

 development:
   <<: *default

 test:
   <<: *default

 staging:
   <<: *default

 production:
   <<: *default 


In Gemfile:

 gem 'activesupport'
 gem 'eventmachine'
 gem 'websocket-client-simple'

Run bundle.

Make a File.rb file in config/intializer. In which we will define a instance method for an audio file.

 class File
   def read_chunk(chunk_size=2000)
     yield read(chunk_size) until eof?
   end
 end


Now, we will create a method for speech to text conversion in which will take an audio file as an argument.

   WATSON = YAML.load_file(File.join(Rails.root, 'config', 'watson.yml'))[Rails.env]

   def speech_to_text(wav_file)
     params = WATSON['params']

     token = ''
     uri = URI.parse(WATSON['auth_url'])
     Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
       request = Net::HTTP::Get.new(uri)
       request.basic_auth WATSON['user_name'], WATSON['password']
       token = http.request(request)
     end

     watson_url = WATSON['watson_url']+"#{token.body}"
     file_url = wav_file #replace this with the file you want to read
     init_message = params.to_json
     ws = ''
     # run websocket in an EventMachine
     EM.run {
       ws = WebSocket::Client::Simple.connect watson_url
       file_sent = false

       ws.on :message do |event|
  data = JSON.parse(event.data)
  if data['state'] && data['state'] == 'listening'
    if !!file_sent
      EM::stop_event_loop
    else
      file_sent = true
      open(file_url, 'rb') do |file|
        file.read_chunk { |chunk| ws.send(chunk, type: :binary) }
      end
      ws.send("", type: :binary)
    end
  elsif data['results'] && data['results'].first['final']
    puts data['results'].first['alternatives'].first['transcript'] if data['results'].first['alternatives']
  end

       end

       ws.on :open do
  puts "-- websocket open"
  puts init_message
  ws.send(init_message)
       end

       ws.on :close do |e|
  puts "-- websocket close #{
  if e!=nil then
    (e)
  end}"
  exit 1
       end

       ws.on :error do |e|
  puts "-- error (#{e.inspect})"
       end
     }
     ws.close
   end

Sunday 11 June 2017

Allow serialized attributes with unknown keys to be permitted in strong parameters.

Suppose that, we have Attempt model and we have serialized an attribute in attempt.rb like this



class Attempt < ApplicationRecord

 #==== Serializations ==================
   serialize :response

 end


Now, if you are creating attempt through strong parameters in controller -

   
   
Attempt.create(attempts_params)


And you have permitted response attribute in strong parameters like this


 def attempts_params
     params.require(:attempt).permit(:response)
 end


        OR

   

 def attempts_params
     params.require(:attempt).permit(:response => {})
 end


Above strong parameters will save response as nil or blank. In this scenario we have to permit keys of serialized attributes in strong parameter



 def attempts_params
     response_keys = params[:attempt][:response].keys
     params.require(:attempt).permit(response: response_keys)
 end

Saturday 3 June 2017

Twilio Phone Number authentication with Authy in Ruby on Rails.

Authy is a Twilio service that provides two factor authentication as an API, making it easy to secure users accounts. Using authy services we can authenticate users by their phone number. OTP will be send on phone number and it will be verified at the twilio end.


In Gemfile.

    # Use Authy for sending token
    gem 'authy'
    # Use Twilio to send confirmation message
    gem 'twilio-ruby'

We need an API key for Authy. You can get this from your Twilio account portal. Click the link to access the Authy dashboard.

If you don’t already have an Authy account, this will set one up for you. You will need to verify your email address and set up two factor authentication. Then you can create an application with Authy and this will give you your API key.

Create a new file authy.rb in config/initializers.

In authy.rb


    Authy.api_key = 'api_key'

    Authy.api_uri = 'https://api.authy.com/'

Now, we can start phone verification via sending a sms.

In sessions controller


     def send_otp

         response = Authy::PhoneVerification.start(via: "sms", country_code: 1, phone_number: "111-111-1111")

         render json: {response: response.message}, status: response.code

     end


    def verify_otp

        response = Authy::PhoneVerification.check(verification_code: "1234", country_code: 1, phone_number: "111-111-1111")

        if response.ok?

              # verification was successful

            end       

    end

In routes.rb


    resources :sessions do

        collection do

          post :send_otp

          post :verify_otp

        end

    end

Friday 26 May 2017

Newsletter Subscription in Shopify and connecting it to HubSpot

If you need newsletter subscription in your Shopify e-commerce, first you have to select the theme in which newsletter sign up form is available. As many Shopify themes provides a basic newsletter sign up form in the footer or right column.

But, It does nothing when you click submit button because of the newsletter sign up form is not connected to the Shopify backend.

For proper working We have to replace email signup form with this code -



{% form 'customer' %}
        {{ form.errors | default_errors }}
        {% if form.posted_successfully? %}
          <p class="form--success">{{ 'general.newsletter_form.confirmation' | t }}</p>
        {% else %}
          <div class="input-group">
            <input type="hidden" name="contact[tags]" value="newsletter">
            <label for="Email" class="newsletter__label label--hidden">{{ 'general.newsletter_form.email_placeholder' | t }}</label>
            <input type="email" value="{% if customer %}{{ customer.email }}{% endif %}" placeholder="{{ 'general.newsletter_form.email_placeholder' | t }}" name="contact[email]" id="Email" class="input-group__field newsletter__input" autocorrect="off" autocapitalize="off">
            <span class="input-group__btn">
              <button type="submit" class="btn newsletter__submit" name="commit" id="Subscribe">
                <span class="newsletter__submit-text--large">{{ 'general.newsletter_form.submit' | t }}</span>
              </button>
            </span>
          </div>
        {% endif %}
 {% endform %}

When properly connected, a newsletter sign up will be fed to HubSpot via Hubshoply and show as a conversion event. You can get it in customers section of Shopify and contacts in HubSpot.


Friday 19 May 2017

Categorized words according to parts of speech from english sentence in Ruby

In the English language, words can be considered as the smallest elements that have distinctive meanings. Based on their use and functions, words are categorized into several types or parts of speech.

In this blog we will define and examples for major parts of speech from English sentence with using ruby gem engtagger .



 require 'rubygems'
 require 'engtagger'


 # Initialize a parser object
 tgr = EngTagger.new

 # Sample text
 text = "Ruby is an expressive, dynamic programming language."

 # Add part-of-speech tags to text
 tagged = tgr.add_tags(text)

 # Get all nouns from a tagged output
 nouns = tgr.get_nouns(tagged)

 => {"Ruby"=>1, "programming"=>1, "language"=>1}

 # Get all the adjectives
 adj = tgr.get_adjectives(tagged)

 => {"expressive"=>1, "dynamic"=>1}

 # Get all the verbs
 adj = tgr.get_verbs(tagged)

 => {"is"=>1}
 
 
 
 
 

Thursday 11 May 2017

Fetch all products from Shopify api



Suppose, If your store contains more than 50 products and you wish to fetch all products from store.

When you call a shopify api's like this -

products = ShopifyAPI::Product.all

Above api will fetch maximum of 50 products but you can use limit parameter to set limit of products in every call of api's like this -

products = ShopifyAPI::Product.find(:all,:params =&gt; {:limit =&gt; 250})

But above api's also returns only 250 products. What if you have more then 250? Can’t you just increase the limit to the total number of products in your catalog to 1000? As simple as it sounds, it doesn’t quite work in that way… Shopify uses a technique called pagination, which basically divides the response to your request into separate memory chunk.

So, we can use pagination technique to fetch all products from shopify -
count = ShopifyAPI::Product.count
       page = 1
       products = []
       while count > 0 do
         products << ShopifyAPI::Product.find(:all, :params => {:page => page})
         count = count - 50
         page = page + 1
       end
 products.flatten!

It will return all products of your shopify store.

Sunday 7 May 2017

Fetch products from Shopify and create or update metafields with key value of each product with Shopify api's.

Sometime, it becomes essentials to add a customized metafield in product so,we can add some functionality with the help of these metafields.
In this blog, we will fetch products from a store of shopify and create our customized metafield in which we will add pdf file url for each product.

 ############ Required Dependencies ##############


    require 'rubygems'

    require 'shopify_api'



    ############ Shopify Credentials ################


    API_KEY = '846bef1--------------------------'

    PASSWORD = '2e0eed--------------------------'

    SHOPNAME = 'store_name_of_shopify-----------'

    shop_url = "https://#{API_KEY}:#{PASSWORD}@#{SHOPNAME}.myshopify.com/admin"


    ##### Fetch Products and create metafields ######   

    begin

      ShopifyAPI::Base.site = shop_url

      products = ShopifyAPI::Product.all

      products.each do |product|

        metafield = ShopifyAPI::Metafield.new(key:'pdf_url_s3',

                                          namespace: "headerlabs",

                                          value: 'http://docs.aws.amazon.com/AmazonS3/latest/dev/s3-dg.pdf',

                                          value_type: "string")

        product.add_metafield(metafield)

      end

    rescue => e

      puts e.inspect

    end

Now, you can access these metafields in template of product in shopify liquid file

    {% assign headerlabs = product.metafields.headerlabs %}

    {% assign key = 'pdf_url_s3' %}

    <a href={{ headerlabs.pdf_url_s3}} target="_blank" > 

Sunday 23 April 2017

Update attr_accessor wiithin accepts_nested_attributes_for in Rails


Suppose that we have association like this -

        class Employer < ApplicationRecord
          
          has_one :account
          accepts_nested_attributes_for :account

        end 


and
        class Account < ApplicationRecord

          belongs_to :employer
          attr_accessor :area

        end


In above association account belongs_to employer and has attr_accessor attributes :area.

Now, we have form like this -
        <%= form_for(@employer) do |f| %>
        
            <%= f.fields_for :account do |acc| %>
              <%= acc.file_field :account_number %>        
              <%= acc.file_field :area %>
            <% end %>
        <% end %>


So, we want to update account attributes within employer update method. For this we have to white-list it in employer strong parameter -

In employers controller,

    def update

        if @employer.update(employer_params)

          flash[:notice] = 'Employer updated Successfully'

          redirect_to employer_path

        else

          flash[:notice] = @employer.errors.full_messages.to_sentence

          redirect_to employer_path

        end

      end


    private

      def employer_params
        params.require(:employer).permit(:name, :email, :password, :role, account_attributes: [:id, :account_number, :area])
      end 


From above method it will update attr_accessor attributes only when we will update account_number attributes.

But what if we want only update attr_accessor attributes that is :area. It won't be updated if none of account attributes updating same time.

For updating attr_accessor wiithin accepts_nested_attributes_for we have to do couple of things -

In Account.rb
    

    class Account < ApplicationRecord

        
          belongs_to :employer
          attr_accessor :area


        def new_attr=(a)
          attribute_will_change!(:name)
          self.area = a
        end



    end


and in strong parameters of employers controller -
    def employer_params
      params.require(:employer).permit(:name, :email, :password, :role, account_attributes: [:id, :account_number, :new_attr])
    end

Thursday 30 March 2017

How to use Amazon DynamoDB with Ruby on Rails

In this blog we will discuss about Amazon DynamoDB and how to use it with Ruby on Rails application.
Amazon DynamoDB is a fully managed NoSQL database service that provides fast and predictable performance with seamless scalability.
NoSQL databases are designed for scale, but their architectures are sophisticated, and there can be significant operational overhead in running a large NoSQL cluster.
With DynamoDB, you can create database tables that can store and retrieve any amount of data, and serve any level of request traffic.
DynamoDB allows you to delete expired items from tables automatically to help you reduce storage usage and the cost of storing data that is no longer relevant.

Now, we will integrate it with Rails application. For this we can use aws-sdk gem.

So, in Gemfile
    gem 'aws-sdk', '~>2'


Run $ bundle

Now, we will configure Aws access. for this create config/initializers/aws.rb

In aws.rb
     Aws.config.update({
        region: 'us-west-2',
        credentials: Aws::Credentials.new(
'REPLACE_WITH_ACCESS_KEY_ID', 
'REPLACE_WITH_SECRET_ACCESS_KEY'),
      })



We can started by initializing a client object of DynamoDB by
    dynamodb = Aws::DynamoDB::Client.new


Now, we can create a table
    dynamodb.create_table({
        table_name: 'VenueOfferTable',
        attribute_definitions: [
          {attribute_name: 'Title',attribute_type:'S'},
          {attribute_name: 'LongDescription', attribute_type: 'S'}
        ],
        key_schema: [
          {attribute_name: 'Title', key_type: 'HASH'},
        ],
        provisioned_throughput: {
          read_capacity_units: 1,
          write_capacity_units: 1
        }
      })


Above code will create a table in DynamoDB.

Now we have a table so, we can add items by
    dynamodb.put_item({
      table_name: 'VenueOfferTable',
      item: {
        'Title' => 'Mill Valley Kitchen',
        'LongDescription' => 'Restaurant and Bar '
      }
    })


Update an item
    dynamodb.update_item({
        table_name: 'VenueOfferTable',
        key: {
          'Title' => 'Mill Valley Kitchen'
        },
        update_expression: 'SET LongDescription = :LongDescription',
        expression_attribute_values: {
          ':LongDescription' => 'Premium Restaurant and Bar'
        }
      })


Fetching the items from table
    response = dynamodb.get_item({
      table_name: 'VenueOfferTable',
      key: {
        'Title' => 'Mill Valley Kitchen'
      }
    })


We can scan full table. scan method can be used to perform a full table scan, which by default will return every item in a table

    response = dynamodb.scan(table_name: 'VenueOfferTable')

    items = response.items



There are many api's for querying to meet your requirement. You can get this from here.

Sunday 26 March 2017

Assignment of Ruby object_id

As we know that in ruby, nearly everything is an object and an object id is a unique identifier for that object. It is much like a fingerprint. All objects have an object id. In Ruby, the method .object_id returns an object’s unique identifier, which is presented by a number or a string of numbers.

For performance reasons true, false, nil and Fixnums are handled specially in ruby. For these objects there is a fixed value of object_id.

Let's check it on irb.

    2.3.0 :001 > false.object_id
     => 0
    2.3.0 :002 > true.object_id
     => 20
    2.3.0 :003 > nil.object_id
     => 8

Note that here we are using ruby 2.3.0. Value of true and nil object has changed from ruby 2.0.0. Before it is for true is 2 and for nil is 4.
You can get why it is changed from this link.

Now, what about fixnums?

Fixnums is in ruby also handled specially. Object id assignment to a fixnums is working on i*2+1.

    2.3.0 :004 > 1.object_id
     => 3
    2.3.0 :005 > 2.object_id
     => 5
    2.3.0 :006 > 3.object_id
     => 7

But, how it's works?

Ruby doesn't use the VALUE as a pointer in every instance. For Fixnums, Ruby stores the number value directly in the VALUE itself. That keeps us from having to keep a lookup table of every possible Fixnum in the system.

Actually, Fixnums are stored in the upper 31 bits, which means a shift left of one. Ruby use the lowest bit to mark that it is a Fixnum.

So, for example when we convert fixnum 4 into it's binary number. It will be 100.

Now, shift it to left and mark it is a fixnum. it will become now 1001. You can see that it is binary value of 9.

From above points, we can conclude that object_id of any other object like string or symbol always will be an even object_id.

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