• Living on the edge (of Rails) #15 - the early edition

    I'm gonna post up the Living on the Edge a little earlier this week because I've found I just can't keep up (when things get busy) with 2 separate sets of notes for the Rails Envy podcast and another for my own blog posts.

    From this week onwards, I'll be following Pratik's suggestion to post about changes as they happen instead of after an entire week so expect a slight change in the format of Living on the edge for next week!

    This week’s report covers changes from 31 Mar 2008 to 6 Apr 2008 (the day the corresponding Rails Envy podcast was recorded).

    Rails.env, Rails.logger, Rails.cache, Rails.root

    This has been a long time coming: You can now use Rails.env instead of RAILS_ENV, Rails.root instead of RAILS_ROOT, Rails.logger instead of RAILS_DEFAULT_LOGGER, and Rails.cache instead of RAILS_CACHE. Not having to use constants is nice because it always felt a bit dirty to have so many hard-coded constants in the Rails namespace.

    Credit goes to Pratik Naik, the newest Rails core team member for this cleanup.

    Related changeset: http://dev.rubyonrails.org/changeset/9180

    Render :partial now works with a collection of heterogeneous elements

    You can now use render :partial to render a collection of different elements and Rails will figure out which partial template to use. For example:

    render :partial => [ monkey, donkey, dramatic_chipmunk ]

    will render the monkey with the 'monkeys/_monkey.html.erb' partial, donkey with the 'donkeys/_donkey.html.erb' partial, and last but definitely not lest, dramatic_gopher with the 'dramatic_chipmunks/_dramatic_chipmunk.html.erb' partial

    This is especially useful if when using STI, where your ActiveRecord model would return objects of different types. The collection [ monkey, donkey, dramatic_chipmunk ] could very well be something returned from your Animal model that has subclasses of Monkey, Donkey and DramaticChipmunk via STI.

    Credit: Zach Dennis of ar-extensions fame.

    Related changeset: http://dev.rubyonrails.org/changeset/9177

    ActiveModel work revived

    It seems like work on ActiveModel (think unified ActiveRecord and ActiveResource behaviors) has been revived, if the latest commits (http://dev.rubyonrails.org/changeset/9171 and http://dev.rubyonrails.org/changeset/9173) by David (DHH) is anything to go by.

    Bugfix: Assigning an invalid has_one association now causes #save to fail on parent

    You could do this before:

    firm = Firm.find(:first)
    firm.account = Account.new # Associate INVALID account
    firm.save # This doesn't fail

    Now that's fixed thanks to Pratik Naik.

    Related changeset: http://dev.rubyonrails.org/changeset/9232

    As usual, any feedback is respectfully appreciated!

  • Living on the edge (of Rails) #14 - the extreme edition. Extremely late.

    This week’s report covers changes from 24 Mar 2008 to 30 Mar 2008 (the day the corresponding Rails Envy podcast was recorded).

    There're lots of big exciting changes this week on edge. Smells like 2.1 soon!

    has_finder gem merged into Rails

    Ryan Daigle has the scoop on the new has_finder-like functionality in Rails so head on over (I won't repeat it here in the interests of DRY).

    Credit goes to Nick Kallen for coming up with the has_finder gem.

    Related changeset: http://dev.rubyonrails.org/changeset/9084

    ActiveRecord: Unsaved attribute changes are now tracked

    You can now ask an ActiveRecord model whether its attributes have been changed (and is unsaved) using the {attr_name}_changed? (magic) method. The {attr_name}_was method will return the original value of the attribute, and the {attr_name}_change method will return an array with 2 members, the 1st being the original value, the 2nd being the changed (and unsaved) value.

    # Change person's name.
    person.name = 'Jason Seifer'
    person.changed?       # => true
    person.name_changed?  # => true
    person.name_was       # => 'jseifer'
    person.name_change    # => ['jseifer', 'Jason Seifer']
    person.name = 'Ceiling Cat'
    person.name_change    # => ['jseifer', 'Ceiling Cat']

    Credit goes to Rails core team member Jeremy Kemper (bitsweat) for this patch (which originated from Jeremy's very own Dirty plugin).

    Related changeset: http://dev.rubyonrails.org/changeset/9127

    ActiveRecord#Base.all/first/last

    Now you can do:

    Post.all.each { |post| # something }
    Post.first
    Post.last

    Kinda like how some other ORMs do (like DataMapper).

    Credit: thechrisoshow and again, Nick Kallen for has_finder.

    Related changeset: http://dev.rubyonrails.org/changeset/9085

    Timestamped Migrations

    This is more useful than it sounds: migrations are now timestamped instead of using incremental numbers in your db/migrate folder. This eliminates the problem of migrations having the same version number when working on a multi-developer Rails app.

    Two new Rake tasks, rake db:migrate:up/down, have been added to allow running of the up and down methods of individual migrations.

    Credit goes to John Barnette, the guy who gave you foxy fixtures.

    Related changeset: http://dev.rubyonrails.org/changeset/9122

    New config.gem option for specifying which gems are required by the application + rake tasks for installing and freezing gems

    Specify which gems are required by your Rails app in your Rails environment.rb! "Vendor everything" supported right in Rails :). An example:

    Rails::Initializer.run do |config| 
      config.gems 'chronic'
      config.gems "hpricot", :version => '0.6', :source => "http://code.whytheluckystiff.net"
      config.gems "aws-s3", :lib => "aws/s3"
    end

    There are also new Rake tasks:

    # List required gems. 
    rake gems 
    
    # Install all required gems: 
    rake gems:install 
    
    # Unpack specified gem to vendor/gems/gem_name-x.x.x 
    rake gems:unpack GEM=chronic

    Credit goes to the prolific Rick Olson for this gem of a patch.

    Related changeset: http://dev.rubyonrails.org/changeset/9140

    ActiveResource #clone

    You can now clone an existing resource:

    gregg = Person.find(1)
    borg = gregg.clone

    This doesn't clone child ActiveResource members though, just the straight up attributes of resource.

    Contribors: Ryan Daigle and thechrisoshow.

    Related changeset: http://dev.rubyonrails.org/changeset/9121

    Big documentation patch

    A big doc patch consisting of all the efforts going on in the doc-rails repository on Github has been committed. Check out Pratik's post for more info on what doc-rails is. Though with Rails moving to Git soon, doc-rails may no longer be necessary!

    Related changeset: http://dev.rubyonrails.org/changeset/9093

  • Installing libmemcached and memcached gem on Ubuntu

    Quick notes for installing libmemcached and Evan Weaver's memcached gem, in case I forget (again):

    1. Get libmemcached source from http://tangent.org/552/libmemcached.html. Configure, make, make install. Make sure you get a version compatible with the Ruby memcached gem by opening the COMPATIBILITY file in the memcached gem files.
    2. gem install memcached
    3. Create a symlink ln -s /usr/local/lib/libmemcached.so.2 /usr/lib/.
    4. Try it out with irb -rubygems, require 'memcached'
  • Living on the edge (of Rails) #13 - Git script/plugin install, has_one :through

    It's time again for some edge Rails love. If you haven't listened to it yet, be sure to check out this week's Rails Envy podcast

    This week’s report covers changes from 17 Mar 2008 to 23 Mar 2008 (the day the corresponding Rails Envy podcast was recorded).

    script/plugin install works for Git repositories

    Yup you can now install plugins from Git repositories simply by running:

    script/plugin install git://github.com/foo/kung_fu

    What this really does is to clone a git repository (sans the entire git history by passing the —depth 1 option) into your plugins directory. If you're looking for a Piston-like way to manage external Git repositories though, you'd still be better off with the development version of Piston (François Beausoleil, is posting frequently on his progress with adding Git support).

    Credit goes to Jack Danger, a long-time Rails contributor for this patch.

    Related changeset: http://dev.rubyonrails.org/changeset/9049

    has_one :through

    It's been a long time coming - now you can do has_one :through (like has_many :through) for your join models. Ryan Daigle has example code on how to use it if you're curious (though really, it's just like has_many).

    Credit goes to the Art of Mission guys and Chris O'Sullivan for pulling it all together.

    Related changeset: http://dev.rubyonrails.org/changeset/9067

    rake tasks time:zones:all, time:zones:us and time:zones:local

    Some timezone-related rake tasks have been added to list the names of time zones recognized by the TimeZone class for the config.time_zone option you can put in your environment.rb. For example

    rake time:zones:local

    * UTC +08:00 *
    Beijing
    Chongqing
    Hong Kong
    Irkutsk
    Kuala Lumpur
    Perth
    Singapore
    Taipei
    Ulaan Bataar
    Urumqi

    Credit: Geoff Buesing (core team member)

    Related changeset: http://dev.rubyonrails.org/changeset/9074

    #number_to_currency helper now supports a :format option

    Now you can do something like:

    number_to_currency(123.50, :unit => "£", :format => "%n %u") 
    # => 123.50 £

    Instead of being stuck with the {currency_code} {amount} format which doesn't work in some locales (such as "42 pounds").

    Related changeset: http://dev.rubyonrails.org/changeset/9052

  • One reason Firefox 3 is going to be awesome - Auto-completion in the Location Bar

    After seriously giving Firefox 3 Beta 4 a try due to Safari 3.1 breaking the Shift key in Gmail (update: as kindly pointed out by some of my readers in the comments, it was Gmail that was broken, not Safari 3.1, doh), I've converted to using Firefox 3 Beta 4 as my primary browser. Before, I was using Firefox 2 as my main web browser, with a Safari window open for Gmail (because I tend to have around 50 tabs open in Firefox 2, and having Gmail among those tabs just kills Firefox 2's performance). So yes, I was using Safari 3 as a "Gmail browser", so to speak (in case you'd thought I'd defected from Firefox despite my history).

    Anyway, enough with all that self-indulgent background - I'm writing this today to rave about how cool this one particular feature, auto-completion in the Location Bar (or the Address Bar, you know, where you type in URLs), in Firefox 3 is. Yes, you probably have already read about it and all the other neat new features and changes in Firefox 3, but I'd love to single out this one because it was the one thing I noticed that made browsing so much better when switching from Firefox 2.

    So what is it? First, a screenshot of it in action:

    Firefox 3 autocompletion in the Location Bar


    Yup, typing into the Location Bar brings up a list of matched webpages from your browsing history. You can see from the screenshot that I entered "javascript" and it brought up not just URLs that started with "javascript" (which is the current Firefox 2 behavior), it also brought up URLs that contained "javascript" anywhere and even pages with titles containing "javascript".

    What's the big deal? Well, one of the worst ("worst" being a relative adjective, relative to my opinion) things that can happen while looking for a page you once visited is forgetting its URL. If I'm lucky I can find it by bringing up the History sidebar in Firefox 2 and searching for it by some keyword or dredging through my browsing history.

    In Firefox 3, I just need to type in some keywords related to the page and most likely it'd come up! Here's how I start posting a new blog entry to this very blog:

    Firefox 3 search history by title in Location Bar


    No need to type "blog.c" and then selecting the correct page from the dropdown while remembering that the new post page is "post-new.php". Less typing, no need to remember URLs. Just page titles and website names. If that isn't useful for you, "you're doing it wrong". What's more, Firefox 3 uses adaptive learning to keep an eye of what you've typed and what you select. After some time Firefox will learn from your choices and provide better suggestions in the autocomplete list. Sweet.

    If you haven't tried out Firefox 3 yet, go grab the latest beta. And then come back to this blog to get Firefox 2 and 3 running at the same time. I'm quite sure you'll thank me for it (because this is not the only great feature in Firefox).

    Update: Phil Wilson pointed to this extension for Firefox 2 that has the same auto-completion functionality.

subscribe via RSS