solnic.eu

probably the best tagline in the world

Ruby DataMapper Status

In my recent post I gave you a brief overview of what I think about the state of Ruby ORMs. Since I’m involved in the development of DataMapper project I want to write a little more lines of text to give you a good overview of the current state of DataMapper project and how the future version 2.0 is going to look like.

DataMapper 1.x

Let’s get this straight once and for all: DataMapper was never a pure implementation of the Data Mapper pattern. It has elements of both Data Mapper and Active Record patterns. It has a mapping layer where you can configure mappings between model properties and database columns but this doesn’t change the fact that your models have direct access to the persistence layer and a lot of persistence-related functionality is mixed into them. This is what makes DataMapper an ‘ActiveRecord-ish’ library. After a few years of development it’s become clear that this approach, despite its advantages over ActiveRecord, is still not good enough.

Probably one of the biggest wins of DataMapper is support for many different kinds of data stores. Apart from supporting most common RDBMS databases there are adapters for various key-value stores, NoSQL databases and more. The flip side is that working with multiple data stores at once is not very stable at the moment and that you can’t easily use the full power of various databases, like MongoDB, due to limitations in DataMapper’s API.

The good news is that while working on DataMapper and many of its adapters we’ve learned our lessons. With all that knowledge and experience the work on DataMapper 2.0 has been started.

DataMapper 2.0

First of all the next major version of DataMapper will implement the Data Mapper pattern as described in the PoEAA:

A layer of Mappers that moves data between objects and a database while keeping them independent of each other and the mapper itself.

DataMapper 2 won’t be a big monolithic library, it will consist of multiple independent pieces that are glued together. Each piece of DM2 is a standalone library so that you could use it separately from the DM itself.

Let me describe all the related projects.

Veritas - the new relational algebra engine

The core of DM2 is Veritas - the new relational algebra engine developed by Dan Kubb. Why not ARel? The answer is simple - ARel is designed to generate SQL whereas DataMapper needs something more abstract with adapters that can handle different kinds of query dialects. With that premise Veritas is a full-featured relational algebra implementation and there’s already an SQL generator which can build pretty complex queries. More generators will be written soon.

Here’s a quick sneak-preview of how you can build relations with Veritas:

veritas-sample.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
header_one = [
  [ :id,   Integer ],
  [ :name, String ]
]

header_two = [
  [ :id,      Integer ],
  [ :user_id, Integer ],
  [ :name,    String ]
]

tuples_one = [
  [ 1, "john" ],
  [ 2, "jane" ]
]

tuples_two = [
  [ 1, 1, "john's project" ],
  [ 2, 2, "jane's project" ]
]

# build base relations
relation_one = Veritas::Relation::Base.new('one', header_one, tuples_two)
relation_two = Veritas::Relation::Base.new('two', header_two, tuples_two)

# rename conflicting attributes
relation_two = relation_two.rename(:id => :project_id, :name => :project_name)

# join the two relations on id == user_id
new_relation = relation_one.join(relation_two) { |r| r.id.eq(r.user_id) }

What’s great about Veritas is that with its level of abstraction you can use it for various things - not just to generate queries. For example there’s an idea of using Veritas to build a new “migrations” library for DM2 that will easily handle even very complex scenarios.

Virtus - the new model definition and introspection layer

I’ve already introduced Virtus - it’s an extraction of DataMapper’s Property API. During the last few months we’ve made many significant improvements and more features will be added soon too. Virtus already supports defining attributes on your models and can handle many kinds of coercions. You can also implement your own coersion methods if you need them. In the near future Virtus will be supporting more complex functionality like EmbeddedValue and ValueObject. It’s also possible that with Virtus you will be able to define relationships between POROs.

The important thing about Virtus is that it’s designed to work with PORO and it has nothing to do with any persistence concerns. For example there were people asking me about things like support for dirty attributes tracking - it’s not going to be included in Virtus.

I should mention that DataMapper 2.0 will be designed to work with POROs that are not extended by Virtus. Virtus will be optional but since it provides a very common functionality I suspect most people will want to use it.

Aequitas - the new validation library

Developed by Emmanuel Gomez, Aequitas is designed to work with any Ruby object and it also has support for Virtus. The idea is similar to what we have in DataMapper 1.x where validations can be derived from property declarations. Aquitas is based on the current dm-validations and the API is very similar, if not identical. Aequitas has support for custom error messages, I18n, validation contexts and built-in data types which come with their own set of validation rules.

aequitas_example.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
require 'virtus'
require 'aequitas/virtus_integration'

class Book
  include Virtus
  include Aequitas

  attribute :title,        String, :required => true
  attribute :published_at, Date
end

book = Book.new(:published_at => '')

book.valid? # => false
book.errors[:title] # => [ "can't be blank" ]"
book.errors[:published_at] # => [ "must be a date" ]

Session, Dirty Tracking and Unit of Work

In the Data Mapper world every change made to the models loaded into memory is tracked by a specialized object which works like a session. When you’re done with making changes you can either commit them or rollback. The important thing is that all the complex logic behind tracking what was changed, what was deleted and what was added is handled by the session object. Your models are dumb in this regard, they don’t care about dirty tracking, it’s not their responsibility. It’s one of the major differences between AR and DM.

The session object will be an implementation of the Unit of Work pattern described in PoEAA as:

Maintains a list of objects affected by a business transaction and coordinates
the writing out of changes and the resolution of concurrency problems.

More technically speaking a session will hold a DAG of commands sorted by their dependencies so that when you commit the session it will know in what order those commands should be executed.

When you think about it you will realize that this pattern is quite common. That’s why it would probably make sense to come up with a general UoW library and then create an extended version for DataMapper needs.

Here’s an example of how such a session may look like:

sample_uow_session.rb
1
2
3
4
5
6
7
8
9
10
DataMapper::Session.start do |session|
  user = User.mapper.get(1)
  user.name = 'John'

  if user.valid?
    session.commit
  else
    session.rollback
  end
end

The Mapper

Probably dm-core, the current core DataMapper library, will be completely rewritten and become the mapper layer with a thin query API that delegates most of the heavy work down to a veritas adapter. For your convenience there will be a veritas mapper class that you can inherit from but this doesn’t mean that you won’t be able to write custom mapper classes. The idea is really simple here, a mapper class defines mappings between PORO and the database schema. In most of the cases this means a direct 1:1 mapping but the huge advantage is that once you need something custom - you will be able to define it.

This is really the key aspect of using a data mapper library - you define your domain objects so that they correspond to your real world domain as close as possible. It makes applying practices like “Fast Rails Tests” suggested by Corey Haines come in a natural way because you’ll be implementing the business logic in POROs and have them unit tested in an isolation without the database access.

You will be able to define a mapper class more or less like this:

example_mapper.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class User
  include Virtus

  attribute :id,            IdentityField
  attribute :email,         String
  attribute :name,          String
  attribute :birthday_year, Integer
end

class User::Mapper < VeritasMapper

  # default 1:1 mapping
  map :id

  # custom field name
  map :email => :email_address

  # map to 2 fields
  map :name => [ :first_name, :last_name ]

  # map to a result of a function call
  map :birthday_year => :birthday_date, :function => :date

end

Roadmap? ETA?

There’s a work-in-progress roadmap for DM2 available here. Regarding ETA it’s really hard to say. We’re taking our time to build all these libraries, there’s a big focus on code quality and proper test and docs coverage. Once the roadmap is finalized we will be able to come up with some ETA.

Here’s the full list of related projects on Github:

…and more will come soon, so stay tuned!

Make sure to follow @datamapper on twitter too :)

If you’re eager to learn more you can always join #datamapper IRC channel. I also understand that this post doesn’t answer many possible questions - feel free to ask them in the comments.

The State of Ruby ORM

We have a lot of different Object-Relational Mapper implementations in Ruby (and a ton and a half of Mongo mappers ;)) and it’s probably a good thing. It seems like the only ORM that really matters right now is ActiveRecord although in “the background” we still have DataMapper and Sequel with growing communities. So I’m wondering…what’s the state of these ORMs? This post is my brain-dump on the subject with a potential to start a disccusion about the future of Ruby ORMs. This is a huge subject but I’ll keep it short.

(beloved) ActiveRecord

I’ve been a rails developer for almost 5 years now and I remember my initial excitement about ActiveRecord just like if it happened yesterday. I remember how blown away I was when I saw ‘an empty’ class in app/models with a ton of functionality added dynamically. I remember how happy I was when I started setting up associations for the first time and seeing that I can easily use them and everything just works OOTB. I remember how awesome it was to use built-in validations - a few lines of simple ruby code and my model is “secured” and invalid data won’t be persisted. Just like that! I also remember what a great feeling it was to use migrations for the first time, oh man there was even a generator which creates files for me, wonderful! Yeah, that was really great and I loved it.

Years were passing and my excitement was slowly disappearing and now it’s almost completely gone. Why? What happened? First of all I’m disappointed with AR3. I thought transition to ARel and the general Rail3 refactor will lead to a better codebase and nicer API. What we have now is like a hybrid of AR2 and something that was promised as AR3 which was not finished in 100%. The general lack of consistency in the API worries me. Too bad because making a major bump in the version number was a great opportunity to clean things up for good. Now we have to wait for 4.0. I’m also still facing various “WTF moments” when I see things like that:

wtf-ar.rb
1
2
User.where(:active => true).kind_of?(Enumerable)
 => false

Yeah I know that’s just rude to point things like that, right? On the other hand is this what you would expect from a library which has a version number > 3.0? I’d expect some level of maturity but what I see now is still a bit of a mess. It’s definitely getting better so probably, with this level of support that AR has now, version ~5.0 will be truly great and mature. I’m really looking forward to that.

Through all those years ActiveRecord got a lot of great features though. Lazy queries, attribute serializers, prepared statements just to name a few. Extracting ActiveModel was also a huge step into the right direction and I’m very happy with it. It’s all great and the improvement is clearly visible.

On the other hand there are still cases where ActiveRecord fails. For instance it still has problems with proper handling of object graph. Which isn’t a great surprise because it’s a tough problem to solve and none of the 3 ORMs has solved it yet.

(bold) DataMapper

With ActiveRecord you get things done, that’s true. Just read the recent post from Xavier Shay “DataMapper Retrospective” where he writes why he likes DataMapper and despite that why he chooses ActiveRecord. He writes “This is my responsible choice at the moment” - I would expect that in many, many cases people pragmaticaly and wisely choose ActiveRecord because the support from community is important and ActiveRecord does have the best support at the moment. When you get yourself into trouble with AR you will likely find help relatively quickly.

After reading Xavier’s post I feel obliged to comment on it. First of all I agree with him and his decisions. DataMapper is trying to solve bigger problems than AR and Sequel. It’s obviously much harder to support any kind of a storage system and it requires a lot of work. It definitely requires more than a couple of years of development and one stable version. DataMapper 1.x series was a great milestone as the API became stable and it’s truly great, just look at this:

sample.rb
1
2
3
4
5
# DataMapper
User.all.posts.comment.all(:created_at.lt => DateTime.now)

# ActiveRecord
User.includes(:posts => :comment).where(:comments => { :created_at.lt => DateTime.now  })

DataMapper introduced a lot of fantastic solutions and just recently ActiveRecord started catching up. It doesn’t change the fact that DataMapper 1.x is much harder to use when you have to resort to raw SQL. That’s why I perfectly understand why Xavier prefers AR and Sequel - both ORMs are built specifically to handle RDBMS and they do it in a decent way.

This post would get too big if I started to write more about DataMapper that’s why I’m stopping now. I will write about what’s happening in the DataMapper camp in a separate post where I will give you an overview of our plans for the near future - expect a lot of goodness to say the least.

To quickly sum up - DataMapper is not there either but getting to the point where we are now was a great experience that’s given us knowledge about how certain problems should be solved. More about this in a separate post…

(impressive) Sequel

I’ve never been a sequel user. I only tried it out a couple of times in the past and it was really nice. The codebase looks much cleaner than in case of ActiveRecord and the feature set is truly impressive. I’m also absolutely amazed that this project has 0 issues on github - HUGE congratulations to Jeremy Evans. He’s doing a fantastic work and I’m really impressed so you should be.

I remember that Sequel introduced various advanced features before AR did - like lazy data sets (aka lazy execution of queries). You probably quickly forgot or you aren’t aware of the fact that AR was the last Ruby ORM that introduced this feature.

I’ve heard from many people that are familiar with Sequel that it’s simply better than ActiveRecord in every aspect. I would not be surprised if this turns out to be true.

I would love to hear more about your experiences with Sequel so please feel free to leave comments!

The State of ORMs?

Right. So where are we now with our favorite ORMs? In my opinion whether it’s ActiveRecord, DataMapper or Sequel - we’re still “not there yet”. I’ve been looking at other languages lately and it’s pretty clear that in Java, Python and PHP most popular ORMs implement the Data Mapper pattern. I’m not saying that this pattern is better. There’s been an open debate about AR vs DM patterns since for ever and there’s no ultimate answer. The fact is, though, that in most of the cases DM is the preffered one. And ORMs in other languages reflect that. Java with its powerful Hibernate, Python with its SQLAlchemy and PHP with its Doctrine. All those projects are mature, have solid codebases and solve hard problems using well known design patterns.

I really like what I see in those ORMs. They all implement Unit Of Work, Identity Map and a lot of other patterns that I didn’t have time to identify. It’s all there. Damn hard problems solved in a clean way with OOP approach and design patterns that were known for many years. When you open up sources of SQLAlchemy or Doctrine you are able to quickly navigate through those projects - classes are well organized and it’s easy to figure things out.

I understand why people like “the less is more” and “convention over configuration” but personally I would love to see more explicitness in Ruby ORMs. Metaprogramming is a dangerous weapon and we shouldn’t forget about this. You probably think “STFU and switch to Java” now. Well, that’s not gonna happen :)

All of this doesn’t change the fact that I believe we can still do better. By looking at other languages we can find a lot of inspirations but many things can be done in a much better way in Ruby.

I would love to get some feedback from you. Are you happy with your ORM of choice?

Making ActiveRecord Models Thin

“Skinny Controller, Fat Model” is a well known best practice in Ruby community. Everybody seems to agree with it and follows it. It’s pretty clear what a skinny controller means. The question is what is a fat model and what should we do if it gets too fat? Even better, what should we do to avoid too fat model? I think many people still confuse Domain Model with ActiveRecord. It’s something more and in this post I will try to explain my new approach to writing Ruby on Rails applications.

Also, I would like to thank Steve Klabnik who triggered the process of writing this post by tweeting this:

We need something better. Persistance and logic are two separate responsibilities
that every rails app combines.

I’m really glad more and more people are starting to realize this.

Behavior vs Data

When we say “model” we usually think about ActiveRecord. In Ruby on Rails world this is how we established things. “M” in the MVC means app/models with a bunch of ActiveRecord model files. This is where the domain logic of our applications lives. I think we should stop thinking like that.

Martin Fowler defines Domain Model as:

An object model of the domain that incorporates both behavior and data.

We should remember though that the way your Domain Model behaves and the way your data are persisted are two separate concerns. ActiveRecord objects represent your data. They give you a low level interface to access your data. Yes, low level. If you mix domain specific behavior into ActiveRecord models you will create classes with too many responsibilities. By violating Single Responsibility Principle model code becomes difficult to extend, maintain and test. I have seen it many times, I’m pretty sure you have too.

A few months ago I stumbled upon this quote:

I pull the behavior out of my models into other objects that wrap the models.
I prefer to make the AR objects simple wrappers around the db-access stuff in AR.

I have a fairly strict rule that controller actions cannot use AR finders or,
in fact, interact with AR at all. AR should be accessed within api methods
inside your model, not from the outside.

This describes exactly what I’ve started doing in my recent Rails projects. The outcome of this approach is more than great. I literally left ActiveRecord models with only validation rules, scopes and before/after hooks. The rest is handled by a separate class hierarchy with domain-specific functionality. Those clases use ActiveRecord models only for the persistence.

Well Defined API

Something that always bothers me in a typical Rails application is the lack of a well defined model API. Your Domain Model should have an interface to every action your application should be able to perform. If you have an online shop where a user can buy a product then with a well-written Rails application you should be able to fire up the console and be able to easily perform this operation. If it’s not so simple then you probably want to think about your model implementation again.

What makes it so hard for us to design and implement a good API for our model? In my opinion it happens because we start with the data instead of behavior. For example if you’re building an online shop, how do you start the design and implementation process? In Rails you probably create migration files to create a db schema. Right? You initially think about the database columns you need to create and validation rules you need to define in the models. After you have all this done you start thinking about the behavior. You add various methods to your ActiveRecord models so they can create new objects, validate and persist them. In the end both data and behavior of your system is mixed together in ActiveRecord models. If you change a column in some table, your system stops working and it’s relatively difficult to fix. Why? Because the domain behavior is tightly coupled with the database schema. Because you started with the db schema and added behavior later.

How about reversing that process and starting with the behavior implemented in separate classes that are not coupled with the database schema? This way you will define your API at a higher level. What’s more important you will start with an API and you will add the persistence logic later.

Behavior & API

The key difference between using ActiveRecord models and domain model classes is that in case of the latter you clearly specify the behavior. For instance if I want to find a product in my online shop, how do I do that? Well, with ActiveRecord Product model I have plenty of choices. I can #find or #find_by_id or #where(:id => id).first etc. This is problematic because the same operation can be done in many different ways. Our goal is to create a consistent behavior that is the same in every place of our application.

Let’s use a simplified example of an online shop and focus on one core behavior - selling a product. Here’s a code spike how it could be modelled:

shop.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class Shop
  class Warehouse
    def self.find(id)
      # returns a product
    end
  end

  class Customer
    attr_reader :user

    def self.find(id)
      # returns a user
    end

    def initialize(user)
      @user = user
    end

    def pay(product)
      # perform the payment
    end
  end

  class Transaction
    attr_reader :customer, :product, :status

    def initialize(customer, product)
      @customer   = customer
      @product = product
    end

    def commit
      @status = customer.pay(product)

      if success?
        commit!
      end
    end

    def commit!
      # do some stuff to persist data about a successful transaction
    end

    def success?
      status === true
    end
  end
end

So, Warehouse can find a product, Customer can find a user, a customer instance can pay for a product and Transaction handles selling a product to a customer. With this ridiculously basic example let’s see how we can write a spec for Transaction:

shop_transaction_spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
describe Shop::Transaction, '#commit' do
  subject { transaction.commit }

  let(:user)        { mock('customer') }
  let(:product)     { mock('product') }
  let(:transaction) { described_class.new(customer, product) }

  before do
    customer.should_receive(:pay).with(product).and_return(payment_status)
  end

  context 'when payment is successful' do
    let(:payment_status) { true }

    its(:success) { should be(true) }
  end

  context 'when payment is not successful' do
    let(:payment_status) { false }

    its(:success) { should be(false) }
  end
end

Running the spec gives you this output:

1
2
3
4
5
6
7
8
9
10
Shop::Transaction#commit
  when payment is successful
    success
      should equal true
  when payment is not successful
    success
      should equal false

Finished in 0.00182 seconds
2 examples, 0 failures

This way we started off by defining our API, it’s pretty simple to use:

sample.rb
1
2
3
4
5
customer    = Shop::Customer.find(customer_id)
product     = Shop::Warehouse.find(product_id)
transaction = Shop::Transaction.new(customer, product)

transaction.commit

Note that we designed and implemented the behavior and we could easily write a spec that checks if that behavior is correct. What about real data and persistence?

Behavior + Persistence

To continue with the shop example let’s add ActiveRecord models:

models.rb
1
2
3
4
5
6
7
8
9
10
11
12
class User < ActiveRecord::Base
  validates :email, :name, :presence => true
end

class Product < ActiveRecord::Base
  validates :name, :sold, :presence => true
end

class Order < ActiveRecord::Base
  belongs_to :user
  belongs_to :product
end

Now let’s use these models in our domain model classes:

shop.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
class Shop
  class Warehouse
    def self.find(id)
      Product.find_by_id(id)
    end
  end

  class Customer
    attr_reader :user

    def self.find(id)
      User.find_by_id(id)
    end

    def initialize(user)
      @user = user
    end

    def pay(product)
      # perform the payment
    end
  end

  class Transaction
    attr_reader :customer, :product, :order, :status

    def initialize(customer, product)
      @customer = customer
      @product  = product
    end

    def commit
      @status = customer.pay(product)

      if success?
        commit!
      end
    end

    def commit!
      create_order

      if order.persisted?
        mark_product_as_sold
      end
    end

    def success?
      status === true
    end

    private

    def create_order
      @order = Order.create(:user => customer, :product => product)
    end

    def mark_product_as_sold
      @product.update_attribute(:sold, true)
    end
  end
end

This way we hide all the details about our db schema behind objects holding the domain logic behavior of our shop application. If something changes with the ActiveRecord models you will only need to change the implementation in one place because there’s one way of finding a user and a product and placing an order.

Testing Benefits

With the approach I described it’s really easy to write solid tests. You can test the behavior in a complete isolation from the db models which results in fast execution of those tests. Most of the logic of your system can be unit-tested without touching the database, this means thousands of test examples running in less than a second. On the other hand when testing ActiveRecord models you are only concerned about validation rules, hooks and finder methods cause there’s no more logic there. It makes the AR tests really clean and easy to maintain.

Feedback?

I understand that it may seem like a heavy approach and Ruby on Rails is all about rapid development and writing less code. However, every project I’ve seen that evolved in something more than a blog written in 15 minutes, sooner or later become a huge mess. I don’t think programmers are guilty here. We’ve been taught to use certain tools and practices and now it’s time to move on, take a step forward.

Still here? Awesome! I would love to get feedback about how you’re dealing with complex logic in your Rails applications - so feel free to comment and let’s start an interesting discussion.

Virtus - Attributes for Your Plain Ruby Objects

I’m happy to announce the first release of Virtus gem. It is an extraction of DataMapper Property API with various tweaks and improvements. If you like how properties work in DataMapper and would like to use such functionality in your plain ruby objects then you should give Virtus a try.

It is an early release but I would not expect many API changes before 1.0.0 since the code is based on the stable DataMapper API and I’m quite happy with it.

How to install?

Virtus is just a gem and comes with no dependencies. To install just run this in your shell:

sample.sh
1
gem install virtus

Why?

As some of you know we’re starting to work on DataMapper 2.0. It will be a true implementation of the Data Mapper pattern and will use a certain set of libraries under the hood. Dan Kubb has already finished his absolutely fantastic relational algebra engine called Veritas along with Veritas SQL Generator - these gems will be the core part of DataMapper 2.0 Query System.

When we were talking with Dan about the future of Property API in DataMapper we both agreed we need an abstraction for defining your classes that would be decoupled from any persistence logic. We also agreed that we actually don’t like “property” word in that context and would prefer “attribute”. There you go - Virtus was borned :)

How does it work?

Virtus works in an almost identical way as Property in DataMapper. You can define attributes in your classes and it will create accessors to these attributes along with typecasting abilities. It comes with a set of builtin attribute types but you are free to add your own types too.

The API is dead-simple. Here’s an example class:

sample.rb
1
2
3
4
5
6
7
8
class Book
  include Virtus

  attribute :title,         String
  attribute :author,        String
  attribute :publish_date,  Date
  attribute :readers_count, Integer
end

This creates 4 attribute objects that are associated with your class. Each of these attributes is responsible for reading and writing values. Values are stored as standard instance variables.

You can easily inspect what attributes a class has:

sample.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
pp Book.attributes

{:title=>
  #<Virtus::Attributes::String:0x8aeb548
   @instance_variable_name="@title",
   @model=Book,
   @name=:title,
   @options={:primitive=>String, :complex=>false},
   @reader_visibility=:public,
   @writer_visibility=:public>,
 :author=>
  #<Virtus::Attributes::String:0x8aea300
   @instance_variable_name="@author",
   @model=Book,
   @name=:author,
   @options={:primitive=>String, :complex=>false},
   @reader_visibility=:public,
   @writer_visibility=:public>,
 :publish_date=>
  #<Virtus::Attributes::Date:0x8ae90e0
   @instance_variable_name="@publish_date",
   @model=Book,
   @name=:publish_date,
   @options={:primitive=>Date, :complex=>false},
   @reader_visibility=:public,
   @writer_visibility=:public>,
 :readers_count=>
  #<Virtus::Attributes::Integer:0x8ae7e84
   @instance_variable_name="@readers_count",
   @model=Book,
   @name=:readers_count,
   @options={:primitive=>Integer, :complex=>false},
   @reader_visibility=:public,
   @writer_visibility=:public>}

Every attribute type has the primitive option set. When you are setting a value of an attribute, the corresponding attribute object will check if the value has the correct type. If the type doesn’t match the primitive, then the attribute will typecast the value.

Available Attribute Types

As I mentioned Virtus comes with various attribute types built-in:

  • Array
  • Boolean
  • Date
  • DateTime
  • Decimal
  • Float
  • Hash
  • Integer
  • Object
  • String
  • Time

These classes are organized in a hierarchy where Object inherits from an abstract Attribute class and all other types inherit from Object.

Options For Defining Attributes

When defining an attribute you can provide additional options. Every attribute class has a list of options that it accepts.

At the moment you can only use options for access control:

sample.rb
1
2
3
4
5
6
7
class User
  include Virtus

  attribute :name,  String,  :accessor => :public
  attribute :email, String,  :reader   => :protected
  attribute :age,   Integer, :writer   => :private
end

It is possible to set a default value of an option directly on an attribute class:

sample.rb
1
2
3
4
5
6
7
8
9
10
Virtus::Attributes::String.reader(:protected)

class User
  include Virtus

  # :reader option will be set to :protected
  attributes :name,  String
  # you can override the default if you want
  attributes :email, String, :reader => :public
end

Custom Attribute Types and Options

Just like in DataMapper you can implement your own attribute types. Whenever you need some twisted typecasting logic or you need to use extra options you can create a custom attribute class.

Here’s an example use-case - let’s say you want a hash and you need to stringify or symbolize the keys.

sample.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
require 'active_support/core_ext/hash/keys'
require 'virtus'

module MyApp
  module Attributes
    class Hash < Virtus::Attributes::Object
      primitive ::Hash

      # Define extra options that this attribute class accepts
      accept_options :stringify_keys, :symbolize_keys

      # Set up default values for our extra options
      stringify_keys false
      symbolize_keys true

      # Typecast logic is depends on the options
      def typecast(value, object)
        if options[:stringify_keys]
          return value.stringify_keys
        end

        if options[:symbolize_keys]
          return value.symbolize_keys
        end
      end
    end
  end
end

Let’s use our custom attribute:

sample.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
class Post
  include Virtus

  attribute :settings, MyApp::Attributes::Hash
  attribute :meta,     MyApp::Attributes::Hash, :stringify_keys => true
end

post = Post.new(
  :settings => { 'foo' => 'bar' },
  :meta     => { :foo  => 'bar' })

puts post.settings.inspect # => {:foo => 'bar'}
puts post.meta.inspect     # => {'foo' => 'bar'}

Other ORMs?

It’s a bit early to talk about that but I would love to see other Ruby ORM libraries using a common gem for model attributes. After we integrate DataMapper with Virtus it should be feasible for others like Mongoid, MongoMapper or even ActiveRecord (sic!) to use Virtus too. Well, at least that’s my ultimate goal.

Let’s not reinvent the wheel!

Resources

Here are links related to the project:

Enjoy!

Custom RSpec-2 Matchers

RSpec is one of my favorite tools. I have literally fallen in love with this fantastic BDD library, especially with its second version. While using RSpec I realized it teaches me how to write tests. Yes, exactly - learning RSpec DSL, its syntax and structure of spec examples you actually learn the best practices in writing tests. RSpec, despite many built-in matchers, comes with a DSL for defining your own, custom matchers. It’s so easy that you’re not gonna believe this.

Basics

In RSpec matchers are nothing but methods available in the context of an example. You use them to make sure that a given expectation is met. There are many matchers that come with RSpec for instance here is how you can use the respond_to matcher:

sample.rb
1
2
3
describe String do
  it { should respond_to(:gsub) }
end

It’s so clean and beautiful that I probably don’t have to explain what this piece of code does, right?

Tip: When you call describe with a class as an argument, RSpec will automatically create an instance of that class and make it available via subject method. Subject is also the default context of an example block. That’s why we don’t have to write “subject.should respond_to(:gsub)”, because by default “should” or “should_not” is called on the subject.

Alright, for a list of available matchers check out the official docs. Let’s focus on writing our own matchers. If you’re wondering why you would need to do that, let me show a simple example of a User model spec:

sample.rb
1
2
3
4
5
6
7
8
9
10
11
describe User do
  before { subject.email = "foobar" }

  it "should have errors on email" do
    subject.errors.should have_key(:email)
  end

  it "should have correct error message" do
    subject.errors[:email].should include("Email is invalid")
  end
end

Now, you probably can imagine that almost identical code could be used in many other cases for many other model classes. Those 6 lines of code can be written as 1. You just need a custom matcher.

Defining a custom matcher is simple. Let’s start with a basic one that checks if a given model instance has validation errors:

sample.rb
1
2
3
4
5
6
RSpec::Matchers.define :have_errors_on do |attribute|
  match do |model|
    model.valid? # call it here so we don't have to write it in before blocks
    model.errors.key?(attribute)
  end
end

And we can use it like that:

sample.rb
1
2
3
4
5
describe User do
  before { subject.email = "foobar" }

  it { should have_errors_on(:email) }
end

It covers only the first expectation, but it’s a good starting point.

Chaining

The second expectation in the example is to see if the correct validation error message is set. It’s possible to run matchers in a chain so let’s see how we can implement chaining in our custom matcher:

sample.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
RSpec::Matchers.define :have_errors_on do |attribute|
  chain :with_message do |message|
    @message = message
  end

  match do |model|
    model.valid?

    @has_errors = model.errors.key?(attribute)

    if @message
      @has_errors && model.errors[attribute].include?(@message)
    else
      @has_errors
    end
  end
end

It’s really that simple. Now the matcher checks two things and returns true only if the message exists and if it matches the expected one.

Let’s use it:

sample.rb
1
2
3
4
5
describe User do
  before { subject.email = "foobar" }

  it { should have_errors_on(:email).with_message("Email has an invalid format") }
end

Nice! One line instead of six. But that’s not everything, with a failing spec failure messages might look like that:

sample.sh
1
2
3
4
5
6
7
8
9
10
F

Failures:

  1) User when email is not valid
     Failure/Error: it { should have_errors_on(:email).with_message("Email has an invali format") }
       expected #<User @id=nil @email="foobar"> to have errors on :email

Finished in 0.00047 seconds
1 examples, 1 failure

It’s automatically generated by RSpec based on the matcher name. It’s ok, but notice that it won’t tell us if the error message was incorrect. That’s why we need to set custom failure messages.

Custom failure messages and it’s done!

It is really recommended to use meaningful failure messages. We need to set 2 types of them, first one for “should” and second one for “should_not” expectations. The idea is that if there is an error and the message is not correct, we need to show that information in the failure output.

So, our complete matcher looks like that:

sample.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
RSpec::Matchers.define :have_errors_on do |attribute|
  chain :with_message do |message|
    @message = message
  end

  match do |model|
    model.valid?

    @has_errors = model.errors.key?(attribute)

    if @message
      @has_errors && model.errors[attribute].include?(@message)
    else
      @has_errors
    end
  end

  failure_message_for_should do |model|
    if @message
      "Validation errors #{model.errors[attribute].inspect} should include #{@message.inspect}"
    else
      "#{model.class} should have errors on attribute #{attribute.inspect}"
    end
  end

  failure_message_for_should_not do |model|
    "#{model.class} should not have an error on attribute #{attribute.inspect}"
  end
end

Now if we run our example and it fails because an error message doesn’t match the expectation, we will get following failure message in the output:

sample.sh
1
2
3
4
5
6
7
8
9
10
11
F

Failures:

  1) User
     Failure/Error: it { should have_errors_on(:email).with_message("Email has an invalid format") }
       Validation errors ["Email is blah"] should include "Email has an invalid format"
     # ./_examples/rspec2_matchers.rb:55:in `block (2 levels) in <top (required)>'

Finished in 0.00053 seconds
1 example, 1 failure

Summing up

As you can see implementing custom RSpec matchers is easy trivial and it’s a highly recommended practice. There are plenty of use cases where you want to write custom matchers. It makes your specs clean and even more readable and what’s most important it keeps your spec’s code DRY and extendable.

Here are some resources if you want to learn more:

Moving From WordPress to Jekyll

Hello World! As usual it’s been a while since I wrote anything here. Just wanted to say that I’m moving the site from WordPress to Jekyll and I like to share what I have learned so far. If you are considering a migration too here are the steps I have taken in order to port most of the tiny content of my blog. Read on and let me know if something can be done in a better (or even completely different) way.

Posts migration

I followed the instruction on the official Jekyll wiki. It worked without any troubles. I only had to manually change file extensions from “html” to “textile”, since that’s what I was using with WordPress to format my posts. Generated post files have YAML fronts with additional information taken from WordPress, specifically post ids and permalinks.

Nginx setup

I had to make sure that old urls from WordPress will redirect correctly to the new ones. Fortunatelly it’s easy to do that with Nginx, here’s my config:

Liquid error: ClassNotFound: no lexer for alias ‘conf’ found

This makes sure that urls with format “/year/month/day/post-title” will be redirected to “/year/month/day/post-title.html”. I didn’t take care of categories and tags urls, but it would be as easy to handle as in case of post permalinks.

Setting up Jekyll

This was (actually still is as I haven’t finished) also a straightfoward task. There is a nice overview on the wiki that describes the basics you need to know about Jekyll. Configuration has defaults that work for me except pygments that I use for code highlighting which is turned off by default. Every additional setting that you add to _config.yml will be available via “site” object in your templates, so it’s handy to configure at least your site’s url.

Layouts

In Jekyll you can easily nest layouts. I use 4 layouts, where “default” is the base one:

  1. default
  2. page
    • this is used for “static” pages, like About, Contact etc.
  3. post - used by blog posts
  4. tag - used by “tag” pages which show all posts tagged with a given tag

Posts

Index page displays a list of post excerpts. With Jekyll you can include “partial” templates by adding them to _includes folder. Here’s how you can use it, given you have “_includes/excerpt.html” in your project:

1
2
3
4
5
6
7
8
9
10
11
12
---
layout: default
title: Home
---

<ul class="posts">
  \{\% for post in site.posts limit: 15 \%\}
  <li>
    \{\% include excerpt.html \%\}
  </li>
  \{\% endfor \%\}
</ul>

where excerpt.html could look like this:

sample.html
1
2
3
4
5
6
7
8
9
10
11
12
<article class="excerpt">
  <header>
    <h2>
      <time pubdate datetime="\{\{ post.date | date_to_xmlschema \}\}">
        \{\{ post.date | date_to_string \}\}
      </time>
      »
      <a href="\{\{ post.url \}\}">\{\{ post.title \}\}</a>
    </h2>
  </header>
  \{\{ post.content | truncatewords:80 \}\}
</article>

Tags

I had troubles using categories with Jekyll so after all I decided to just use tags. You can tag a post with YAML front:

template.erb
1
2
3
4
5
6
7
8
---
title: My Post
tags:
  - foo
  - bar
---

post content

Then all the tags will be accessible via site object in your templates. For example you can list your tags along with post counts like that:

sample.html
1
2
3
4
5
6
7
<ul>
  \{\% for tag_data in site.tags \%\}
    <li>
      \{\{ tag_data[0] }} (\{\{ tag_data[1].size \}\})
    </li>
  \{\% endfor \%\}
</ul>

I put pages that list tagged posts in “tags” folder which makes them accessible via “/tags/some-tag.html” urls. I still need to write a rake task which dynamically generates these templates. Rake task is done and it looks like that:

sample.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
namespace "tags" do
  desc "Generate tag pages"
  task :generate_pages do
    folder = "tags"

    site.tags.each do |tag, posts|
      tag_page = "#{folder}/#{tag}.html"

      File.open(tag_page, 'w') do |file|
        file.write <<-EOS
---
layout: tag
title: solnic.eu / tags / #{tag}
name: #{tag}
---

<ul class="posts">

</ul>
        EOS
      end
    end
  end
end

Code highlighting

I use Pygments to highlight code snippets. Installation instruction for various platforms is also on the wiki. Once you got it installed you will need to generate CSS:

sample.sh
1
pygmentize -f html -S default > pygments.css

Where “default” is the name of a pygment theme. Here are available built-in pygments themes:

  • autumn
  • borland
  • bw
  • colorful
  • default
  • emacs
  • friendly
  • fruity
  • manni
  • monokai
  • murphy
  • native
  • pastie
  • perldoc
  • tango
  • trac
  • vs

To learn more about Pygments you can check out the docs.

In order to highlight a code sample in your post you just wrap everything in a liquid “highlight” block providing language name as an argument. Check out the list of all languages supported by Pygments, pretty impressive, BrainFuck included :). For instance if you want to highlight a ruby snippet you do this:

sample.sh
1
2
3
\{\% codeblock sample.rb \%\}
puts "Hello World!"
\{\% endcodeblock \%\}

Comments - importing to Disqus

This is still a work in progress. You can export entire content of your WordPress blog to a special XML feed called “WordPress eXtended RSS”. Then you upload this file via Disqus’ import tool. There is also another way, you can use Disqus WordPress plugin to do the import automatically. Unfortunately neither of these methods worked for me. It seems like the generated file is corrupted, but the data are there so I will have to manually parse it and generate a new import XML file. YAY…!

Resources

Here are some related links that you may find useful:

Rack Middleware Contest

CodeRack is a coding contest dreamed up by a group of the Ruby programmers at Lunar Logic Polska who were excited about the possibilities of Rack middleware. The team wants to encourage Ruby developers to explore the possibilities and what better way than to hold a contest? The secondary goal of the contest is to generate a set of open source solutions that will solve real problems and inspire others. Every entry will be released under the MIT open source license.

Programmers are encouraged to submit contest entries that will be judged based on the cleverness of the application and the elegance of the code. Entries can be submitted at coderack.org until midnight EST November 15th. Finalists are scheduled to be announced on the 1st of December and public voting will run for one month. The final winners will be announced on the 5th of January.

The first round of the contest will be judged by an elite panel of judges including Ben Bangert of O’Reilly Media, Chris Wanstrath and PJ Hyett of GitHub, Joshua Peek of 37Signals, Yehuda Katz of Engine Yard and Rails core team member, Ryan Tomayko of Heroku, Core Rails team member Matt Aimonetti, and the Rails Envy team of Gregg Pollack and Jason Seifer.

Once the finalists have been selected by the panel, the public will vote for the top prize winners.

Prizes have been donated by Bytemark Hosting, GitHub, Jetbrains, Mindmeister, Freelance Total, Heroku, Rackspace Hosting, Peepcode, BDDCasts, and Zenbe Shareflow. The top prize includes a dedicated quad core server package and is valued at over $3000. Every entrant will receive a credit from bddcasts.com and $30 credit from Heroku. All finalists will receive a package including Zenbe Shareflow subscriptions, a RubyMine license from JetBrains, and five credits from bddcasts.com. Details of all of the prize packages will soon be available on the coderack.org website.

More information about the contest, including the contest rules, can be found at coderack.org.

ps. This post is a copy from Lunar Logic Polska blog

Unobtrusive JavaScript Helpers in Rails 3

A while ago I have written a post about JavaScript helpers in Ruby on Rails and tried to explain why they are a bad idea. It’s hard to believe for me that it was almost 2 years ago! Since then so many things have happened in the Ruby world…Now Rails 3 is on its way and we already know what significant improvements and changes it will include. One of them is related to JavaScript helpers and the way how remote links and forms will be handled and I must admit that the new idea is absolutely great.

The new way is based on unobtrusive approach to JavaScript. This means that HTML code will be separated from JavaScript. I have checked out the latest sources of Ruby on Rails and found out that some of the work is already done. There is a new helper called AjaxHelper, it implements link_to_remote method which in the moment of writing this post looks like this:

sample.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def link_to_remote(name, url, options = {})
  html = options.delete(:html) || {}

  update = options.delete(:update)
  if update.is_a?(Hash)
    html["data-update-success"] = update[:success]
    html["data-update-failure"] = update[:failure]
  else
    html["data-update-success"] = update
  end

  html["data-update-position"] = options.delete(:position)
  html["data-method"]          = options.delete(:method)
  html["data-remote"]          = "true"

  html.merge!(options)

  url = url_for(url) if url.is_a?(Hash)
  link_to(name, url, html)
end

What you see here will generate a clean markup with HTML5-compliant attributes prefixed with a word “data-”. If you are not familiar with them you can checkout a nice article by John Resig HTML 5 data- Attributes. Those attributes will instruct the additional JavaScript code how it should handle the behavior. Basically all links, buttons and forms that have the special attribute “data-remote” set to “true” will issue an AJAX request. There has been a discussion on the Rails on Rails Core group about how to implement corresponding JavaScript code. People are worried about its performance since finding all elements with data-remote=true appears to be slow in case of Prototype and jQuery. Moreover there is a problem of new elements that may be dynamically inserted after the page was loaded and all the event listeners were attached. Fortunately there is no need to be worried as our situation is a perfect example where we should use Event Delegation. DHH has already showed in his Rails 3 and the Real Secret to High Productivity presentation how links and buttons can be handled by Prototype library and it looks absolutely reasonable to me.

I would like to focus on jQuery though as it’s getting more popular even in the Rails community. Great example is my job where we use jQuery in every of our new projects. So how can we handle new remote links and forms using this popular library? Actually it’s ridiculously easy. Thanks to jQuery.live function we can easily use Event Delegation to handle AJAX calls. Just take a look at this sample of a markup that new helpers in Rails 3 will generate:

sample.html
1
2
3
4
5
6
7
8
<!-- the new link to remote -->
<a href="/users" data-remote="true">Users</a>

<!-- the new remote form -->
<form action="/users" method="post" data-remote="true">
  <input type="text" name="login"/>
  <input type="submit"/>
</form>

Pretty clean, I really like it! Now let’s see how we can implement jQuery handler that will send AJAX requests:

sample.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var request = function(options) {
  $.ajax($.extend({ url : options.url, type : 'get' }, options));
  return false;
};

// remote links handler
$('a[data-remote=true]').live('click', function() {
  return request({ url : this.href });
});

// remote forms handler
$('form[data-remote=true]').live('submit', function() {
  return request({ url : this.action, type : this.method, data : $(this).serialize() });
});

The above code will send an AJAX request when you click on a remote link or submit a remote form. Note that it will work also with new elements dynamically inserted to the DOM. The example JavaScript code is the bare minimum of course, we could have something much more sophisticated. We will be able to specify success and failure handlers and also elements that should be updated with an AJAX response text (and probably much more!), hence the JavaScript is going to be more complicated.

This is definitely a step into the right direction. I’m looking forward to Rails 3!

Client-side Rendering With Prototype

Web applications are getting more and more complex. The user interface of a modern web application can be as rich as its desktop equivalent. If we use JavaScript/HTML/CSS trio to build this UI then we definitely want to use AJAX. A typical approach is to use AJAX to update parts of our page using an HTML response, everyone knows that, right? Does this approach allow us to create a responsive, fast and flexible UI? The answer is no.

Here are 4 main downsides of using AJAX requests to load UI parts:

  • You increase the server load – yes, you make an AJAX request only because you need a piece of HTML code that you want to insert to an already rendered page. That was cool a few years ago when AJAX was such a great innovation. Nowadays it should be considered as a less efficient solution.
  • You complicate the server-side code – because you need parts of your page to be returned by the server you, obviously, need to handle that by writing more server-side code. You end up having many actions in your controllers that return different fragments of HTML. I know, you think it’s normal, everyone does that.
  • You loose a lot of control over the UI – you use DHTML techniques to deal with the UI and in the same time you need the server to get parts of that UI. This leads to a code duplication and in many cases ends up with a big mess.
  • A user will have to wait until a request is done – that just sucks, that poor guy has to wait because you went back to the server for a little piece of HTML. How you are going to implement a responsive UI this way? “Your servers are fast”. Of course they are, but what if user’s ISP sucks? What if the user is downloading something and 99% of his bandwidth is gone?

Rendering HTML on the client-side is ridiculously simple. Consider the following example. Let’s say we have a page with a list of some people, the list is just a simple HTML table. It could look like this:

sample.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<table>
  <thead>
    <tr>
      <th>First Name</th>
      <th>Last Name</th>
      <th>E-Mail</th>
    </tr>
  </thead>
  <tbody id="people">
    <!-- here go people -->
  <tbody>
  <tfoot>
    <tr colspan="4">
      <td>
        <a id="previous" href="#">Previous</a>
        <a id="next" href="#">Next</a>
      </td>
    </tr>
  </tfoot>
</table>

As you can see the tbody element is empty, we will load its content after the entire page is loaded. Instead of a bunch of “tr” elements the server should return a nice JSON data which could look like this:

sample.js
1
2
3
4
5
var people = [
 { id : 1, first_name : 'John', last_name : 'Doe', email : 'john.doe@somewhere.com' },
 { id : 2, first_name : 'Jane', last_name : 'Doe', email : 'jane.doe@anywhere.com' },
 { id : 3, first_name : 'Third', last_name : 'Guy', email : 'third.guy@nowhere.com' }
];

To render these data we obviously need a template. Prototype gives us a handy class called Template which is perfect for our needs. To create a template and render the list of people we need a few lines of JavaScript:

sample.js
1
2
3
4
5
6
7
8
9
10
var personRowTemplate = new Template(
  '<tr id="person_#{id}"><td>#{first_name}</td><td>#{last_name}</td><td>#{email}</td></tr>');

var peopleRows = '';

people.each(function(person) {
  peopleRows += personRowTemplate.evaluate(person);
});

$('people').update(peopleRows);

That’s pretty much it. It doesn’t look spectacular, huh? Now just think about the benefits of this approach:

  • You have the data in JSON format, you can use them to render things like an edit form without going back to the server, thus user experience will be better
  • You can be focused on building a nice JSON API for accessing data instead of implementing actions that return small pieces of HTML
  • Your client-side code is cleaner and more consistent

Sounds like a good deal, doesn’t it? :)

jQuery vs Prototype - Part II

Recently, new versions of jQuery and Prototype have been released – it’s a perfect moment for a part number 2. On the official Prototype blog we can read that the general performance of CSS selectors is now improved, unfortunately only for Safari 3, but Element#up/#down/#next/#previous should now be faster on all browsers, it’s a good news as they were really slow. On the other hand we have jQuery official announcement with information that jQuery is now 300% faster – we’ll see!

This time I made a step forward and decided to use a custom JavaScript-based testing environment instead of running tests using Firebug profiler. The obvious advantage is that I was able to run all the tests on 4 different browsers. New test cases aren’t much different then in the first part, let’s say it’s a modification of the previous ones with some extra operations and a little more complex HTML structure.

Test environment setup

Libraries:

  • jQuery 1.2.2
  • Prototype 1.6.0.2

All the tests were run on the following browsers:

  • Firefox 2.0.0.11
  • Konqueror 4.00.00
  • Opera 9.50_beta1
  • Internet Explorer 7 (but using Windows on VirtualBox!)

A tiny piece of JavaScript code is responsible for running the tests, each operation is called only once inside a try-catch block, so the essential part looks like this:

sample.js
1
2
3
4
5
6
7
8
    try {
      var start = new Date;
      test();
      var end = new Date - start;
      this.writeResults(test, end);
    } catch(e) {
      test.resultCell.innerHTML = '<div style="color: red">Exception caught: '+e.message+'</div>';
    }

There is a 3 seconds break between each test run, results are automatically inserted into the results table. If you want, you can check it out on your own, just go right here and hit the ‘run tests!’ button.

The results

I’m happy to see that all tests pass on the latest Konqueror, previous version from KDE3 fails on some Prototype tests. I don’t own Mac, so you won’t see Safari results here, although I’ve run the tests on my friend’s MacBook with very similar hardware as my laptop has (Intel Core Duo 2ghz + 2 gigs of RAM), and it was faster even then Konqueror (no, it doesn’t mean his MacBook is faster then my laptop!!!! ;)).

I’ve run everything 3 times, here are average results in ms:

# Library Test Firefox Konqueror IE7 Opera
1 jQuery
$(‘td.counter’).addClass(‘marked’)
96.6 32.3 70 37
Prototype
$$(‘td.counter’).each(function(el){el.addClassName(‘marked’)})
108.3 49.6 858 75.7
2 jQuery
$(‘td.counter span.special’).removeClass(‘special’)
62 23.6 46.6 25.6
Prototype
$$(‘td.counter span.special’).each(function(el) {el.removeClassName(‘special’)})
28 23.7 167 24.7
3 jQuery
$(‘td.content span.odd’).css(‘color’, ‘red’)
124.7 40.3 63.7 38.3
Prototype
$$(‘td.content span.odd’).each(function(el) { 
el.setStyle(‘color: red’)
})
55.7 31 297 33.7
4 jQuery
$(‘td.content span.even’).before(‘

text

’)
382.7 177.3 373.7 205.3
Prototype
$$(‘td.content span.even’).each(function(el) {
el.insert({before:‘

text

’}) })
359 90.7 527 138.7
5 jQuery
$(‘td.content h3’).show()
178.7 227.7 83.3 1161.7
Prototype
$$(‘td.content h3’).each(Element.show)
38 21 250.7 19
6 jQuery
$(‘div.special’).hide()
90 81.3 33.7 375.3
Prototype
$$(‘div.special’).each(Element.hide)
18 7 73.3 12
7 jQuery
$(‘div.special, td.content .odd’).toggle()
637.7 431.7 517 1360.3
Prototype
$$(‘div.special, td.content .odd’).each(Element.toggle)
71 43.7 106.7 43
8 jQuery
$(‘span.odd’).remove()
132.7 59.3 123.3 66.7
Prototype
$$(‘span.odd’).each(Element.remove)
29 11.7 36.7 19.3
9 jQuery
$(‘#data p.lost:first’).html(‘gotcha!’)
5 1.7 10 3.3
Prototype
$(‘data’).down(‘p.lost’).update(‘gotcha!’)
11.7 2 10 7.3

Conclusion #2

Prototype was at least 2 times faster then jQuery in 15 cases, and jQuery was faster then Prototype in 8 cases. What library should I choose? In my case I will stick with Prototype, because it offers the same functionality as jQuery does + more and it’s faster. jQuery is probably better for projects where there’s a need for some fancy UI effects and that’s it, but it’s just an assumption, correct me if I’m wrong…