Rails

Authlogic is Awesome

Have been tinkering around with authlogic. The most I love about is its out-of-the-box functionality. I used to wrestle with restful_authentication to get certain things that I need. Not in anyway that I’m bashing it but seeing how easy authlogic I couldn’t believe why I didn’t use it sooner.

I like it so much that I even made a rails template base on authlogic. This rails template has the usual basic signup/login/logout and I threw in some cucumber steps & stories in it. Here it is in flesh & bytes http://github.com/fadhlirahim/myrails-template/blob/master/template_authlogic.rb

My little contribution to a rails plugin (sort of)

Getting your bug fix/code pulled into the main repo really gets you excited & satisfied.

I never thought it could give me this much sense of enjoyment. Check it out.

http://github.com/dmix/weekly_builder/tree/master

Includes & Eager Loading

I’m figuring out something in my rails app.  I’m figuring out which one’s the worst:

Eager loading 100 rows of data you don’t actually need at the moment

or

10 queries giving 10 result set at once?

Here’s the code to explain it.

1
2
3
@event = Event.find(params[:event_id])
 
@event_attendees = @event.attendees.paginate(:page => params[:page], :per_page => 10)

In the view, for each attendees, it’s calling a purchase record. Since I’m using will_paginate and setting 10 records per page, for every 10 record of attendees, there’s 10 queries for a purchase record. Here’s the following SQL that will be generated:

1
2
3
4
5
6
7
8
9
10
11
12
SELECT * FROM `attendees` WHERE (`attendees`.event_id = 4)
 
SELECT * FROM `purchases` WHERE (purchasable_type = 'Attendee' AND purchasable_id = 1) LIMIT 1
SELECT * FROM `purchases` WHERE (purchasable_type = 'Attendee' AND purchasable_id = 2) LIMIT 1
SELECT * FROM `purchases` WHERE (purchasable_type = 'Attendee' AND purchasable_id = 3) LIMIT 1
SELECT * FROM `purchases` WHERE (purchasable_type = 'Attendee' AND purchasable_id = 4) LIMIT 1
SELECT * FROM `purchases` WHERE (purchasable_type = 'Attendee' AND purchasable_id = 5) LIMIT 1
SELECT * FROM `purchases` WHERE (purchasable_type = 'Attendee' AND purchasable_id = 6) LIMIT 1
SELECT * FROM `purchases` WHERE (purchasable_type = 'Attendee' AND purchasable_id = 7) LIMIT 1
SELECT * FROM `purchases` WHERE (purchasable_type = 'Attendee' AND purchasable_id = 8) LIMIT 1
SELECT * FROM `purchases` WHERE (purchasable_type = 'Attendee' AND purchasable_id = 9) LIMIT 1
SELECT * FROM `purchases` WHERE (purchasable_type = 'Attendee' AND purchasable_id = 10) LIMIT 1

Clearly you can that see the above code creates a n + 1 problem.

So I tried to modified it using eager loading like the following:

@event_attendees = @event.attendees.paginate(:include => :purchase, :page => params[:page], :per_page => 10)

Here’s the following SQL query generated:

1
2
3
SELECT * FROM `attendees` WHERE (`attendees`.event_id = 4)
SELECT `purchases`.* FROM `purchases` WHERE (`purchases`.`purchasable_id` IN (1,2,3,4..100) AND `purchases`.`purchasable_type` = 'Attendee')
 # query is shorten for brevity

You can see that it’s using 1 query that fetches 100 rows of data. At first I thought that it will limit the eager loading with my will_paginate per page settings. But clearly for every page that I’m viewing, it’s calling that query hence returning 100 rows of data for each page I’m viewing.

At the moment I’m using the query without eager loading. Simply because I’m concern the app is fetching 100 rows that I don’t need at once. I have no idea how to limit an eager loading association base on will _paginate per_page. Or probably I could eager load once and keep in cache. Or does rails does that automatically?

Will investigate though. Oh well, back to work!

Routes Gotcha

Something peculiar happened when I was doing something trivial.

If you accidently named your restful route the following

resource :roles instead of resources :roles

When you point your app to /roles it won’t go to your index controller action but it will instead call your show action.

Rebuilding Ferret Index

I had trouble reindexing the ferret index using the rake command (rake ferret:rebuild). I got this non-descriptive error regarding failing to rebuild it (Even in my development mode). So after googling for it, all one has to do is so simple.

Go into your rails script/console and just type

Model.rebuild_index

And you’re done.

Ensuring your join model uniqueness

For example:

id |category_id | inventory_id

1   384            1            #first entry
2   384            2            #this would be ok.
3   384            1            #this would not be ok

To ensure that a category_id doesn’t have any inventory_id duplicate:

[sourcecode language="ruby"]

class CategoryProduct < ActiveRecord::Base
  belongs_to :category
  belongs_to :inventory

  validates_uniqueness_of :category_id, :scope => :inventory_id
end

[/sourcecode]

Index your tables people.

A good read on table index.

http://www.railway.at/articles/2008/04/24/database-agnostic-database-ignorant

Sometimes, it is easy to forget when someone or something else handles it for you. For instance, ActiveRecords. Rails does not  create foreign keys for you. It only creates the primary key. It does not impose constraint on the database level. The association is handled on the application level. So always remember to create an index for your model associations. It could save your database server from working too hard.

Note to self

Do not name your database column with the name ‘no’.

You’ll get this error when you try to run your test

ActiveRecord::StatementInvalid: Mysql::Error: Unknown column ‘false’ in ‘field list’

Nested Layouts in Rails


I was wondering how to keep the layouts in my rails application code DRY – I was close to the point of kicking myself for having to make changes to all my layouts whenever something standard changed – so i researched online and found the above diagram by Matt McCray in his blog.

I used Matt’s method for nesting layouts, but instead of defining a method called sub_layout in my controllers, I called a pre-defined rails controller method:

< % render :partial => “layouts/#{controller.controller_name}” %>

and defined a partial layout named after every controller I had, which had different settings for their own views. Rails has a local variable called ‘controller’ you can use to access its controller’s name and even the action used for the current view. So using this, I don’t have to define additional methods in my controllers, nor use any plugins.

kudos to Matt for coming up with this in the first place. Thanks!

Rails 2.1 Label

A label method is introduced in Rails 2.1.

The following code:

[sourcecode language="html"]

< % form_for (@post) do |f| %>

< %= f.label :title %>

#Code truncated for clarity
< % end %>

[/sourcecode]

Would generate the following HTML:

[sourcecode language="html"]

[/sourcecode]

If your label contains a css class and if you need another name other than the default column name for your label, just do as following:

[sourcecode language="ruby"]
< %= f.label :title, "Please key in a title", :class => “form_label” %>
[/sourcecode]

The code above will generate the following:
[sourcecode language="html"]

[/sourcecode]