Archive for the 'Rails' Category

I18n fix

March 23rd, 2011 by pyrat

Fix for an error with I18n, ruby 1.9.2 and Rails 3.

(incompatible character encodings: UTF-8 and ASCII-8BIT)

Rails 3 Benchmarks Startup Time

March 14th, 2011 by pyrat


Waiting

I have been having an annoying problem recently. One of the projects I am working on has a fairly large Gemfile and this is impacting startup time considerably on Ruby 1.9.2.

Ruby Start-up Times is a good article detailing boot up times for different ruby versions with a relatively fresh app.

Well, the development app I am currently working on has 148 gems defined in the Gemfile.lock. I don’t think this is overly excessive as many gems such as devise have many dependencies.

The result is that it takes a long time to bootup rails when using 1.9.2. This means that repetitive tasks such as tests, generating migrations, running migrations, rake tasks, generators, basically anything which requires a boot of the rails environment takes a long time.

This impacts the speedy development feel which rails gives you, diminishing the experience somewhat. I decided to try and see different boot times for different ruby versions.

For the benchmarks I used the same script as used on the post Ruby Start-up Times

  #!/bin/bash
  echo puts Time.now > test_script
  time rails runner test_script
  time rails runner test_script
  time rails runner test_script

Rails startup performance comparison

The graph above shows the average run time for the above script in seconds for each of the ruby versions listed. The ruby versions were installed using rvm. The most recent REE gave a mysql2 segmentation fault so I went with the earlier version.

Results

Rubinius is painfully slow to startup, for me it is currently unusable. 1.9.2 is significantly slower than 1.8.7 for bootup. This is highly frustrating as once the application starts up, 1.9.2 feels snappier than 1.8.7.

REE takes the title for the fastest rails 3 bootup time in development for a project with a number of gems defined in the Gemfile.

Possible reasons for 1.9.2’s terrible performance

There is a thread about this on Rails-Core

To quote Yehuda Katz


There are things that the C require code does in 1.9 that slow things down. One such example is re-checking $LOAD_PATH to make sure it is all expanded on every require. This is something that should be addressed by ruby-core. I’ll open a ticket on redmine if there isn’t one already.


I am also experiencing this problem and a $LOAD_PATH issue seems like a potential cause. Lets hope it gets fixed soon.

Digging deeper there is a bug report on the ruby bugtracker but unfortunately it looks to be scheduled for the 1.9.3 release. It doesnt look like this is going to be coming out any time soon, so another solution needs to be found.

Suggestions for a quick fix

  • It is possible to stop bundler requiring all the gems on startup, and you then need to manually require them in your code. This is a potential solution but it would be a lot better if the bug in 1.9.2 could be fixed instead.
  • Use REE for most of your development and use 1.9.2 in a separate terminal if you need it for tests etc.
  • Some other kind of lazy loading solution would be excellent, or even better someone with knowledge of ruby internals who can fix this problem and it be released as a patch release rather than waiting for 1.9.3.

Google Product Search Xml Generator

April 16th, 2010 by pyrat

I have been working on a google base product search xml feed generator. It is in the form of a semi-customizable rake task. I have released this as a kind of rails plugin.

rake googlebase:generate generates an xml file of your products.

Configuration

To configure, add Rails.root/config/google_base.yml

Example google_base.yml file in files/google_base.yml

As the structure of the xml is dependant on your product models I have left it to the programmer to modify the google.rake file and set the correct instance methods for returning product information, along with the named_scope for returning live products.

TODO:

Instead of editing this rake file manually it would be good to add a plugin type class method which can take the configuration of your products and generate this automatically.

Its is available on github

Jquery Assertion for Rails

April 10th, 2010 by pyrat

When doing functional testing of ajax actions it is nice to be able to test the format of the javascript returned to the browser.

When using rjs I was using the excellent arts testing library, now I have moved to raw jquery instead. The method below provides a short hand way to test simple jquery methods. it can be built upon for sure but this little regex is quite powerful.

  def assert_jquery(effect, id)
    assert_match(/\$\(['"]+##{id}['"]+\).#{effect}\(.*\);/, @response.body)
  end

Consider the jquery

$("#announcement").hide();

  assert_jquery('hide', 'announcement')

This currently only works for id methods and when jquery isnt in compatibility mode. Also integration testing using something like env.js and harmony is a better way of javascript testing. Things like blue ridge actually integrate the env.js framework into a rails plugin and are a great solution if you have to do some real heavy lifting.

However, this method brings maximum results for minimum effort.

Install Mysql Gem on Snow Leopard and Macports

March 8th, 2010 by pyrat

export ARCHFLAGS="-arch i386 -arch x86_64" ; gem install --no-rdoc --no-ri mysql -- --with-mysql-dir=/opt/local/lib/mysql5 --with-mysql-config=/opt/local/lib/mysql5/bin/mysql_config

Rails 2.3 Upgrade Notes

February 27th, 2010 by pyrat


In Need of Love and Care

I have written a number of rails applications over the past few years. While new projects are using rails 2.3 I have a number of older applications which I should have upgraded before but havent. Anyway, here is some little notes to take into account when upgrading to rails 2.3. Then from here you are placed well for the upcoming release of rails 3.

  • to_param method issues (fixnum to string)
  • test_helper modifications – class name (ActiveSupport::TestCase and all unit tests need to extend this)
  • add include ActionController::TestProcess to test_helper.rb
  • to silence spec warnings for old unpacked gems – Rails::VendorGemSourceIndex.silence_spec_warnings = true
  • sessions

ActionController::Base.session = {
  :key => '_session_name',
  :secret => 'd00cda5710eab8sdfsdf6c5fe165780074fa5027f50168a0bd0ae2832c05bb4f804a07228b220b67e'
}

In an initializer instead of environment.rb (some plugins access the session in a different manner.)

  • Truncate format is deprecated, update to include :length hash key.
  • If you are defining constants in environment.rb, move them to an initializer to make them play better with tests.
  • To access session_id you first have to call the session. Also, the method of accessing the session id has changed.

The following 2 lines are required to get the session id.

session[:session_id]
id = request.session_options[:id]

Christmas Card Labels Application

December 8th, 2009 by pyrat

santa

I have been keen to get my hands dirty with ExtJS, so jumped at the chance to make a christmas card list application which can print the list to labels; to stick on envelopes.

I have finally become mature enough to have a christmas card list along with my girlfriend, which is useful for keeping track of friends both in Trondheim and the United Kingdom.

To get it up and running on heroku it is pretty swift –

  git clone git://github.com/pyrat/christmas-card-labels.git
  cd christmas-card-labels
  sudo gem install heroku
  heroku create
  git push heroku master
  heroku rake db:migrate

You are now good to go, you may need to tweak the css (labels.css) to match your specific labels which can be a painful experience.

Default username / password is god / jul which is norwegian for merry christmas!

There is a demo version online

Configurable ActiveResource Site Variable

September 16th, 2009 by pyrat

flickr

Documentation on ActiveResource is fairly thin on the ground.

If you are using ActiveResource in the real world it is likely that you will want to use different webservices depending on what environment you are in. (Staging, Development, CI, Production etc.)

Heres how to do it. This assumes the REST api has been put under the api namespace and has been setup with HTTP Authentication.

config/initializers/config.rb

  raw_config = File.read(RAILS_ROOT + "/config/config.yml")
  GLOBAL = YAML.load(raw_config)
  APP_CONFIG = GLOBAL[Rails.env]

config/config.yml

  development:
      webservice: http://username:password@localhost:3001/api/
  test:
      webservice: http://username:password@localhost:3001/api/
  staging:
      webservice: https://username:password@staging.com/api/
  production:
      webservice: https://username:password@production.com/api/

app/models/incometype.rb_

  class IncomeType < ActiveResource::Base
    self.site = APP_CONFIG['webservice']
  end

Here is a great railscast on the subject.

Git Submodule Gotcha

August 12th, 2009 by pyrat

The gotcha comes when I switch branches back and forth between the “master” (no submodules, but with checked in source) and “dev” (where my submodule work is). Here’s what happens:

git checkout master

error: Untracked working tree file ‘vendor/plugins/acts_as_list/lib/active_record/acts/list.rb’ would be overwritten by merge.

Here’s a workaround…
To go back to a branch w/o submodules

rm -rf vendor/plugins
git checkout master
git checkout vendor/plugins

To go back to a branch w/ submodules

git checkout dev
git submodule update --init

Another gotcha, when I tried to merge dev into master I got “fatal: cannot read object… It is a submodule!” A solution is:

git merge -s  resolve

Original Article

Using mod_expires to speed up serving pages with apache

May 21st, 2009 by pyrat

This is rails specific to a certain extend and involves setting the expires header on static asset to make browsers cache. This can be dangerous so is best used with timestamped css and javascript assets.

By default: rails helpers will add a timestamp onto the end of the asset so when you redeploy the file the browsers will recache the file because the timestamp has changed.

eg.

  <script src="/javascripts/all.js?1242919746" type="text/javascript"></script>

To setup mod_expires apache on debian based:

  sudo a2enmod expires

Then in your config

  ExpiresActive On
  <FilesMatch "\.(js|css)$">
    ExpiresDefault "access plus 1 year"
  </FilesMatch>

You can easily add image types to this as well but often css loads images and designer often forget to use these helper methods. So in the real world just doing it with js and css makes it safer to do with maximum performance gain.