How to use ActiveRecord Callbacks in Rails

Rails3Callbacks are a great technique for achieving simplicity and flexibility. A callback allows you to run some code (usually a method) automatically when another piece of code runs. In Rails, you’ll commonly see callbacks that run before, after or even around other bits of code. Callback functions are minimizing the length of codes in controllers.

Implementing Callbacks

There are four types of callbacks accepted by the callback macros:

  • Method references (symbol)
  • Callback objects
  • Inline methods (using a proc)
  • Inline eval methods (using a string) – deprecated

Here is the list of some useful callback functions while saving AcriveRecord objects

  • before_save
  • after_save

before_save:

This method is called before an ActiveRecord object is saved.

class Post < ActiveRecord::Base before_save :update_slug protected def update_slug self[:slug] = [year, season_slug, season_type_slug].compact.join '/' end end

after_save:
Once the active record object saved some method will be fired in that scenario we have to use the after_save callback.

class Post < ActiveRecord::Base after_save :handle_status_changed protected def handle_status_changed Setting.create(:post_id=>self.id , :status => true) end end

How To Implement Event Calendar In Rails App

Event calendar is a way to show multiple, overlapping events across calendar days and rows. This is an interface to add events, edit events, & destroy event. In Rails there is a gem/plugin “event_calendar” to implement it just like Google calendar.

The following steps demonstrate the implementation of event_calendar in both Rails 2.3.x and Rails3.x environment.

Step#1 –

Installing the gem/plugin

  • In rails 2.3.x

Install the required plugin from below path

script/plugin install git://github.com/elevation/event_calendar.git

Generate the necessary static file and example

script/generate event_calendar
  • In rails 3.x

Install the required gems

gem 'event-calendar', :require => 'event_calendar'

Run “bundle install

You can also use as a Plugin, to install plugin

rails plugin install git://github.com/elevation/event_calendar.git

Generate the necessary static file for the event calendar

rails generate event_calendar

Step#2

Include the necessary style sheet & java-script into your layout/view

<%= stylesheet_link_tag "dialog","fullcalendar","jquery-ui","style" %>
<%= javascript_include_tag "jrails1/fullcalendar.js","jrails1/jquery-
ui.js","jrails1/gcal.js","jrails1/jrails.js","jrails1/jquery.validate.js"%>

Step#3

Create a migration file to add necessary columns as follows

class CreateEvents < ActiveRecord::Migration
def self.up
create_table :events do |t|
t.string :name
t.datetime :start_at
t.datetime :end_at
t.timestamps
end
end
def self.down
drop_table :events
end
end

Step#4

Add the necessary paths to the “config/routes” file

  • In Rails 2.3.x
map.calendar '/calendar/:year/:month', :controller => 'calendar', :action => 'index',
 
:requirements => {:year => /d{4}/, :month => /d{1,2}/}, :year => nil, :month => nil
  • In Rails3.x
match '/calendar(/:year(/:month))' => 'calendar#index', :as => :calendar, :constraints => {:year => /d{4}/, :month => /d{1,2}/}

Step#5

Change the Event model to add the calendar as follows

class Event < ActiveRecord::Base
has_event_calendar
end

Step#6

Modify the Calendar controller as follows

class CalendarController < ApplicationController
def index
@month = (params[:month] || Time.zone.now.month).to_i
@year = (params[:year] || Time.zone.now.year).to_i
@shown_month = Date.civil(@year, @month)
@event_strips = Event.event_strips_for_month(@shown_month)
end
end

Step#7

You can also override the events method in helpers/calendar_helper.rb

module CalendarHelper
def month_link(month_date)
link_to(I18n.localize(month_date, :format => "%B"), {:month => month_date.month, :year => month_date.year})
end
# custom options for this calendar
def event_calendar_options
{
:year => @year,
:month => @month,
:event_strips => @event_strips,
:month_name_text => I18n.localize(@shown_month, :format => "%B %Y"),
:previous_month_text => "<< " + month_link(@shown_month.prev_month),
:next_month_text => month_link(@shown_month.next_month) + " >>"
}
end
def event_calendar
calendar event_calendar_options do |args|
event = args[:event]
%(<a href="/events/#{event.id}" title="#{h(event.name)}">#{h(event.name)}</a>)
end
end
end

Step#8

Add the following code to display the calendar in the view file

<%= event_calendar %>

See Also: Security Checks you must do before Rails App release

I hope it helps you. Planning anything in Ruby on Rails? Get in touch with Andolasoft experts. Feel free to give your valuable feedback.

How To Generate Barcode Using Barby Gem In Rails 2.3.8

A barcode is a series of vertical black lines with white spaces in between. This series of lines and spaces can be read by a device that can decode them. This would be a barcode reader.

In Ruby on Rails there is a gem called “barby” which generates the barcode with various format.

Here is an example to create barcode using barby & Rails 2.3.8.

Step#1

Include the barby gems in your config/environment.rb file

config.gem'barby'
config.gem 'barby-chunky_png'
config.gem 'png''RubyInline'

Install the gems by running the commandrake gems:install. Restart the Rails server.

You might face problem to start the server after the gems installed.Comment out the gems “png” & “RubyInline” in the “config/environment.rb” to get the server started.

Step#2

Create a folder named “Barcodes” to store the barcode images in your “Public” folder.

Step#3

Add the below lines of code in your controller

require'barby'
'barby/outputter/png_outputter'

Step#4

The following method will generate the barcode images and store in the “/public/Barcodes” path. Place this method inside the controller.

The “symbology” is the format in which the barcode will be generated. Default is “Code128B”, If you want to generate in different format you can set the “symbology” according to it.

def generate_barcodes(data) # check to see if we don't already have this barcode image uri = CGI.escape(symbology) + '_' + CGI.escape(data) + '.jpg' fname = RAILS_ROOT + '/public/Barcodes/' + uri #fname = '/var/www/html/arc_cloud/arcdevelopment/' + uri
 
# if the barcode image doesn't already exist then generate and save it
if ! File.exists?(fname)
 
str = 'Barby::'+symbology+'.new("'+data+'")'
 
begin
barcode = eval str
rescue Exception => exc
barcode = Barby::Code128B.new(data) # fall back to Code128 type B
end
 
File.open(fname, 'w') do |f|
f.write barcode.to_jpg
end
 
end
uri
end

Step#5

Following lines of code will call to generate your dynamic barcode
generate_barcodes(@item_id)

Step#6

To show the Barcode images call the following lines of code

<img src="/Barcodes/<%= @job_info.job_number %>.jpg" >

How to shorten URL using “bitly.com” in Rails 3.x

rorURL shortening is a technique on the World Wide Web (WWW) in which a Uniform Resource Locator (URL) may be made substantially shorter in length and still direct to the required page.

This is achieved by using an HTTP Redirect on a domain name that is short, which links to the web page that has a long URL. This is especially convenient for messaging technologies such as Twitter and Identical which severely limit the number of characters that may be used in a message.

Many web developers pass descriptive attributes in the URL to represent data hierarchies, command structures, transaction paths or session information. This can result in URLs that are hundreds of characters long and that contain complex character patterns. Such URLs are difficult to memorize and manually reproduce. As a result, long URLs must be copied-and-pasted for reliability. Thus, short URLs are more convenient for websites.

Step# 1

  • To begin with, create an account at bit.ly “
  • Get your API key by the following URL

“http://bit.ly/account/your_api_key/”

Step# 2

  • In rails 3.x

Write the following gems in your gemfile

gem 'bitly'
  • Run “bundle install”

Step# 3

Add the following code in your controller

require 'bitly'

Step# 4

Bitly recently released their version 3 API. From this 0.5.0 release, the gem will continue to work the same but also provide a V3 module, using the version 3 API. The standard module will become deprecated, as Bitly do not plan to keep the version 2 API around f orever.

To move to using the version 3 API, call in you top of the controller:

Bitly.use_api_version_3

Step# 5

To shorten a URL

bitly = Bitly.new('your-bitly-user-id','your-bitly-api-key') page_url = bitly.shorten('your-url') shorten_url = page_url.short_url

It will generate the bitly URL similar to “http://bit.ly/7BWXcQ”

How to add AJAX Pagination using jQuery in Rails3

Ruby_on_railsAjax pagination will do the same functionality of pagination without refreshing the page. It calls the action through jQuery to display the results per page.

This example demonstrates the implementation of ajax pagination in Rails3. However the same can be used with Rails2.3.x.

Remember to add jQuery to your paths.

Step#1

Add the following gem to your Gemfile

gem 'will_paginate'
Run bundle install

Step#2

Include the following code in the controller you want to paginate, For example, I have used Posts controller.

class PostsController < ApplicationController
  def index
    @posts = Post.paginate(page: params[:page], per_page: 10)
  end
end

Step#3

Add this in the view “posts/index.html.erb” file

<div id=”post_id”>
<%=render partial:’posts’%>
</div>

Encapsulate the order list in the partial view “posts/_posts.html.erb”

<ul>
<% @posts.each do |post|%>
<li>
<!-- Show post data -->
</li>
<% end %>
</ul>
<% = will_paginate(@posts,:id=>”ajax_paginate”)%>
 
<script>
 
$(document).ready(function() {
$(“#ajax_paginate”).find(“a”).each(function(){
var linkElement = $(this);
var paginationURL = linkElement.attr(“href”);
linkElement.attr({“url”:paginationURL, “href”: ”#”});
linkElement.click(function(){
$(“#post_id”).html(‘<div align= “center”><br/>
<img src=”/images/loader.gif”/></div>’)
$(“#post_id”).load($(this).attr(‘url’));
Return false;
});
});
});
 
</script>

The last line “”ajax_paginate”) %>” will generate your pagination links

Voila, You are done!

Polymorphic Associations in Rails3

ror31In polymorphic associations, a model can belong to more than one model, on a single association.

Here is an example where a model is associated with two other models in Rails3. For example we have Events and Article model which have comments. So the “Comment” model is common between the “Event” and “Article” model. Here are the steps to implement the polymorphic association between these three models.

Step#1
Let’s create a resource “Comment” by rails generator.

rails g scaffold Comment content:text

Step#2

Add associations in the models as below

Comment model:

class Comment < ActiveRecord::Base
attr_accessible :commentable_id, :commentable_type, :content
belongs_to :commentable, :polymorphic => true  #Now, it is acted as polymorphic
end

Event model:

class Event < ActiveRecord::Base
attr_accessible :name
has_many :comments, :as => :commentable
end

Article model:

class Article < ActiveRecord::Base
attr_accessible :name
has_many :comments, :as => :commentable
end

Step#3

Add the following attributes in the migration files of the comment model

Look for newly created file under “db/migrate” folder

class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.text :content
t.references :commentable, :polymorphic => true
t.timestamps
end
end
end

Then execute rake db: migrate in the command line

Step#4

Add nested resources inside the “config/routes.rb” file

resources :events  do
resources :comments
end
resources :articles do
resources :comments
end

Step#5

Add link to add new comments in view page of article and events as follows

In “/app/views/events/show.html.erb”

<%= link_to 'New comment', new_event_comment_path(@event)  %>

In /app/views/articles/show.html.erb

<%= link_to 'New comment', new_article_comment_path(@article)  %>

Step#6

Changing the form_for tag in new comment page

In “/app/views/comments/_form.html.erb”

Before

<%= form_for (@comment) do |f| %>

After

<%= form_for [@commentable, @comment] do |f| %>

Add following codes in both “Articles” & “Events” controllers to get the comments individually

In “/app/controllers/events_controller.rb”

def show
@event = Event.find(params[:id])
@comments= @event.comments #added to view all the comments for the selected event
respond_to do |format|
format.html # show.html.erb
format.json { render json: @event }
end
end

In “/app/controllers/articles_controller.rb”

def show
@article = Article.find(params[:id])
@comments= @article.comments #added to view all the comments for the selected article
respond_to do |format|
format.html # show.html.erb
format.json { render json: @article }
end
end

Step#8

Add the following codes to “Comments” controller to creating a comment

In “/app/controllers/comments_controller.rb”

class CommentsController < ApplicationController
def new
@commentable = find_commentable
@comment = Comment.new
end
def create
@commentable = find_commentable
@comment = @commentable.comments.build(params[:comment])
if @comment.save
flash[:notice] = "Successfully created comment."
redirect_to :id => nil
else
render :action => 'new'
end
end
 
private
 
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
end

Now the comment model will work as a polymorphic association between article and event model.