Stored Procedures and Rails – Part 1


There is no documentation in Rails about how to use stored procedures or atleast it is difficult to find where to look at. And according to DHH stored procedures is not the Rails Way to do things. DHH mentioned in his post

I want a single layer of cleverness: My domain model. Object-orientation is all about encapsulating clever. Letting it sieve half ways through to the database is a terrible violation of those fine intentions. And I want no part of it.

I somewhat agree to what DHH has to say. And that’s all fine but what if we don’t have any other option apart from using stored procedure and our stored procedure has some complex logic which we don’t want to put in our Ruby code then here is a little hack to it

ActiveRecord::Base.connection.execute("execute procedure_name")

But the above code will not return anything it will only execute your procedure, considering everything went OK.

Moreover, it’s not DRY if everytime you have to write that line of code just to call a procedure.

Here is a better way to do it:

1) Create a class and let’s call it

Class DbStoredProcedure
  your methods here .......
end

2) Create a class method within it

def self.fetch_db_records(proc_name_with_parameters)
  ActiveRecord::Base.connection.execute(proc_name_with_parameters)
end

Then simply call it as

DbStoredProcedure.fetch_db_records("exec procedure_name 'args1', 'args2', 'and so on' ")

As mentioned above, this will only execute a procedure without returning any value. To return records or values from stored procedures can use other methods provided by the AR,

class DbStoredProcedure < ActiveRecord::Base

  def self.fetch_db_records(proc_name_with_parameters)
    connection.select_all(proc_name_with_parameters)
  end

  def self.insert_update_delete_calculate(proc_name_with_parameters)
    connection.execute(proc_name_with_parameters)
  end

  def self.fetch_val_from_sp(proc_name_with_parameters)
    connection.select_value(proc_name_with_parameters)
  end

end

And then simply call it like

DbStoredProcedure.method_name("exec procedure_name 'args1', 'args2', 'and so on' ")

Sweet…

If you know a better way to do it then I would love to know your views.

Stored Procedures and Rails – Part 2

RSS Feeds + Ruby on Rails + Web App


The Feedtools library is a very comprehensive and powerful Ruby library for handling rss, atom, etc as well as caching. It makes creating, consuming and manipulating feeds a piece of cake.

It’s ideal for parsing RSS feeds in Ruby on Rails applications.

Assuming that you already have installed Ruby and Rubygem, simply run

gem install feedtools

to install the FeedTools gem

or download it from the FeedTools project page and put the untar/unzipped folder in the vendor/plugins directory of your app.

To do a very quick test, create a file called testfeed.rb and add the below code in it:

    require "RubyGems"
    require "feed_tools"

    feedurls = 'http://www.sphred.com/combined_feed'
    # If you want to fetch more than one feed then comment the above feedurls variable and   uncomment the below one.
    #feedurls = %w(http://feeds.feedburner.com/Sphred_top_10_feeds   http://feeds.feedburner.com/Sphred_site_only http://feeds.feedburner.com/Sphred_site_feature)
    my_feeds = FeedTools::build_merged_feed feedurls

    my_feeds.title = 'Sphred.com Feed'
    my_feeds.copyright = 'SPhred'
    my_feeds.author = 'Nasir '
    my_feeds.id = "http://www.sphred.com/combined_feed"

    File.open('./my_feeds.xml', 'w') do |file|
      file.puts my_feeds.build_xml()
    end

Running this file from IRB will create a my_feeds.xml file in your current directory with all the feed contents.

To show feeds on a website, you need to do a few things:
1) Put

require "feed_tools"

at the top of your controller
2) Create an action within this controller to show your feeds, lets call that action user_data

    def user_data
      @feed = FeedTools::Feed.open(params[:feed_url])
      # You can first test it with a static feed url like this
      #@feed = FeedTools::Feed.open('http://www.sphred.com/combined_feed')
    end

3) In the corresponding view add this code

  <div class="feeds">
    <h3>
      <a href="<%= h @feed.link %>">
      <%= @feed.title %></a>
    </h3>
    <p><%= @feed.description %></p>
    <% for feed in @feed.items %>
      <div class="feed_item">
        <h4>
          <a href="<%= h feed.link %>">
          <%= feed.title %></a>
        </h4>
        <p><%= feed.description %></p>
     </div>
   <% end %>
 </div>

This is all good for development environment or for small apps but once you go to production environment then you have to think of caching to avoid hitting the feed server every time before displaying feed contents.

New features on SPhred.com

First, A big thanks to all the guys out there for registering and sending invitation to their friends/relatives to try out sphred.com

SPhred is currently in very early stages, like what other sites say ‘in beta’.

A few things are added on SPhred in the last couple of days:

1) Earlier you first had to create a post and then could add tags to it but now you can add tags while creating a post.

2) Now you can put a face to your name i.e. add a picture. This functionality is available by going to your profile page. The option is given just below “Profile for your name”. You can access your profile page after signing in by clicking on your email address part of ‘Signed in as your email address‘.

3) Page to view users who sphredded an item has been redone and looks much better now (atleast I think so). Have a look by clicking on the number of users who sphreaded an item. Or you can directly go here http://sphred.com/users_sphredding/9-tutsbuzzcom

4) Search is functional now though currently it only looks for the search term in a Sphred Item’s title or description.

6) Comments look much better now as you can see the picture of people who posted comments.

I would love to hear your feedback or suggestions i.e. what you would like to have on sphred and what you think isn’t working or won’t work.

Once again thank you all for using sphred.

Not binding your selection list to a particular model in Rails


In Rails, we use collection_select helper to display values from a particular model using a drop down but it is generally tied to a particular model, i.e. if we look at the generated html then we see something like

select name="customer[customer_search]" id="customer_customer_search"

What if we want something like:

select name="customer_search" id="customer_search"

Then we can simply use select_tag helper and get the values from our model like this

customers = Customer.find(:all, :order => 'first_name').map{|x| [x.full_name] + [x.id]}
select_tag(:customer_search, options_for_select(customers))

If we don’t want to display the values from model and would like to feed in something simple and manually, then

customers = [['text_to_display1', 'value1'], ['text_to_display2', 'value2']]
select_tag(:customer_search, options_for_select(customers))

If text_to_display and its value both are same then we can use something as simple as:

customers = ['wee', 'asdf']
select_tag(:customer_search, options_for_select(customers))

Pagination in Ruby On Rails using will_paginate plugin


We do pagination in Rails by using its built in paginate method in our controller


def display_data
@display_data_pages, @display_data = paginate(:location_data,
:conditions => ["loc.updated_at < ?", params[:date]],
:joins => "as loc inner join location_address as locadd on loc.id = locadd.id"
:per_page => 10,
:order => "location_name")
end

Often we would like to put this code inside our model mainly for two reasons:
1) Code Reuse, and
2) To keep the business logic where it belongs
But we couldn’t do that (since it is difficult to do) due to the paginate method and had to write the same code more than once in the controller and sometimes in more than one controller.
On top of that we have to put this chunk of code in our views only to show the pagination links
<div class="pagination">
<%= if @survdefault_pages.current.previous
link_to("< Prev", { :page => @survdefault_pages.current.previous })
end %>


<%= pagination_links(@survdefault_pages) %>

<%= if @survdefault_pages.current.next
link_to("Next >", { :page => @survdefault_pages.current.next})
end %>
</div>

We can put this code inside a partial but it is still a pain.

Moreover, Rails’ built in pagination will be out of Rails before it will reach version 2 which is not that far.

Update: Rails built in pagination is now removed but is still available as a plugin, ie, classic_pagination.

We have another option, use will_paginate plugin. The advantages of will_paginate plugin are:
1) Easy to use,
2) Less code in views to show pagination links, and
3) It can be used inside models

Follow these steps to use will_paginate plugin

1) Grab it, by going to the command prompt and change directory to the app root. Then run
ruby script/plugin install svn://errtheblog.com/svn/plugins/will_paginate
NOTE If the above code doesn’t installs the plugin in your vendor/plugins directory then you probably don’t have svn installed on your machine.

2) Now in our controller we can simply write

def display_data
@display_data = LocationData.paginate(:page => params[:page],
:conditions => ["loc.updated_at < ?", params[:date]],
:joins => "as loc inner join location_address as locadd on loc.id = locadd.id", :per_page => 10,
:order => "location_name")
end

:per_page and :page are required.
The best thing is, as mentioned above, we can move this code to the LocationData model that will help in keeping our controller clean and will also help in code reuse.
To do that, we can create a class method in our model like:

def self.display_location_data(update_date, page)
paginate(:page => page, :conditions => ["loc.updated_at < ?", update_date], :joins => "as loc inner join location_address as locadd on loc.id = locadd.id",
:per_page => 10,
:order => "location_name")
end

In our controller, the display_data method will now be replaced with just one line

def display_data
@display_data = LocationData.display_location_data(params[:date], params[:page])
end

In the view, the big chunk of code will be replaced by a single line to show our pagination links, like

<%= will_paginate @display_data %>

And we are done…

UPDATE: Formatting / Styling pagination links

How to get acts_as_attachement plugin working on mac osx


If you want to use acts as attachement for image upload/manipulation as well then first you need to install imagemagick (and its dependencies) and RMagick.

Before installing imagemagick you also need to install the following libraries as well:

1) libjpeg

Download it from http://www.ijg.org/files/jpegsrc.v6b.tar.gz

tar zxvf jpegsrc.v6b.tar.gz
cd jpeg-6b
cp /usr/share/libtool/config.sub .
cp /usr/share/libtool/config.guess .
./configure --enable-shared --enable-static
make
sudo make install
sudo ranlib /usr/local/lib/libjpeg.a

2) libpng

Download it from http://www.libpng.org

tar zxvf libpng-1.2.22.tar.gz
cd libpng*
./configure
make check
sudo make install
sudo ranlib /usr/local/lib/libpng.a

3) freetype

Download it from http://download.savannah.nongnu.org/releases/freetype/

tar zxvf freetype-2.3.5.tar.gz
cd freetype*
./configure
make
sudo make install

4) libwmf

Download it from http://wvware.sourceforge.net/libwmf.html

tar zxvf libwmf-0.2.8.tar.gz
cd libwmf*
./configure
make check
sudo make install

5) ghostscript

Download it from http://pages.cs.wisc.edu/~ghost/doc/gnu/index.htm

tar zxvf ghostscript-8.01.tar.gz
cd ghostscript*
./configure
make
sudo make install

Imagemagick installation
Download it from http://www.imagemagick.org/script/download.php

tar zxvf Imagemagick-6.3.2.tar.gz

cd Imagemag*
export CPPFLAGS=-I/opt/local/include
export LDFLAGS=-L/opt/local/lib
./configure –prefix=/opt/local –disable-static –with-modules –without-perl \
–without-magick-plus-plus –with-quantum-depth=8 \
–with-gs-font-dir=/opt/local/share/ghostscript/fonts
make
sudo make install

RMagick Installation
If ruby and gem package manager is installed on your machine then simply do
sudo gem install rmagick
To check whether it is installed properly;
– go to terminal and run
irb -rubygems -r RMagick
irb(main):001:0> puts Magick::Long_version

this should give you the following output

This is RMagick 1.15.10 ($Date: 2007/06/09 16:45:25 $) Copyright (C) 2007 by Timothy P. Hunter
Built with ImageMagick 6.3.2 10/28/07 Q8 http://www.imagemagick.org
Built for ruby 1.8.6 (2006-12-25 patchlevel 0) [i686-darwin8.9.1]]
Web page: http://rmagick.rubyforge.org
Email: rmagick@rubyforge.org

Installing rmagick from source

tar xvzf RMagick.tar.gz
cd RMagick*
./configure
make
sudo make install

Using Act_as_attachment
I was about to write this but then I found a very good tutorial on installing and using acts_as_attachment here.

Full text search using Ferret (acts_as_ferret) with rails

I recently started working with acts_as_ferret so I thought to put together a little how to:

Assuming you already have ruby on rails environment set up

1) To install it run gem install ferret
this will prompt you to select a gem for your platform

2) go to your rails project root directory and run
script/plugin install svn://projects.jkraemer.net/acts_as_ferret/tags/stable/acts_as_ferret

3) Add require 'acts_as_ferret' to your config/environment.rb

4) Resart your app

To add full text search capability to a model simply add this within your model

acts_as_ferret

To add full text search capability to a model but on some specific attributes/field_names add this

acts_as_ferret :fields => [ :author, :content ]

How to perform search?

If your model name is location then you can use

Location.find_by_contents(search_criteria)

Note: If you have very large number of records then it might take a while to run your search for the first time as it indexes all the records

If you want to use pagination or multiple models then use
Location.find_with_ferret query, :page => params[:page], :per_page => 10,
:multi => [ Model_2, Model_3 ]

I will be adding some advanced stuff later on …

How to get Gruff working with Rails on windows

NOTE: You can’t do gem install rmagick on windows since (as of now) rmagick gem is only for *nix systems

1) Download rmagick-win32 from http://rubyforge.org/frs/?group_id=12&release_id=15197

This also has imagemagick for 8 pixels so you don’t need to do a separate download for imagemagick. If you want imagemagick for 16 pixels then download it from here http://www.imagemagick.org/script/binary-releases.php

Imagemagick site says ’16 bitversion permits you to read or write 16-bit images without losing precision but requires twice as much resources as the Q8 version.’

3) Install Imagemagick

To confirm if imagemagick is installed properly go to your command prompt and type

convert logo: logo.gif
identify logo.gif
imdisplay logo.gif

this should display the imagemagick logo if everything was ok

4) Go to your command prompt and run gem update --system

5) Go the directory where you unzipped the downloaded rmagick-win32 file

6) Run gem install rmagick --local

after it is installed successfully then you should see

Successfully installed rmagick, version 1.15.9

7) Either run gem install gruff

OR

to use rails plugin. Go to your app root directory and run

ruby script/plugin install http://topfunky.net/svn/plugins/gruff

And you are done…