Tuesday, November 1, 2016

Subclassing ActiveModelSerializers

In a rails application, when it comes to an API response, ActiveModelSerializers eases a lot of burden on rendering the output in the required format. 
ActiveModel::Serializer gives us a simple layer between the model and the controller that lets us to call to_json on an ActiveRecord object or collection while responding with our desired API format.

But, in many scenarios, we may want to expose an object in more than one format. In such cases, the easiest thing to do is to create a duplicate version of the serializer and render with them as per the need. For Example, assume we have a user object and we need two flavors of user details, one for the financial department and the other for HR department. We can define the following two serializers.


Financial Department
class EmployeeSerializer < ActiveModel::Serializer
   attributes :id, :name, :salary, :worked_hours
end
HR Department
class ResourceSerializer < ActiveModel::Serializer
   attributes :id, :name, :experience, :skills
end


This is absolutely fine for such simple serializers. Assume the following scenario. Where we need simple and complete details of an object(say Person) in two different serializers. We can define them as follows.


Simple Details
class SimpleSerializer < ActiveModel::Serializer
   attributes :name, :dob, :skills
   attribute :total_experience do
     object.past_positions.inject(0, total) do |position|
       total + position.experience_in_years
     end
   end
   attribute :avg_peer_rating do
     sum = object.peer_ratings.inject(0, total) do |rating|
       total + rating.value
     end
     sum / object.peer_ratings.size
   end
end
Complete Details
class CompleteSerializer < ActiveModel::Serializer
   attributes :name, :dob, :skills
   attribute :total_experience do
     object.past_positions.inject(0, total) do |position|
       total + position.experience_in_years
     end
   end
   attribute :avg_peer_rating do
     sum = object.peer_ratings.inject(0, total) do |rating|
       total + rating.value
     end
     sum / object.peer_ratings.size
   end
   attribute :location_history do
     object.residential_locations.map(&:name)
   end
   attribute :personal_intrests do
     object.hobbies.map{|h| h.formatted_s}
   end
end

But, we can notice that we have duplicated all the code highlighted in blue. But, that's what we do in ruby. we believe in DRY principle. 

This duplicate code can be avoided by inheriting CompleteSerializer from SimpleSerialiser as given below.


Simple Details
class SimpleSerializer < ActiveModel::Serializer
   attributes :name, :dob, :skills
   attribute :total_experience do
     object.past_positions.inject(0, total) do |position|
       total + position.experience_in_years
     end
   end
   attribute :avg_peer_rating do
     sum = object.peer_ratings.inject(0, total) do |rating|
       total + rating.value
     end
     sum / object.peer_ratings.size
   end
end
Complete Details
class CompleteSerializer < SimpleSerializer
   def initialize(obj, options = {})
     super(obj, options)
   end

   attribute :location_history do
     object.locations.map(&:name)
   end
   attribute :personal_interests do
     object.hobbies.map{|h| h.formatted_s}
   end
end


Thursday, April 25, 2013

Ruby: Symbol is not a variable. Its the Value


Even some experienced ruby developers misunderstands this sometimes. A symbol in ruby is misunderstood to a variable. And this misunderstanding is because of the following syntax.

an_hash = { :key1 => "value1", :key2 => "value2", :key3 => "value3" }

The code :key1 => "value1" may look like an assignment. But it is not. It is the syntax.

Try this in irb..


irb(main):001:0> :data = "a_value"
SyntaxError: (irb):1: syntax error, unexpected '=', expecting $end
:data = "a_value"
       ^
from /home/vinoth/.rvm/rubies/ruby-1.9.3-p392/bin/irb:13:in `<main>'

irb(main):002:0> :data => "a_value"
SyntaxError: (irb):2: syntax error, unexpected tASSOC, expecting $end
:data => "a_value"
        ^
from /home/vinoth/.rvm/rubies/ruby-1.9.3-p392/bin/irb:13:in `<main>'

irb(main):003:0> :data
=> :data



Consider the following hash.


another_hash = { "key1" => "value1", "key2" => "value2", "key3" => "value3" }

Here we can see the key-value pairs. Here in another_hash, the string "key1" is a key. Similarly, in an_hash, the symbol :key1 is a key.

Don't ask the value of a symbol. A symbol, by itself is a value. 

Object Oriented Ruby - Part-I


An irb command speaks more than paragraphs.

All Primitives are Objects

irb(main):001:0> 56.is_a? Object
=> true     # 56 is an integer. Its not just a number. Its an Object.
irb(main):002:0> 56.class
=> Fixnum   # 56 is an object of the class Fixnum

irb(main):001:0> "hello!".is_a? Object
=> true     # "hello!" is a string. Its not just a string. Its an Object.
irb(main):002:0> "hello!".class
=> String   # "hello!" is an object of the class String

irb(main):001:0> (:data).is_a? Object
=> true     # :data is a symbol. Its also an Object.
irb(main):002:0> (:data).class
=> Symbol   # :data is an object of the class Symbol

Classes are Objects of the class 'Class'

irb(main):001:0> Fixnum.is_a? Class
=> true # Fixnum is a class. Its pretty clear.
irb(main):002:0> Fixnum.is_a? Object
=> true # What!! Fixnum is also an Object?
irb(main):003:0> Fixnum.class
=> Class # Yes. Fixnum is an object of the class Class. And so are the Othe classes.

Have a look at this too.

irb(main):001:0> Class.is_a? Object
=> true
irb(main):002:0> Class.is_a? Class
=> true
irb(main):003:0> Class.class
=> Class  # Class is the object of the class Class


What is an Object then??

irb(main):001:0> Object.is_a? Object
=> true # Object is an object. Straight forward.
irb(main):002:0> Object.is_a? Class
=> true # OOh!! Object is a class too.
irb(main):003:0> Object.class
=> Class # Object is an object of the class 'Class'


There is something called Module

irb(main):001:0> require 'singleton'
=> true # Singleton is a module that comes with ruby. Lets inspect this
irb(main):002:0> Singleton.is_a? Module
=> true # A module is a module
irb(main):003:0> Singleton.is_a? Class
=> false # A module is not a class
irb(main):004:0> Singleton.is_a? Object
=> true # A module is also an Object
irb(main):005:0> Singleton.class
=> Module # A module is an Object of the class Module
irb(main):006:0> Module.class
=> Class # Same as above


So, Everything is object here.



...... to be continued  ......

Tuesday, February 26, 2013

Implement Stack and Queue using Array in Javascript

Stack and Queue are the most commonly used data-structures in many situations.
In javascript, we can implement these two data-structures very easily using Array.

Array Methods used:
    1. push     : adds the specified element(parameter) to the array at the end
    2. pop       : removes the last element in the array and returns it
    3. shift      : removes the first element of the array and returns it
    4. unshift : inserts the specified element(parameter) to the array in its 0th(first) position
   
Implementing a Stack:
    Stack implies Last-In First-Out. Element inserted at last should be removed first.

  We can implement a stack in any one of these two methods
      1. push and pop method
              push adds the element at the end
              pop removes the last element

              Example:
                 
             var items = [ 'pen', 'pencil' ];
                  items.push('sharpner');           // items becomes [ 'pen', 'pencil', 'sharpner' ]
                  items.push('eraser');                // items becomes [ 'pen', 'pencil', 'sharpner', 'eraser' ]
                  var op1 = items.pop();             // items becomes [ 'pen', 'pencil', 'sharpner' ]
                  alert(op1);                                    // op1 is assigned with 'eraser'
                  var op2 = items.pop();             // items becomes [ 'pen', 'pencil' ]
                  alert(op2);                                    // op2 is assigned with 'sharpner'




      2. unshift and shift
              unshift adds the element in the first
              shift removes the first element
             
              Example:
             
             var items = [];
                 items.unshift('sharpner');       // items becomes [ 'sharpner']
                 items.unshift('eraser');            // items becomes [ 'eraser', 'sharpner']
                 var op1 = items.shift();            // items becomes [ 'sharpner']
                 alert(op1);                                     // op1 is assigned with 'eraser'
                 var op2 = items.shift();            // items becomes []
                 alert(op2);                                     // op2 is assigned with 'sharpner'

   
    'push and pop' method is more efficient than the other, because it involves less shifts in array elements.

Implementing a Queue:
    Queue implies First-In First-Out. Element inserted at first should be removed first.

  We can implement a queue in any one of these two methods
      1. push and shift method
              push adds the element at the end
              shift removes the first element

              Example:
                 
                 var items = [];
                 items.push('sharpner');                // items becomes [ 'sharpner' ]
                 items.push('eraser');                // items becomes [ 'sharpner', 'eraser' ]
                 var op1 = items.shift();            // items becomes [ 'eraser']
                 alert(op1);                                // op1 is assigned with 'sharpner'
                 var op2 = items.shift();            // items becomes []
                 alert(op2);                                // op2 is assigned with 'eraser'



      2. unshift and pop
              unshift adds the element in the first
              pop removes the last element
             
              Example:
             
             var items = [];
                 items.unshift('sharpner');            // items becomes [ 'sharpner']
                 items.unshift('eraser');            // items becomes [ 'eraser', 'sharpner']
                 var op1 = items.pop();                // items becomes [ 'eraser']
                 alert(op1);                                // op1 is assigned with 'sharpner'
                 var op2 = items.pop();                // items becomes []
                 alert(op2);                                // op2 is assigned with 'eraser'