Using open source software is like living in prehistoric ages: you’d better always stay with your mates, otherwise soon you will find yourself alone fighting against the harsh nature trying to survive until one day you will be eaten by a huge carnivore.
That’s what happens with those who are too lazy to keep their web application up to date with Rails. You can find many posts describing the process of migration to Rails 4.0. In this article I’d like to tell you about my favourite changes in ActiveRecord 4.0.
I assume that your Rails version is 3.2 or greater, otherwise you most likely were already eaten.
Rails 4.0 comes with a bunch of new features such as Russian Doll-caching and Turbolinks. But probably the most important change for us was improved support of PostgreSQL databases.
Since first version of Rails it assumed that you use MySQL to store your data. Steve Klabnik wrote an article about two default stacks used by Rails projects today. Whereas MySQL is well-supported by Rails and its default ORM ActiveRecord, most of PostgreSQL features (like hstores, arrays etc.) were undeservedly ignored. Until Rails 4 came in.
HStores
As you may noticed, here at adeven we are big fans of crunching numbers with Postgres. And we love to have them returned as hashes, that could be easily mapped on value objects. If you had ever tried using hstores with Rails, I bet you did it with activerecord-postgres-hstore gem that allows you to use ActiveRecord::Coders::Hstore
serializer for handling hstores. Good news, since Rails 4.0 you can get rid of this dependency in your Gemfile. You don’t even need to declare your hstore fields as serializable, Rails is smart enough to detect and properly cast the type of your column.
Moreover, if you have a custom serializer built on top of hstore then you don’t have to manually parse a string with serialized hash anymore. Just assume the parameter for your load
method to be a hash and it should be returned as a result of your customdump
method.
Consider a serializer class for a field containing an hstore. With ActiveRecord::Coders::Hstore
it could look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Since Rails 4.0 it turns into
1 2 3 4 5 6 7 8 9 10 11 |
|
Less work for us, right?
Everything is an ActiveRecord::Relation
Lazy loading of database objects was first introduced in ActiveRecord 3.2. That means that the database will be queried only when you really need the data. Until then you’re dealing with ActiveRecord::Relation
. This approach plays well with a streaming feature deferring data extraction until view rendering phase. It was still possible to eager load the data by calling all
on your scope which implicitly converted your ActiveRecord::Relation
into Array
. Starting from ActiveRecord 4.0 this ambiguity has been removed. From now all
and scoped
are deprecated and you should either explicitly call to_a
on your scope to get an array of results or call load
to eager-load your data.
where.not
That is the change we all were waiting for! Starting from Rails 4 you can make your code more database-agnostic by replacing pure string conditions with chained empty where
and not
methods.
1 2 3 4 5 6 7 |
|
Scopes must be turned into lambdas
Consider a model that has a scope with datetime
1 2 3 |
|
Parameters that will be passed to where
are evaluated at the time when Post
is loaded, which means that on the next day Post.yesterday
will keep the same records as for today. To avoid this since ActiveRecord 4.0 you have to use lambdas to define scope (as well as default scope) conditions:
1 2 3 |
|
Note that Date.yesterday
will be evaluated only when the ActiveRecord will call lambda given as an argument to apply the scope.
Getting rid of “Unknown OID” warning
After I updated our app to Rails 4.0 I got a bunch of warnings saying Unknown OID: ...
. It happens when Rails tries to find out the OID for the column to properly cast the type. This pull-request gave me a hint that from now you should be more strict and explicitly define what column type should be expected when using SQL 'column' AS alias
statement.
1 2 3 4 |
|
Conclusion
Almost all changes in ActiveRecord 4.0 that comes with Rails 4 related to advanced usage of Arel and PostgreSQL. If you don’t have too much logic in your database and if you were doing everything right then upgrading from 3.2 should be pretty smooth and surprise-less.