marked for destruction

Today I had gone through an issue, which got fixed by using the marked_for_destruction? method. This marked_for_destruction is part of Active Record Autosave Association module. Autosave Association module takes care of automatically saving associated records when their parent is saved. For more details see Auto Save Association .

In my project I have a model called Directory and it has many Categories. But I have to add a validation that there should be atleast one category associated with the directory. So in the directory model I added a validation in the after_save callback, which will check the count of Categories is greater that 0.


Write a named scope to fetch the data sorted by distance using Geokit

Recently I had to work on a feature "As a User ISBAT see the Business sorted by distance". We are using Geokit gem for manipulating the location. And we have the models 'Business' has many 'Location's.

I had to fetch the businesses in the order of the distance of the locations from the origin. The origin is the point which we will pass to the method. Since this method should be part of a chained named scope, I had to implement this as a named scope.

After done some searching I found a useful link from pivotallabs. At the end there is one comment from Keith:

named_scope :within, lambda{|o, d|
 origin = o
 distance_sql = self.distance_sql(origin)
 within = d
 {:select => "*, #{distance_sql} as distance",
  :conditions => "#{distance_sql} <= #{within}", 
  :order => 'distance asc'}}

This code helped me to create a named scope which will fetch the businesses in the order of the distance.

The test also passed for this named scope. But in the controller, where I am using this named scope along with other named scopes i,e, chained named scope, the named scope was not working as expected. It was throwing MySql Error with message "distance is undefined".

After done with some searching I found the link which explains that in chain named_scopes only conditions will get added, and selects will get ignored.

Then I tried by changing the 'distance' variable with the distance_sql as the order value. And it worked:

named_scope :by_location, lambda{|origin, within|
 distance_sql = Location.distance_sql(origin)
 {:select => "*",
  :conditions => "#{distance_sql} <= #{within}", 
  :order => '#{distance_sql}', :joins => :locations }}


acts_as_taggable_on gem have issue with after_save callback

Today I had spent a lot of time fixing an after_save callback issue related with acts_as_taggable_on gem. We're associating keyword tag to a model using the following command:

acts_as_taggable_on :keywords

And we've a after_save call back in that model which uses the updated keywords. But the issue was in the callback, if you reload the object you will lose the new keywords associated with it, because the keywords are not yet saved.

Then I Googled about this issue and found the following blog which helped me to solve the issue: I tried with the update_tags mentioned in the blog, but with the latest acts_as_taggable_on gem this fix is not working. Then I gone through the code of acts_as_taggable_on gem, and in core.rb I found the following line:

after_save :save_tags

Then I tried calling save_tags from my callback method. Thats it! It got fixed!!


Updated time_diff gem

Now with time_diff gem you can calculate the time differnce between two Time in the formatted form by passing a third parameter to the Time.diff() method.

If you are not passing any parameter then by default it will take the third parameter value as'%y, %M, %w, %d and %h:%m:%s' and it will return the formatted time difference in the form: '1 year, 2 months, 3 weeks, 4 days and 12:05:52'.

For hours, minutes and seconds have two formats, with text and without text. The parameter is with '%h', '%m', '%s' are the formats which won't add text with the value, ie., it return 3 for '3 hours'. The parameters with he formats '%H', '%N', '%S' will return the values with text, ie., '2 hours', '30 minutes'.

If you are using the default format ie., formats with comma seperated, then it will remove the intervals(year, month, ..) which are zero.

If you need only day and hours in the time difference you can specify that by passing parameter in the format of '%d %h'. This will calculate the formatted time diff text only for days and hours.


Create ruby gem using Jeweler

Recently I created a ruby gem time_diff using the help of jeweler. Jeweler is a gem using that you can create and manage ruby gems.
First install jeweler:

sudo gem install jeweler

Then create the scaffold for your gem using the command:

jeweler your-gem

This will create two directory test and lib. In lib folder you can create the files for your gem. In test folder you can create the files for tests. The above command will create some other files also like Rakefile, README.rdoc, Gemfile. You can add your dependencies to the Gemfile.

You can create the version using:

rake version:write

Then you can install the gem in your local machine using:

rake install

Then to release the gem to RubyGem:

rake release

You need a RubyGem account to push gem to your account.
For more information visit GitHub