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.