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 install Ruby on Rails with Sybase anywhere adapter on Windows


Installing Rails on Windows and using Sybase as db for the first time is a pain. So I thought to write a how to:

1) Download latest stable release of Ruby from http://rubyforge.org/frs/?group_id=167 on to your computer.

2) Run the executable and follow the onscreen instructions.

3) Once Ruby is installed successfully then go to command prompt and type ruby -v then hit enter. If everything was done properly then you will see the version of ruby, something like this

ruby 1.8.6 (date ...) [..]

4) Now you need to download the latest gem from http://rubyforge.org/frs/?group_id=126

5) Unzip it and then go to the command prompt again and type ruby setup.rb.

6) This will install the gem package manager. To be sure if everything went OK type gem -v on the command prompt to see the version of gem installed on your machine.

7) Now, to install rails run gem install rails --include-dependencies and wait while it is installed.

8) Once this process is complete then run rails -v and you should get the rails version as the output.

To communicate your rails app with Sybase you need to follow these steps.

1) Download sybaseanywhere_adapter.zip file (by Michael Scott)

2) Inside you have two ruby files and a read me file:

  • Put sybaseanywhere_adapter.rb file under your ruby installation, i.e., ruby\lib\ruby\gems\1.8\gems\activerecord-1.13.2\lib\active_record\connection_adapters
  • Put sybaseanywhere.rb file file under your ruby installation, i.e., ruby\lib\ruby\gems\1.8\gems\activerecord-1.13.2\lib\active_record\vendor
  • Now add sybaseanywhere in ruby\lib\ruby\gems\1.8\gems\activerecord-1.13.2\lib\active_record.rb file like this
    RAILS_CONNECTION_ADAPTERS = %w( mysql postgresql sqlite firebird sqlserver db2 oracle sybase openbase frontbase sybaseanywhere )

3) Now create a directory called ADO, if you don’t already have it under your ruby installation directory, for example, ruby\lib\ruby\site_ruby\1.8\DBD

4) Download rub-dbi package from http://rubyforge.org/projects/ruby-dbi/ unzip it and put the ruby-dbi\lib\dbd\ADO.rb under your newly created directory ruby\lib\ruby\site_ruby\1.8\DBD\ADO

5) Your database.yml will also look a bit different like this

development:
adapter: sybaseanywhere
dsn: dsn_name
mode: DBI:ADO

Obviously, you have to create your dsn name using windows control panel. Now thats something off topic and I imagine you already know how to do this.

On windows you can use Aptana as your IDE (download from here) since it is free and has plugins for rails, svn, etc.