• Ruby 1.9.0 has been released

    Just in the nick of time for the Christmas target, the Ruby core team has released Ruby 1.9.0 - Matz announced the release on the ruby-talk mailing list not too long ago.

    Rubygem and Ruby library developers, now's the time to get down to making your Ruby code compatible with 1.9.0.

    Rails is not too far from being compatible with 1.9, thanks to the efforts of Jeremy Kemper and a few other contributors. Mongrel is not quite there yet though (I use mongrel for my Rails applications, and I think at least 50% of you do too). So while running your Rails apps on Ruby 1.9 is not an easy task right now (unless you enjoy lots of monkey patching), let's hope the full 1.9.0 release will inspire more Ruby developers to get their libraries compatible so we can all enjoy the big speed boost in Ruby 1.9.

    Very nice (if somewhat geeky) Christmas present from the Ruby core and contributors!

  • Generating migrations gets easier - Rails 2.0 a feature a day #6

    You may not have noticed this yet, but Rails 2.0 has a new convenient syntax for generating ActiveRecord migrations. Go ahead, run the migration generator with script/generate migration. I'll wait.

    Yup, you can now specify the columns you want to add in your migration by passing attribute/type pairs to the migration generator. Ergo,

    script/generate migration AddMoreToAnime episodes:integer licensed:boolean

    will generate a migration like so:

    class AddMoreToAnime < ActiveRecord::Migration
      def self.up
        add_column :animes, :episodes, :integer
        add_column :animes, :licensed, :boolean
      end
    
      def self.down
        remove_column :animes, :licensed
        remove_column :animes, :episodes
      end
    end

    This ties in pretty nicely with the syntax for the model generator (script/generate model), which also accepts attribute pairs. Tiny change but "it's all about consistency".

    For the geeks among you, check out the related changeset and ticket.

    About the contributor, Pratik Naik

    Pratik Naik (WorkingWithRails profile), probably better known as lifofifo or just lifo, is an active Rails contributor and can be found on #rails-contrib and #rubyonrails nearly 24/7. Almost everyone who's used Rails has used code that lifo has written. Oh, and lifo also won one of the monthly Rails Hackfests.

    He also keeps a pretty good blog where he posts mostly on Rails hacking and tips.

  • Rails 2 a feature a day - update

    In case anyone is wondering about the pause in Rails 2.0 - a feature a day posts, yes, I know, I've not been writing any posts for a week or so. I'll be posting more actively again from tomorrow - just taking a short break due to general lethargy these few days. And submitting patches > blogging.

    On a somewhat related note, I'll be posting weekly updates of edge Rails changes in a tie-up with a particular Rails podcast from the beginning of next year - not gonna say which one!

  • Rails 2.0.2 released, so what's new?

    Rails 2.0.2 was tagged not too long ago and will hit the gem servers soon I expect. Being a minor point release there aren't many changes, but here're the ones I feel are worth mentioning:

    ActionPack changes

    Configurable asset hosts: You can now pass a proc to ActionController::Base.asset_host. This allows you to get by the hard-coded assumption that you have 4 asset hosts numbered 0-3 when using the '%d' wildcard (introduced in Rails 2.0.1).

    I contributed this patch so I'm gonna be lazy and copy and paste most of the documentation I wrote for patch.

    The example proc below generates http://assets1.example.com and http://assets2.example.com randomly.

    ActionController::Base.asset_host = Proc.new { |source| "http://assets#{rand(2) + 1}.example.com" }
    image_tag("rails.png")
      => <img src="http://assets2.example.com/images/rails.png" alt="Rails" />
    stylesheet_include_tag("application")
      => <link href="http://assets1.example.com/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />
    

    The proc also takes a single source parameter which is the path of the source asset. This can be used to generate a particular asset host depending on the asset path. This is useful if you have, say, images hosted elsewhere, or you want an SEO-friendly URL for your images:

    ActionController::Base.asset_host = Proc.new { |source|
      if source.starts_with?('/images')
        "http://images.example.com"
      else
        "http://assets.example.com"
      end
    }
    image_tag("rails.png")
      => <img src="http://images.example.com/images/rails.png" alt="Rails" />
    stylesheet_include_tag("application")
      => <link href="http://assets.example.com/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />

    Asset cache directories are automatically created: In Rails 2.0.1, if you tried to cache your assets (javascripts and stylesheets) in a subdirectory (example below), you either need to check it into your source control or have your deployment tool (Capistrano, etc.) create it for you. Josh Peek contributed a patch that created the subdirectory instead so you can do something like:

    javascript_include_tag(:all, :cache => "cache/money")

    and not have to bother about creating the 'cache' subdirectory.

    Railties changes

    Default database is now SQLite3: The default database is now SQLite3 instead of MySQL. Running 'rails takeover_the_world_app' will now come with a database.yml that's setup for SQLite3. To get the old behavior (where it's preconfigured for MySQL), run rails -d mysql takeover_the_world_app instead. This is mostly to make this "just work" on Mac OS X Leopard, where SQLite3 is already installed with the OS.

    Template loading is faster: DHH has turned on ActionView::Base.cache_template_loading by default in the production.rb environment config file that basically means that Rails no longer does file system stat calls when loading templates. The downside is that you have to restart your Rails application to see templates changes in production mode, but it's not really that big an issue since no one should be editing templates anyway 'live' in a production application.

    New rake tasks for migrations: rake db:migrate:redo to undo your last migration and re-run it - very useful when developing migrations (when you screw up, that is). rake db:migrate:reset drops the database, re-creates it, and then runs all migrations.

    rake task for generating secret keys: rake secret to generate a secure key that you can use for cookie sessions. This is useful for updating Rails applications from 1.x to 2.x, which uses cookie-based sessions by default and requires a secret key.

    config.action_controller.session = {
      :session_key => '_your_app_session',
      :secret      => 'some super long string that you can generate with the rake secret task'
    }

    Personally I just use super long quotes from Family Guy.

    That's it! For the curious, expect Ruby 1.9 compatibility, improved caching, and big ActionPack and rendering refactoring changes in Rails 2.1.

  • Sensible GROUP BYs in ActiveRecord::Calculations - Rails 2.0 a feature a day #5

    Doing GROUP BYs in ActiveRecord has always been tricky. There's a lot of "magic" in ActiveRecord and room for untested edge cases. Thankfully, Rails also has a squadron of eagle-eyed contributors who are on hand to fix unforeseen errors.

    For example, if you wanted to do this:

    class Click < ActiveRecord::Base
      belongs_to :site  # site_id foreign key is a String, e.g. 'www.rubyonrails.org'
    end
    
    # Now, try counting the number of clicks, grouped by site.
    Click.count(:all, :group => :site)
    # => [[nil, 1], [nil, 3]]
    

    This is a surprisingly common thing to do especially when you are producing reports or statistics of any kind and unfortunately decided to go with a non-(auto)numeric foreign key. As you may have noticed, the sites were returned as nil which is totally unhelpful. Thankfully, this has been fixed in Rails 2.0:

    Click.count(:all, :group => :site)
    # => [[nil, 1], ['www.site, 3]]

    GROUP BY and :foreign_key don't mix

    This change is NOT in Rails 2.0.

    If you wanted to do GROUP BYs in your ActiveRecord models (via the :group option), you had to take note of one particular gotcha. For example, with an ActiveRecord model like this:

    class Anime < ActiveRecord::Base
      belongs_to :japanese_studio, :class_name => 'Studio', :foreign_key => 'studio_id'
    end

    Note that we specified the :foreign_key option since it can't be inferred from the association name of 'japanese_studio'. If we wanted to counting the number of anime grouped by studio though, we're in big trouble:

    Anime.count(:all, :group => :japanese_studio)
    # ActiveRecord fails and mumbles about an unknown "japanese_studio_id" key.
    

    Basically what happened is Rails did not use the specified foreign key column of 'studio_id', inferring it instead from the association name of 'japanese_studio'. This is not yet fixed but there's already a patch ready for it at the Rails issue tracker. In fact, I'm gonna verify it right after posting this.

    About the contributor, Kamal Fariz

    I thought it was time to cover Rails 2.0 contributions by someone closer to home ("home" being my home, Singapore) so I singled out Kamal Fariz (WorkingWithRails profile), a Rails developer working in Malaysia for a Rails shop. Kamal's also a former Rails Hackfest winner (read the post-Rails Hackfest interview). Kamal is also an active member of the Malaysia Ruby Brigade (I guess it's not called a "Ruby User Group" since "RUG" sounds rather unglamorous).

    Wow look at the number of parentheses I used in the last paragraph. For no reason whatsoever here's a lolcats picture:

    Parenthese cats are parenthetic


subscribe via RSS