• Shokudo Japanese Food Bazaar (in Singapore) - don't bother

    Subscribers who read my blog for Ruby- or Mozilla-related posts should ignore this post, it's another of those blogging as catharsis posts. To my defence, I haven't done one of those for a really long time!

    If you're staying in Singapore and looking to try out the food at Shokudo Japanese Food Bazaar after it was featured in the local newspaper, my advice to you is, "don't bother!" Why? In 2 words, horrible service.

    Despite some positive reviews (yes, the decor is not too bad), my dining experience at Shokudo consisted mostly of getting the service crew's attention (and failing spectacularly despite standing right at the counter) and being scowled at or avoided by most of the staff (which is not good, since being a bazaar-style restaurant, you needed to place your order at each stall manned by different members of the service crew).

    My friends and I were speculating that either the staff got scolded that day (and reacted negatively to that), or they were just too stuck up because business was good. Either way, it was just terrible. When leaving, I even got rudely reminded that I'd left that one of those things they gave you to reserve a table. Did I mention the service was horrible? (Granted, there were 2 counters where the staff were attentive and actually quite friendly - this was at the macha drink stall and the katsu curry counter.)

    What about the food? With such bad service I would say no one shouldn't really care about the quality of the food - thankfully enough, the food is of a consistently mediocre level to even bother!

    Has anyone had a similar experience at Shokudo, or was it just our unlucky day?

  • Living on the edge (of Rails) #8 - the code optimization edition

    Here's this week's update of the important changes that have been happening on edge Rails. There were lots of performance patches this week, credit mostly due to the guys from Acunote and their latest blog post on optimizing Rails.

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

    ActiveRecord::Base#attributes-related optimizations

    The ActiveRecord::Base#attributes_before_typecast no longer clones attribute unnecessarily.

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

    ActiveRecord::Base#attributes now no longer supports options. The ActiveRecord::Base#attributes method used to support :only and :except options, which are actually unnecessary since it returns a Hash. You can use Hash#slice or Hash#except (both ActiveSupport core extensions) directly on the hash.

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

    ActiveRecord associations optimized by avoiding named block arguments

    Alexander Dymo is at it again optimizing ActiveRecord performance, this time by avoiding passing named block arguments. Turns out that it is faster and more memory efficient in Ruby to pass blocks like this:

    def foo
      bar { |*block_args| yield(*block_args) if block_given?
    end

    instead of passing the block around like so:

    def foo(&&block)
      bar(&block)
    end

    Occurrences of the more expensive way of passing blocks have been replaced in the ActiveRecord associations code so associations are lighter to use.

    For a more detailed write-up, check out Alexander's blog entry.

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

    ActiveRecord associations optimized by using symbol callbacks instead of string callbacks

    Again from Alexander Dymo, this patch also improving ActiveRecord association performance. Internally, ActiveRecord associations code uses a lot of string callbacks (e.g. before_save "some_ruby_code_to_eval"). It turns out that that is significantly more expensive compared to simply using Module#define_method because when the callback string is evaluated, the binding needs to be passed along. Passing the binding takes up memory (which is bad, of course).

    The internal associations code has been changed to use that define_method now, and if you're using a lot of associations, you would save megabytes of memory! (Alexander's blog post has more detailed benchmarks.)

    Remember, when writing your own before and after filters, not to use a string that needs to be evaled!

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

    Improve ActiveRecord::Base#save performance by avoiding repeated calls to ActiveRecord::Base#connection

    Another Alexander Dymo performance patch. This particular patch improves performance by getting the connection object just once and calling it directly, instead of needlessly calling several times. This should improve ActiveRecord::Base#save performance.

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

    ActiveRecord associations now support the :readonly option

    ActiveRecord::Base#find supports the :readonly option to retrieve records that were read-only (i.e. you couldn't save them). Now you can do the same for associations, like so:

    has_many :comments, :readonly => true

    This allows you to protect associated records from being saved.

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

    String#squish and String#squish! to remove consecutive chunks of whitespace

    A String#squish extension has been added that trims whitespace from both ends of a string, and compressing consecutive whitespace groups within the string into 1 space each.

    For example,

    @description = %{ String#squish() allows me to write long strings
      inside my Ruby code, without having to worry about indentation,
      the page margin, spaces, tabs or newlines. "double" or 'single'
      quotes are both fine, and #{interpolation} works. }.squish
    

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

    As always, let me know of any inaccuracies or any suggestions you may have in the comments, see you guys next week!

  • Living on the edge (of Rails) #7 - improved ActiveRecord::Base#attributes, time zone support

    It's that time of the week again (every Wednesday for the overly observant, coinciding with the release of the Rails Envy podcast) for some choice updates of what changes have been happening on edge Rails. This week's report covers changes from 4 Feb 2008 to 10 Feb 2008 (the day the Rails Envy podcast was recorded).

    More efficent ActiveRecord::Base#attributes

    ActiveRecord::Base#attributes returns a hash of all attributes with clones of their objects as values. This unnecessary cloning is expensive, and has now been removed. ActiveRecord::Base#attributes now returns a hash of values of the attributes.

    Thanks to Juanjo Bazan, there have been 2 further patches (after the podcast was recorded) related ActiveRecord::Base#attributes that further improves ActiveRecord's performance: removal of cloning from ActiveRecord::Base#attributes_before_typecast, and removing options (:only and :except options, specifically) from ActiveRecord::Base#attributes.

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

    ActiveResouce::Base#exists? now uses HTTP HEAD instead of a GET

    A HTTP HEAD request is really all that is needed to check for existence (200 == exists, 404 == doesn't exist). This has been changed to HEAD from a GET request, which is more efficient since all we retrieve are the HTTP headers and there's no unnecessary instantiation of the ActiveResource object.

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

    Time zone support for ActiveRecord, and config.time_zone property for specifying a default Time Zone

    ActiveRecord models now have time zone-aware attribute readers and writers. Times returned from ActiveRecord attribute readers now have a time_zone attribute themselves, allowing time zone-aware calculations.

    You can now configure the default Time.zone value with config.time_zone in your environment.rb. Setting this will enable time zone-awareness for ActiveRecord models.

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

    A Template class has been introduced to ActionView

    As part of the ActionPack refactoring that's still ongoing, a ActionView::Template class has been introduced to encapsulate all the data relevant to the currently rendered template. This is largely an internal refactoring so Rails users shouldn't be affected.

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

    Concrete sweeper classes

    You can now use an explicit class when declaring a cache_sweeper. E.g.

    class ListsController < ApplicationController 
      caches_action :index, :show, :public, :feed 
      cache_sweeper Sweepers::List, :only => [ :edit, :destroy, :share ] 
    end

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

    As always, let me know of any inaccuracies or any suggestions you may have in the comments - this week's report is a little rushed because I'm a little late in posting it up!

  • Living on the edge (of Rails) #6 - better performance, Git support, and more

    Here's another week of noteworthy updates on the Rails trunk. Thanks once again to the Rails Envy podcast for featuring my updates, and even bigger thanks to the Rails contributors and committers who make things happen. This week's Living on the Edge was covered in Rails Envy podcast #17.

    The company I work for, Bezurk (yeah we know some of you hate the name "Bezurk" - that's going to change), is currently looking for a Ruby developer to join our ranks. This person will be working mainly on Ruby-based web development projects. As we all know, "Rails doesn't scale" (delivered in Jason Seifer-style - meaning it's just a joke!) so we'd love anyone who's up for a challenge and who's also willing to work outside the Rails comfort zone (our current favorite: Ramaze). Our Ruby team currently comprises 3 experienced developers and 1 up and coming Rubyist.

    We're active Open Source contributors (Arun released ActiveCouch recently), while I am a Rails contributor (I'm 'chuyeow' on the Rails Trac) myself.

    If all this sounds interesting enough to you, do check out the full job description and drop us an email. Yes, we're serious when we said "+1 for DotA/Counterstrike skills)". There's a catch though - you have to work on location at our office in Singapore.

    Anyway, let's get back on topic - this weeks’ report covers changes from 28 Jan 2008 to 3 Feb 2008 (the day the Rails Envy podcast was recorded).

    Saving, creating and updating ActiveRecord objects is more efficient

    Thanks to Gleb Arshinov and Alexander Dymo with their blog post and patches about improving Rails performance by approaching it via minimizing garbage collection, saving, creating, and updating ActiveRecord objects is now significantly more efficient.

    The expensive ActiveRecord::Base#attributes method is no longer called internally, so there's no unnecessary cloning of attribute values. Less memory usage means less garbage collection, which means better performance!

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

    SQL calls and rendering are faster

    This patch is courtesy of Gleb Arshinov and Alexander Dymo too.

    Rails surrounds every SQL call and ActionView::Base#render with the ruby method Benchmark#realtime so that it can print out some benchmarking numbers. Benchmark#realtime allocates an unnecessary 45k of memory per call (who knew!). This has been monkey patched in Rails to a leaner implementation, reducing memory usage and increasing performance.

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

    MySQL adapter slight optimization

    Table and column names in the MySQL adapter are now cached in instance variables, reducing memory allocations (and thus the need for GC).

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

    script/generate does Git!

    script/generate now allows you to pass the '--git' (or '-g') option to add the generated files to git (much like how you could do the same with Subversion with '-c' or '--svn'). This patch is the work of Steven Soroka so nice work Steven!

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

    map.resources :products, :as => 'something_else'

    Here's something that will make non-english Rails developers happy: you can now do, for example,

    map.resources :comments, :as => 'comentarios'

    so that you can keep having your model names independent of what URLs you'd actually like to appear on the site.

    The above map.resources means that you can keep your resource and model names in English (Comment), while having URLs like this: /comentarios/123.

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

    :index option for form_for and fields_for to simplify multi-model forms

    Inspired by a Railscasts episode where Ryan Bates mentions how ugly it is to have to pass :index => nil to prevent #text_field (and other form helpers) from inserting the model's ID in the input name (e.g. project[task_attributes][123][name] when what you really want is project[task_attributes][][name]).

    Meaning instead of

    <% fields_for "project[task_attributes][]", task do |f| %>
      <%= f.text_field :name, :index => nil %>
      <%= f.hidden_field :id, :index => nil %>
    <% end %>

    you can now do:

    <% fields_for "project[task_attributes][]", task, :index => nil do |f| %>
      <%= f.text_field :name %>
      <%= f.hidden_field :id %>
    <% end %>

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

    No more emails in your production logs

    You'd probably have noticed that ActionMailer logs entire email messages in the log, even in production. Well, it's been changed to be less verbose now. At the :info log level, only the recipients are logged. You can still see the entire email at the :debug log level (which is the default for development environment).

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

    As always, let me know of any inaccuracies or any suggestions you may have in the comments. Oh, and if you liked this, do me a favor by submitting it to Ruby Reddit.

  • ActiveCouch - a CouchDB library in the spirit of ActiveResource and ActiveRecord

    My fellow Rubyist at work, Arun Thampi, has released ActiveCouch, a Ruby library for CouchDB (if you don't know what CouchDB is, read this). Check out the official blog announcement of ActiveCouch.

    ActiveCouch tries to be an ActiveResource and ActiveRecord (yes, there is even an ActiveCouch::Migration class for creating CouchDB views) equivalent for representing CouchDB documents in Ruby. I wish I could write some coherent code examples here but I am not that up to date with the latest changes in ActiveCouch (despite my name being tagged as a committer to ActiveCouch, it is largely Arun's awesome little baby).

    Never fear though, since Arun and I are chowing down our own dog food - we're currently porting several gigabytes worth of hotel data from our hacked together XML and Ferret-based library to use the ActiveCouch library. I'm sure we'll get a more coherent API after this exercise, since we are no longer relying on specs and mocks, but working on a Real Application.

    If you decide to try out ActiveCouch, do let us know of any feedback or bug reports at the ActiveCouch Google Code site. ActiveCouch is Open Source, so if you've patches that's even better!

subscribe via RSS