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