Wednesday, January 28, 2015

super vs super() in Ruby

class A
  attr_reader :stack

  def initialize
    @stack = Array.new
  end
end

class B < A
  attr_reader :name

  def initialize(args={})
    super
    @name = args.fetch(:name, nil)
  end
end

When I ran the following code, I got an ArgumentError
b = B.new({:name => 'Ruby'})

ArgumentError: wrong number of arguments (1 for 0)
The error complained that I was passing in 1 argument for the initialize method in class A. The reason the ArgumentError appears is super in the subclass will take with it any parameters that were sent to the initialize method. To avoid sending the parameters, call super with parentheses. Thus, the initialize method for class B should be

def initialize(args={})
  super()
  @name = args.fetch(:name, nil)
end

Tuesday, August 6, 2013

Rails action caching with querystring parameters

We can cache a particular action with its query string parameters in rails as follows :

caches_action :action_name, :cache_path => Proc.new { |c| c.params }

Use of "!~" operator in Ruby

"!~" can be used to have conditional statements to check if string doesn't match particular regular expression. So that whenever we want to check if particular string is not matching a regular expression we can avoid having negative conditional statements using "unless" like

unless "str" =~ /reg_exp/
 # do something
end

We can write this conditional statement as assertive condition as follows:

if "str" !~ /reg_exp/
 # do something
end

Interpolating Instance, Class level or Global variable in Ruby

When the expression to be interpolated into the string literal is simply a reference to a global, instance or class variable, then the curly braces may be omitted.

So the following should all work: 

@first_name = "Anil"
puts "#@first_name Galve"  #=> "Anil Galve"

@@first_name = "Anil"
puts "#@@first_name Galve" #=> "Anil Galve"

$first_name = "Anil"
puts "#$first_name Galve"  #=> "Anil Galve"

Monday, August 5, 2013

before_save vs before_validate in Ruby On Rails

If we want to manipulate data before saving into database we tend to use before_save for example if we want to trim users first name before saving to database we would normally use before_save callback and will do something like below:

before_save :trim_first_name

def trim_first_name
  first_name = first_name.strip
end

But there is gotcha into it, it will skip validation for updated first_name because before_save callback gets executed after validations. So lets say, if there uniqueness validation for first_name and if there is already user with first_name "anil" present in database and if user specify "anil " then that user will be inserted since later one has extra space and it skips that validation and before saving into database it strips the first_name and defeats the purpose of our validation.

Hence, whenever we want to manipulate data before saving into database its good idea to have before_validation callback instead of before_save callback.

Same can be achieved like below:

before_validation :trim_first_name

def trim_first_name
  first_name = first_name.strip
end

Wednesday, April 11, 2012

Tracking ajax requests in google analytics

Recently I had one requirement from client to capture even ajax requests in application for google analytics reports.

I changed google analytics account for capturing dynamic content and added following javascript code in application.js file and it worked.

$(function() {
// Log all jQuery AJAX requests to Google Analytics
$(document).ajaxSend(function(event, xhr, settings){
if (typeof _gaq !== "undefined" && _gaq !== null) {
_gaq.push(['_trackPageview', settings.url]);
}
});
});

Saturday, March 3, 2012

Delete Vs. Destroy In Rails

I’ve been writing this web app that has the following models: Order, Recipient, Message. An order has many recipients and a recipient has many messages. The recipients are also dependent upon the order and the messages are dependent upon the recipient.

In Ruby code this looks like:
Order.rb

class Order < ActiveRecord::Base
has_many :recipients, :dependent => :destroy
has_many :messages, :through => :recipients
end

Recipient.rb

class Recipient < ActiveRecord::Base
belongs_to :order
has_many :messages, :dependent => :destroy
end

The idea here is that when I delete an order, I also delete any associated recipients and any associated messages. My controller looked like this:

def delete
Order.delete(params[:id])
end

There are a couple things wrong with this. The first and most important thing is that when I delete a row in the order table, it leaves orphaned rows in the order and messages table. I want to delete these rows as well! The next thing is that this isn’t RESTful design. Instead of calling my method “delete,” let’s call it “destroy.” To fix the issue though, we need to use another method that has subtle difference than delete. Instead of delete, I should be using the destroy method. Why is that?

The delete method essentially deletes a row (or an array of rows) from the database. Destroy on the other hand allows for a few more options. First, it will check any callbacks such as before_delete, or any dependencies that we specify in our model. Next, it will keep the object that just got deleted in memory; this allows us to leave a message saying something like “Order #{order.id} has been deleted.” Lastly, and most importantly, it will also delete any child objects associated with that object!

Now my code in my controller looks like this.

def destroy
Order.destroy(params[:id])
end

Whenever I delete an order object, it will delete all child recipient and message rows in the database . This prevents any orphaned rows and allows for consistency in the database!