Skip Mocha 0

Posted by luca
on Thursday, October 23

Yesterday I confessed how messed up was CachedModels 0.0.2. The problem was pretty simple: I made some mistakes mocking up Memcached behaviors.

The Dilemma

I massively use Mocha for track how many calls CachedModels performs against the cache, and (ideally) for run test suite without any server active.
But, this approach led me to broken results. Should I keep out Mocha from my tests?

The Solution

Why don't mock the mock? We know, Ruby allows to add behaviors to classes at runtime, Mocha itself take this advantage. I added to my test_helper.rb the following code:

if ENV['SKIP_MOCHA'] == 'true'
  class Object
    def expects(*args)
      self
    end

    def method_missing(method_name, *args, &block)
    end
  end

  class NilClass
    def method_missing(method_name, *args, &block)
    end
  end
end

Now I can safely run tests without Mocha:

$ rake cached_models SKIP_MOCHA=true

CachedModels 0.0.3

Posted by luca
on Wednesday, October 22

Since I began to work as professional developer I learned a lot of stuff, but, first of all I learned to be honest with customers and with the Community.
I have to admit: CachedModels 0.0.2 was a huge mess.

It was a broken version, due to wrong mocks in test. I apologize for all the problems you could encountered using it. Since I discovered all the errors, I worked hard to restore all the lost functionalities.
But it wasn't enough for me, so I focused my attention on performances, reducing cache accesses: now benchmark test tooks 36.015132 fewer seconds than plain ActiveRecord!

I hope you would appreciate my honesty and newest version of my plugin. Enjoy!

Assets Packager

Posted by luca
on Wednesday, October 15

When you deploy your application it could be convenient to package all your stylesheets and javascripts in a single file, let say all.css and all.js, in order to decrease the HTTP requests against your server.

You may also find useful to reduce the size of those files, through a process which eliminates all unneeded white spaces and comments.

AssetsPackager Rake tasks will help you in solving those problems.

Installation

Download from the repository, then copy assets_packager_tasks.rake under lib/tasks and jsmin under the script directory.

How It works?

First of all, we need to generate a configuration file:

$ rake assets:config

Look for a file called assets.yml in your config directory and make sure the order of listed files is the same you wish to have in your application (i.e. prototype.js before of effects.js, or lowpro.js before of my_behavior.js).
Feel free of edit it.

We are now ready for merge and compress our files:

$ rake assets:package


Now, in your application make sure of use #javascript_include_tag and #stylesheet_link_tag with the :cache => true option.

Credits

AssetsPackager was strongly inspired by the homonym plugin written by Scott Becker, but I dont't like the approach used by him.

I don't like the idea of load a plugin for something I don't need in production mode. In fact you should execute those tasks before your app will be started (i.e. Capistrano post deploy task).

It also introduces new helpers (#javascript_include_merged) which substantially, reproduce the same behavior of the :cache => true option.

Last, but not least, I don't like the naming system: base_1150571523.js
If you use Mongrel this means to have something like this:

<script type="text/javascript" src="/javascripts/base_1150571523.js?1150571523"></script>


Which sounds a bit redundant, if compared with all.js?1150571523.

Uladzislau Latynski for his jsmin.rb Ruby porting.

Thanks to Steve Souders for his High Performance Web Sites book.

CachedModels 0.0.2

Posted by luca
on Friday, October 10

CachedModels hit 0.0.2.

First of all, I transformed it to a Ruby gem, so you can use it outside Rails! Second, I dramatically enhanced performances, avoiding useless cache lookups and expirations. Take a look at the new benchmark stats: 1000 requests with a level of concurrency equal to 100, tooks 6 fewer seconds, if compared with standard ActiveRecord.

I strongly encourage you to upgrade to the newer version.

Released Sashimi 0.2.1

Posted by luca
on Monday, September 29

I've just released a new version of Sashimi (0.2.1), it fixes a bug for Ubuntu.

The Problem

When the script starts tries to load repository concerned classes: GitRepository and SvnRepository, which are subclasses of AbstractRepository. In repositories.rb I use Dir#[] to load all the .rb files in a certain directory, but the order of the resulting array is unpredictable, so if the first class was not AbstractRepository Sashimi was crashing.

The Solution

I've fixed it, so, if you have experienced this problem, please update Sashimi with:

$ (sudo) gem update sashimi

Cached Models 1

Posted by luca
on Wednesday, September 10

cached_models provides to your models a transparent approach to use Rails internal cache mechanism.

Usually, when you decide to use cache for your ActiveRecord results, you have to manually implement complex expiring policies.
cached_models simplifies your code:

class Author < ActiveRecord::Base
  has_many :posts, :cached => true
end

class Post < ActiveRecord::Base
  belongs_to :author, :cached => true
end

That's all!!.

A more complex example..

class Project < ActiveRecord::Base
  has_many :developers, :cached => true

  has_many :tickets, :cached => true
  has_many :recent_tickets, :limit => 5,
    :order => 'id DESC', :cached => true
end

class Developer < ActiveRecord::Base
  belongs_to :project, :cached => true
end

Example 1

project.developers # Database fetch and automatic cache storing

developer = project.developers.last
developer.update_attributes :first_name => 'Luca' # Database update and cache expiration for project cache

Example 2

# Fetch associated collection for both the projects
project.developers
project2.developers

developer = project.developers.last
project2.developers << developer # Database update and cache renewal for both project and project2 caches

Example 3

project.tickets # Database fetch and automatic cache storing
ticket = project.recent_tickets.first
ticket.update_attributes :state => 'solved' # Database update and cache expiration for both tickets and recent_tickets entries

The current version works only with the has_many macro.

How to install

$ ./script/plugin install git://github.com/jodosha/cached_models.git

Official page

http://lucaguidi.com/pages/cached_models

Europe RailsConf 2008

Posted by luca
on Monday, September 08

David Heinemeier Hansson at Euro RailsConf 2008
© 2008 James Duncan Davidson

This RailsConf has been very special for me for two reasons: it was the first time I joined this event, and because I was invited as speaker.

Berlin is a quite beautiful city, the ideal context for this kind of events, because its new breed in web and marketing entrepreneurialism. Try to go around in the north-east side, there is an huge amount of design firms and Starbucks shops full of creative people. Amazing.

The conference was full of talented developers, I met a lot of them, it's always inspiring to talk with people like them.

The speechs

Sep, 02

Ben Scofield has illustrated how to maintain a Rails application, through RESTful plugins, explaining why its the convenient choose in despite of gems, engines, and libs. Honestly, not so much interesting, I had expected something better by Ben.

Jonathan Weiss and Mathias Meyer talked about deploying solutions and monitoring for Rails. It was a nice overview, but, unfortunately, not so exhaustive, due to the speech duration.

Core Team panel: it was a friendly chat with three members of the Rails core team. They talked about the last year on Rails and about the future of the framework.

Sep, 03

David Heinemeier Hansson has talked about how to deal with legacy software. Very inspiring.

Michael Bleigh and Chris Selmer has explained how to enhance the user experience using javascript, and how get rid of it. Interesting.

Stefan Kaes, David Anderson and Larry Baltz, they gave an overview about their CRM product. Too detailed.

Alex MacCaw and Stuart Eccles presented their fantastic gem for realtime applications. They wrote also a Rails plugin to allow server pushing. Amazing!

Nick Sieger has introduced himself and his recent work on ActiveRecord connection pooling.

Jeremy Kemper in his speech about scaling web applications, has shared a lot of technical tips he used to speed-up Basecamp at 37signals. Priceless.

Sep, 04

David Black talked about the Ruby runtimes, language changes and adoption. Nice collective hacking session.

Christian Lupp is a designer and he showed us how Rails is a good prototyping tool.

Rany Keddo introduced a lot of Rails plugins for backgrounding time expensive tasks, including its solutions.

Sven Fuchs leads the Rails i18n team, he talked about the history of the i18n support in Rails, why they choose to create this group and about the work we are doing (me included) on the upcoming Rails 2.2. Interesting.

My speech

My speech has followed the Sven's one, it was concerned with the same argument: I presented to the big attendee Click to Globalize.
As you probably know, it's a Rails plugin, which extends the first version of Globalize, and allow to translate your page in-place.
The guys was attended my presentation, has appreciated how my software is focused on its goal and leaves out all the bloated stuff.

The rest

I spent the rest of the week visiting Berlin. Sven guided me in the east-side and the Mitte, and let me appreciate a wonderful place. Thanks man!
. Noteworthy was the dinner with David Black at the Japanese restaurant, just near the hotel.

Very nice experience. I hope to meet all of you, the next year.

Ruby Time marshaling bug in pre-1.9

Posted by luca
on Friday, August 29

Ruby's Time has a bug: when try to serialize an timezoned time, then unserialize it back, the result will use the server local time, instead of use the original time zone.

>> utc = Time.now.utc
=> Fri Aug 29 09:07:37 UTC 2008
>> marshaled = Marshal.dump utc
=> "\004\bu:\tTime\r\251\037\e\200\344\254T\036"
>> Marshal.load marshaled
=> Fri Aug 29 11:07:37 +0200 2008

This bug doesn't affects Ruby 1.9, but we still don't use that version for production purpose. If you use 1.8.x with Rails 2.1.0, your cached timestamps (including ActiveRecord objects), are probably wrong.

>> comment = Comment.first
=> #<Comment id: 865423346, post_id: 1, text: "Nice post.", created_at: "2008-08-29 09:27:48", updated_at: "2008-08-29 09:27:48">
>> Rails.cache.write('comment', comment)
=> true
>> Rails.cache.read('comment')

=> #<Comment id: 865423346, post_id: 1, text: "Nice post.", created_at: "2008-08-29 09:27:48", updated_at: "2008-08-29 09:27:48">
>> comment.update_attributes :text => "Nice post!"
=> true
>> Rails.cache.write('comment', comment)
=> true
>> Rails.cache.read('comment')
=> #<Comment id: 865423346, post_id: 1, text: "Nice post!", created_at: "2008-08-29 09:27:48", updated_at: "2008-08-29 11:28:42">


Look at the last updated_at attribute, it uses local time instead of UTC time zone.
The first time everything goes right, because #updated_at wasn't invoked and casted to a Time instance. It's a string, and the marshaling is ok.
But, when I update the object, ActiveRecord changes the value of that timestamp, but before, it cast it to a Time, and everything goes wrong.

I submitted a patch for this bug, it was committed, and will be available in the upcoming Rails 2.2 it's available in Rails 2.1.1. You are strongly encouraged to update your Rails version.

UPDATE 2008-09-08: This patch was already included in the Rails maintenance release 2.1.1.

Twitter Is Down

Posted by luca
on Friday, August 08


via [TechCrunch]

Less Is Not Laziness

Posted by luca
on Thursday, August 07

Doing less meaningless work, so that you can focus on things of greater personal importance, is NOT laziness. This is hard for most to accept, because our culture tends to reward personal sacrifice instead of personal productivity.
--Timothy Ferris

Click To Globalize: Ready for Rails 2.1!

Posted by luca
on Monday, July 21

Click to Globalize is ready for Rails 2.1!

I spent a lot of time to make this release the best of ever! I know that a lot of time has passed since the latest Rails major release, and I apologize for this.
The official Globalize it seems dead, but the great work of Nate Clark (aka heythisisnate) has made it compatible with Rails 2.1. Thanks Nate!
The Rails Edge now includes a basic support for i18n!

What's Changed?

The first big change is about the configuration, past versions has cluttered a bit your ApplicationController, I know, but now Click uses a YAML file configuration file for locales.

As you can see, it's more readable than put an Hash inside your main controller, and it also take the advantage to separate configuration from logic.

The second change regards the default language, you can use the above file to declare it, or use the Globalize syntax (Globalize::Locale.set_base_language('en-US')), but you have to choose a locale before the app starts.
This because Click needs a secure fallback mechanism, if no active Locale was set, it's always guarantees your application to work.

The third feature is about formatting: you can always choose between textile and markdown without editing ApplicationController, but using the same configuration file.

I removed the deprecated class method ApplicationController#globalize? in favor of the instance one. This means you can use it to turn on/off Click to Globalize, just returning a boolean value:

This version also includes tiny fixes, refactoring and cleanup.




You may wish to learn a bit about Click to Globalize, so I encourage you to visit the official page.
I hope you enjoy your i18n on Rails!

What's New In Rails Edge: i18n

Posted by luca
on Friday, July 18

Ruby on Rails has just integrated a basic support for i18n.

ActiveSupport

ActiveSupport now includes the i18n gem which provides the API and the settings for the default locale: en-US.
The gem abstracts the repository where the translations are stored, so all the plugin authors could write their own mechanism. The bundled repository is called Simple and stores all the settings in memory.

Declaring a locale is quite easy:

How can I translate or localize?

I18n#t is also useful to fetch locale defaults:

ActiveRecord

ActiveRecord now returns localized error messages for validations.

You may wish to declare your messages:

ActionPack

ActionView now supports translations and localization for time and currency helpers (i.e. distance_of_time_in_words, number_to_currency).


UPDATE 2008-07-19: Sven Fuchs wrote a i18n Rails manifesto and a technical post about the i18n API.

Sashimi 0.2.0!

Posted by luca
on Monday, July 14

Sashimi has just hit 0.2.0!

This release has no sugar for you! No new features, just test improvements and code robustness.

Sashimi: Getting Started Tutorial

Posted by luca
on Monday, June 30

Here a getting started tutorial for Sashimi

. Sashimi getting started tutorial

Released Sashimi 0.1.6

Posted by luca
on Monday, June 23

I just released a new version of Sashimi, with tiny fixes and a new home! In fact the project is also hosted on RubyForge, now you can install the gem with:

$ (sudo) gem install sashimi
or with:
$ (sudo) gem install jodosha-sashimi --source=http://gems.github.com

If you wish, you can visit the project pages on GitHub and on RubyForge.

UPDATE The release 0.1.6 is broken, you are strongly encouraged to update your gem with the newest 0.1.7.