Archive for rubyonrails

Using the older Rake (0.7.3)

You have updated rake to the newer version and only to find out that it does not work with older Rails tasks.

Certainly the rake 0.8.3 is not compatible with the Rails 1.2.3. If you try rake db:migrate, it fails with error: undefined method `last' for {:prepare=>:environment}:Hash.

To invoke the older rake use rake _0.7.3_ db:migrate. Obviously rake version 0.7.3 must be installed.

Older rake on remote

To invoke older rake in the remote server on your capistrano task, such as cap deploy:migrate, set which rake to use in the deploy.rb using set :rake, "rake _0.7.3_".

Comments

Juggernaut Rails Rake Tasks & Capistrano Tasks

Manage juggernaut push server process via rake using juggernaut rake tasks and juggernaut capistrano tasks.

Comments

Rails NULL Encoding of MySQL Results

If you are not careful, the encoding that you set in database.yml may bring some ill-effects. The encoding: utf8 causes ActiveRecord connection to execute set names = 'utf8' in the MySQL session. This tells MySQL server that the this particular session sends and want to receive everything in utf8 character set.

Even the column stored in ‘latin1’ is converted to ‘utf8’. This takes a considerable hit on the performance, I also have a suspicion that MySQL does not cache results when it is forced to do the conversion.

How to avoid

1. Store data in correct encoding as it needs.

2. By telling MySQL to not convert the results by initaliazing rails with…

ActiveRecord::Base.connection.execute('SET CHARACTER_SET_RESULTS = NULL')

Comments

Midnight publishing of objects & MySQL Query Cache

Usually we have to list objects that are published or expired on some day or time, for e.g. in a shop catalog, say you want to make a product available on a particular date and your conditions may look like the following in a Rails model:

  named_scope :available, lambda{
    {
      :conditions=>["products.is_available = 1 and products.available_at <= ?", Time.now.to_s(:db)]
    }
  }

MySQL has a facility to cache the results of queries and respond quickly when asked again. To make use of it, the query should be constant. In the above, the Time.now changing every second, you end up asking MySQL with different query every second. In reality, many listings can work without being too sensitive to time. You can publish at midnight without doing much harm. A simple change to Date.today.at_midnight or even the immediate hour can result in great performance of your queries:

  named_scope :available, lambda{
    {
      :conditions=>["products.is_available = 1 and products.available_at <= ?", Date.today.at_midnight.to_s(:db)]
    }
  }

Comments (2)

UTF8 BOM, Rails Views & Phantom Space

Some how my XHTML was not formatting properly. Firefox, added phantom spacing around an element, which I was not able to recover with the CSS. I found rails was sending a weird character where it merges the template with the view yield. That turned out to be the UTF8 BOM which was added by my previous text editors to the view files. Textmate does not add this and it wont remove if the file already has one. The worse part is, rails renderer send this to the browser as it is, even if it is in the middle of the XHTML.

The quick fix is to remove the BOM, if your editor does not allow you to do so, a quick google search on removing UTF8 BOM can get you some script to remove BOM.

Comments (1)

Useful ActiveSupport::Dependencies

It is quite handy to use rails’ auto-loading functionality on a non-rails ruby project. For e.g. if you want the classes in your lib folder to be auto-loaded, the following piece of code will help:

require 'active_support'
Dependencies.load_paths << "#{File.join(File.dirname(__FILE__), 'lib')}"

Say you have a file lib/answer.rb which defines class Answer; end;. This will be required when you first use Answer constant in your code.

Comments

RGhost & Radiant CMS

If you are planning to use RGhost with the Radiant CMS. Do not extract RGhost in to the vendor/plugins. It certainly wont work. The best thing to do would be to make it available as an extension.

These steps may be useful in getting it working:

  1. sudo gem install rghost
  2. cd vendor/extensions
  3. gem unpack rghost
  4. mv rghost-0.7.4/ rghost
  5. cd rghost
  6. mv lib/* .
  7. rmdir lib
  8. mv rghost lib
  9. rm rghost.rb

Finally add the following to rghost_extension.rb

require 'document'
require 'data_grid/data_grid'
RGVERSION='0.7.3'
class RghostExtension < Radiant::Extension
  version "0.7.4"
  description "RGhost Extension"
  url "http://rubyforge.org/projects/rghost/"
  def activate
    RubyGhostConfig::GS[:path]=case PLATFORM
      when /darwin/: "/opt/local/bin/gs"
      when /linux|freebsd/: "/usr/bin/gs"
      when /mswin/: "C:\\gs\\bin\\gswin32\\gswin32c.exe"
    end
  end
end

Comments

MySQL Auto-increment Column

Fact: MySQL keeps its auto-increment counter in memory for Innodb table, this gets initialised when the database starts. The number that gets assigned when the database gets loaded in the memory is found by for e.g. in the id column by max(id)+1 or 1 if empty. Each time you add a record with a NULL value for the auto-increment column, this value in the counter is assigned and counter is incremented again by 1. More on How AUTO_INCREMENT Handling Works in InnoDB.

Some one in the #rubyonrails found it as a problem. He/she had removed the record with the biggest value, restarted the database and the id gets recycled. As per the log story, record was removed but only to be found again. Their solution was to keep a counter on a table, set it manually, and all the dance that you have to do with rails when you mess with the id attribute.

In fact, if they had done it properly, i.e. using dependency options in associations; removing the biggest record and its id being recycled should not be a problem at all. But you know its never a programmers’ fault. In the end I suggested him/her to set a flag to the record that it is unusable instead of removing it. But hey, will they listen? No, it is cool to mess with id column.

Comments

Code After Rcov

The report generated by rake spec:rcov is good and helps me drop some old habit that i got from other than ruby languages. Take this method for instance:

48   def status
49     case status_code
50     when 'A'
51       :active
52     when 'Z'
53       :complete
54     else
55       nil
56     end
57   end

The line 54 & 55 were never tested, because the status codes are nothing supposed to be other than A or Z.

Ruby will return nil in any other case anyway, so I rewrote it to:

48   def status
49     case status_code
50     when 'A'
51       :active
52     when 'Z'
53       :complete
54     end
55   end

nice, 100% covered.

Comments

find(:last) for what?

find(id), find(:first) and find(:all) is all fine, but why do we ever need find(:last)

It is shocking, that find(:last) patch made to the core without many “+1”.

Comments

« Previous entries Next Page » Next Page »