Named Scopes


One of my favorite features of Rails is named scopes. Maybe it’s because I’ve seen so much Rails code with conditions and finders spread all over the code base, but I feel that named scopes should be used almost always where you would find yourself otherwise writing a find_by or even using the conditions argument directly in consumer code. The basic rule I follow is to always use named scopes outside of models to select a specific subset of a model.

So what is a named scope? It’s really just an easier way of creating a custom finder method on your model, but it gives you some extra benefits I’ll talk about later. So if we have code like:

class Foo < ActiveRecord::Base
  def self.find_all_fluxes
    find(:all, :conditions => {:fluxes => true})    
  end
end

p Foo.find_all_fluxes

we can easily replace that with

class Foo < ActiveRecord::Base
  named_scope :find_all_fluxes, :conditions => {:fluxes => :true}
end

p Foo.find_all_fluxes

You can give named_scope any argument that find can take. So you can create named scopes specifically for ordering, specifically for including an association, etc.

The above example is fixed to always have the same conditions. But named_scope can also take arguments. You do that by instead of fixing the arguments, send in a lambda that will return the arguments to use:

def self.ordered_inbetween(from, to)
  find(:all, :conditions => {:order_date => from..to})
end

Foo.ordered_inbetween(10.days.ago, Date.today)

can become:

named_scope :ordered_inbetween, lambda {|from, to|
  {:conditions => {:order_date => from..to}}
}  

Foo.ordered_inbetween(10.days.ago, Date.today)

It’s important that you use the curly braces form of block for the lambda — if you happen to use do-end instead, you might not get the right result, since the block will bind to named_scope. The block that binds to named_scope is used to add extensions to the collections returned, and thus will not contribute to the arguments given to find. It’s a mistake I’ve done several times, and it’s very easy to make. So make sure to test your named scopes too!

So what is it that makes named scopes so useful? Several things. First, they are composable. Second, they establish an explicit interface to the model functionality. Third, you can use them on associations. There are other benefits too, but these are the main ones. Simply put, they are a cleaner solution than the alternatives.

What do I mean by composable? Well, you can call one on the result of calling another. So say that we have these named scopes:

class Person < ActiveRecord::Base
  named_scope :by_name, :order => "name ASC"
  named_scope :by_age, :order => "age DESC"
  named_scope :top_ten, :limit => 10
  named_scope :from, lambda {|country|
    {:conditions => {:country => country}}
  }
end

Then you can say:

Person.top_ten.by_name
Person.top_ten.from("Germany")
Person.top_ten.by_age.from("Germany")

I dare you to do that in a clean way by using class method finders.

I hope you have already seen what I mean by offering a clean interface. You can hide some of the implementation details inside your model, and your controller and view code will read more cleanly because of it.

The third point I made was about associations. Simply, if you have an association, you can use a named scope on that association, just as if it was the model class itself. So if we have:

class ApartmentBuilding < ActiveRecord::Base
  has_many :tenants, :class_name => "Person"
end

a = ApartmentBuilding.first
a.tenants.from("Sweden").by_age

So named scopes are great, and you should use them. Whenever you sit down to write a finder, see if you can’t express it as a named scope instead.

(Note: some of the things I write about here only concerns Rails 2. Most of the work I do is still in the old world of 2.3.)



Use presence


One of the things you quite often see in Rails code bases is code like this:

do_something if !foo.blank?

or

unless foo.blank?
  do_something
end

Sometimes it’s useful to check for blankness, but in my experience it’s much more useful to check for presence. It reads better and doesn’t deal in negations. When using blank? it’s way too easy to use complicated negations.

For some reasons it seems to have escaped people that Rails already defines the opposite of blank? as present?:

do_something if foo.present?

There is also a very common pattern that you see when working with parameters. The first iteration of it looks like this:

name = params[:name] || "Unknown"

This is actually almost always wrong, since it will accept a blank string as a name. In most cases what you really want is something like this:

name = !params[:name].blank? ? params[:name] : "Unknown"

Using our newly learnt trick, it instead becomes:

name = params[:name].present? ? params[:name] : "Unknown"

Rails 3 introduces a new method to deal with this, and you should back port it to any Rails 2 application. It’s called presence, and the definition looks like this:

def presence
  self if present?
end

With this in place, we can finally say

name = params[:name].presence || "Unknown"

These kind of style things make a huge difference in the small. Once you have idiomatic patterns like these in place in your code base, it’s easier to refactor the larger parts. So any time you reach for blank?, make sure you don’t really mean present? or even presence.



Ruby memory leaks


They aren’t really common, but they do exist. As with any other garbage collected language, you can still be susceptible to memory leaks. In many cases they can also be very insidious. Say that you have a really large Rails application. After some time it grinds to a halt, CPU bound in GC. It may not even be a leak, it could just be something that creates so much garbage that the collector cannot take care of it.

I gotta admit, I’m not sure how to find such a problem. After getting histograms of objects, and trying to profile it, maybe run with ruby-debug, I would be out of options. Maybe some kind of shotgun technique – shutting down parts of the application, trying to pinpoint the location of the problem.

Now, ordinarily, that would have been the end of my search. A failure. Or maybe several weeks of trying to read through the sources.

The alternative? Run the application in JRuby. See if the same memory leak shows up (remember, it might be a bad interaction with MRI’s runtime system that gives you grief. Or maybe even a bug in MRI Garbage Collector). But if it doesn’t go away, you’re in luck. Wait until the CPU starts chugging for real, and then take a heap dump using the jmap Java SDK tool. Once that’s done, you’ll be sitting with a large honking binary file that you can’t do much with. The standard way of reading it is through jhat, but that don’t give much to go on.

But then I found this wonderful tool called SAP Memory Analyzer. Google it and download it. It’s marvelous. Easily the best heap analyzer I’ve run across in a long time. It’s only flaw is that it runs in Eclipse… But well, it can’t be everything, right?

Once you’ve opened up the file in SAP, you can do pretty much everything. It’s quite self explanatory. The way I usually go about things is to use the core option, and then choose “find_leak”. That almost always gives me some good suspects that I can continue investigating. From there on it’s just to drill down and find out exactly what’s going on.

Tell me if you can do that in any way as easy as that with MRI. I would love to know. But right now, JRuby is kicking butt in this regard.



What about Sun’s Ruby strategy?


Wow. Today was a strange day for blog reading. I’ve already had several WTF moments. Or what do you say about 7 reasons I switched back to PHP after two years on Rails, where the first and most important reason seemed to be

IS THERE ANYTHING RAILS/RUBY CAN DO THAT PHP CAN’T DO? … (thinking)… NO.

Bloody hell. All programming languages in use today are Turing complete. Of course you can do exactly the same things in all of them. But I still don’t program in Intercal that often.

Example number two: About JRuby and CPython performance. This blog post uses the Alioth language benchmark to show us that Python’s C implementation is faster than JRuby. Of course, the JRuby version used in this comparison is 1.0, which is now almost 4 months old. Comparing the C implementation of one language with a Java implementation of another language seems kind of suspect anyway.

But these two examples is nothing compared to a post by Krishna Kotecha from yesterday. It’s called Sun’s Ruby strategy – Engage and Contain?. You should ge read it. It’s actually quite amusing. I usually don’t respond to other blog posts, and I don’t usually quote in my blog. I’ll do an except here, because there are several points in that post I want to elaborate on.

Compromise definitely seemed to be an underlying theme at RailsConf Europe. DHH’s keynote downplayed the need for evangelism – something I strongly disagree with. Rails has certainly made a lot of progress towards wider acceptance, but we’ve got a really long way to go before more companies start to adopt it, and I certainly don’t think turning down the evangelism and doing stealth deployments via JRuby is the answer.

There are really two interesting points in this paragraph. First of all the question of evangelism. I would say it’s about time to turn it down. Actually, I’ve gotten the very real impression that the wild-eyed Rails evangelism is now turning people away from Rails rather than winning more “converts”. Telling people about the advantages of Rails is still something that needs to be done, but the full fledged Rails marketing machine has already done it’s work and should be turned down a notch.

The second point Krishna sneaked in there is about JRuby “stealth deployments”. I’m pretty sure no one will ever do a real stealth deployment, and I find that concept totally wrong.

At RailsConf Europe 2007 however, Dave didn’t even specifically discuss Rails – and this seems to have been at the behest of the conference organizers. If this is the case, then the Rails community is already in trouble. Is this the price of Sun’s ’support’: that the community is no longer able to freely discuss the platform and what work needs to be done to get it accepted in the enterprise on its own terms?

Where does this particular conspiracy theory come from? Is there any evidence whatsoever that the organizers of RailsConf wanted Dave to not speak about the shortcomings of Rails? And even if that were the case, what’s there to say that Sun is the reason for this? (Couldn’t it have been IBM or ThoughtWorks, who were also Diamond sponsors?)

I have real problems with this attitude and approach. Selling Rails and Ruby, as “just a Java library” is a massive disservice to the technology, and simply means enterprise customers and decision makers won’t evaluate Ruby on its own merits.

What is important to realize is that the argument “just a Java library” will only ever be used in the case of organizations where there are good technology arguments for using JRuby on Rails, but non-technical management are making decisions based on what is most safe at the moment (see the Blub Paradox by Paul Graham). In most cases the “just a Java library” argument is useful only when talking about conservative environments who are standardized on a certain platform. And believe me, Krishna, there are many places where Java is the only allowed technology to be deployed. But in most cases JRuby will work fine for those IS departments. Is it really a disservice to the technology to make Rails and Ruby into something that can be used in even wider domains, removing cruft and bloatware at all places possible? Is it a disservice for the technology to be used in places where it would never enter without the help of JRuby?

But JRuby is not the best answer for Rails and Ruby developers.

I don’t really understand this quote. Obviously Krishna have strong opinions about the subject, but stating something as a fact without telling the reasons for it being that way doesn’t feel that interesting.

Serious Rails deployments (Mongrel not some Java Application Server) within enterprise environments may be difficult to achieve, but with the right political backing and developer persistence it can be done.

I must say I find it interesting that Mongrel is viewed as a serious deployment option when compared with a standard Java application server. The question here isn’t how we should get enterprise environments to use Mongrel; rather, we should first decide if Mongrel really is a serious enough deployment environment for enterprises.

And this will benefit the whole Rails community – not just those who tie themselves to Sun’s technology platform.

I heard this rumor about Java being Open Source… Does that still mean tying yourself to “Sun’s technology platform”?

And also, the vendor with the most to lose if Rails really does fulfill its potential in enterprise environments.

Why? What exactly does Sun lose if Rails win? Sun is using Rails and benefiting from it. And be careful about this: Rails is Rails, no matter if it runs on JRuby, MRI, YARV, Rubinius, IronRuby, Ruby.NET, XRuby, Cardinal or any other Ruby implementation now or ever. Rails is Rails.

Maybe I’ll start to believe when they start promoting Ruby on Rails at JavaOne, as opposed to promoting JRuby on Rails at RailsConf.

I guess you didn’t attend JavaOne 2007, where both JRuby on Rails and Ruby on Rails had sessions, including promoting in one of the major keynotes. Sun is serious about Java being a multilingual platform. Of course they’re spending money on getting these languages working on Java, but Sun is also giving support to both Rubinius and MRI. Would they really do that if this conspiracy theory is correct? For more information about that particular data point, take a look at Tim Bray’s blog here: Rubinius Sprint.

Much more likely I think, is that we’ll see a Java based Rails alternative that ships with some new version of Java which has been designed to incorporate features from dynamic languages like Ruby and Python.

Java will almost certainly never ship with a web framework. That said, Phobos is one of the Sun projects for web development that uses JavaScript and incorporates features from Rails and Ruby, and also Python and other languages and frameworks.

And still, Sun doesn’t seem to have a problem with Rails and Phobos living side by side. GlassFish includes support for both. And the Rails support doesn’t make any changes to Rails, it doesn’t require you to do anything extra, except that your application should run in JRuby. The latest version basically allows you to say “glassfish_rails start” while standing in your application directory.

…what compromises are we making for Sun’s involvement…

Yeah. What compromises are we making for Sun’s involvement in the community? Except handling the fact that we get more commercial backing, more money in the ecosystem, more help from Sun engineers creating high quality Ruby code, a server that happens to host the SVN server for Ruby itself, and so on? Are these contributions? Sure. Are they commitments? Yeah. Are they something that will require compromises from the community? No, not really.

Sometimes I think that many in the Open Source world still panics as soon as a big company starts to make inroads. And yes, in many cases this hasn’t worked out well. But we gotta see to the facts too. Some companies we will never be able to trust, but Sun has definitely been on the right side of the Open Source fence for a long time. Come on, people.



ActiveHibernate is happening


So, it seems someone stepped up to the challenge and started working on ActiveHibernate from me initial idea. The code got pushed online a while back and I have finally had the time to look at it. Over all it looks really nice.

Of course, it’s very early times. I’ve submitted some patches making the configuration aspect easier and more AcitveRecord like – but it’s going to be important to have access to all the features of Hibernate too. When in the balance, I don’t think we should aim for total ActiveRecord equivalence.

Read more here and find the Google Code project here.

I would encourage everyone interested in a merger between Rails and Hibernate to take a look at this. Now is the time to come with advice on how it should work, what it should do and how it should look like.



The State of JRuby


It’s been sort of quiet on the JRuby front for a few weeks, so I thought I’d give a heads up on what things we’re working on at the moment. At the moment, we’re planning to release 0.9.9 sometime next week. At that point, several things we’re working on right now should be fixed.

  • There is a problem with deterministic threading in JRuby, which results in timeout errors sometimes escaping out of their rescue nodes. This is very serious for long running applications and Charles is hard at work providing better Thread semantics for us. The problem is that it’s very hard to match MRI’s green thread functionality with real native threads.
  • Thomas is hard at work with one of his gigantic refactorings. This time the goal is to remove most of ThreadContext and make many parts of the call chain and block invocation chains easier to work with.
  • Marcin have been working for some weeks now on a port of the hash implementation in MRI, and a corresponding rewrite of RubyHash. At the same time, he’s hard at work rewriting RubyString to allow COW (copy-on-write) semantics. This could potentially improve performance and also make JRuby less memory intense.
  • Earlier this week, we identified and fixed two very serious memory leaks. The second of these caused large leakage in all Rails applications using Cgi::Session for session data (which is almost all JRuby on Rails applications, except those running in Rails-integration). At the moment we don’t see any leaking for Rails applications, so the situation looks good. (Both of these leaks were found with the help of Java monitoring tools, like JConsole, jmap and jhat. Very useful things.)
  • I have been doing some serious YAML fixes these last days, with the result that our YAML situation is better than ever. It even handles recursive objects correctly. (Which is a pain in Java. In C it’s easy, though.)

Overall, we’re working very hard on the last, quirky compatibility issues right now; we have a few different, large Rails applications that we use to identify strange issues. And also, more and more people are trying their applications on JRuby, which means we get better (and more) bug reports. This is really great.

After 0.9.9 has been released, we’re planning on finishing up remaining important bugs. I’m also very keen about getting more databases running really well with Rails. We will try to get Continous Integration set up for these too.



ActiveHibernate – Any takers?


This is a call for action. JRuby on Rails is getting more stable each day, and JRuby performance is consistently improving. This means that JRuby on Rails is well on the path of becoming a viable platform for several kinds of web development.

ActiveRecord-JDBC is central to this, and it’s a good project and works very well. Within the limitations of ActiveRecord, of course. So, I’m thinking (and this is by all means not a new thought), that I would like to have the rest of Rails, but using Hibernate as backend. With JRuby approaching 1.0 fast, ActiveHibernate seems like a neat project. The only problem is time. So why is ActiveHibernate tempting? Well, for all those situations where ActiveRecord really doesn’t fit; composite keys, complicated legacy systems. Or databases where you would like to use prepared statements for everything. Or get really nice speed.

What needs to be done? For it to be really useful, there are few points: First, a Hibernate extension that serializes and deserializes into RubyObjects. By doing it that way, there is no need to create Java bean classes. Secondly, provide all the useful help functionality around the Hibernate implementation, that AR users have gotten used to. This includes things like validations, automatic handling of updates and inserts, and is generally about doing a good Ruby interface around Hibernate. This also includes creating a good way of configuring Hibernate without having to resort to the XML. Maybe using YAML? Or a Ruby DSL? After that has been done, the final point is easy: get mind share and start doing applications with it! I for one know that I would like to use such a project!



Post Rails meetup


Last evening was very nice. We usually have a good time at the Rails meetups, hosted by Valtech. Yesterday it started out with Dr Nic William, who spoke about some metaprogramming techniques. Very neat, and the best part was his Magic Wiggly Lines. I’m not sure if it’s genius or mental. But it’s cool, at least; it’s basically a const_missing hook, which makes it possible to use class names even if you spell them wrong. Hehe.

After that I spoke about new JRuby thing. I have a cold, so I took it pretty easy, and it was very free form with questions. There was many interesting questions, actually, and I think Nic taped it all…

After that, we drank beer and talked technology, which is always fun!



Rails meet in Stockholm


And it’s time again for a Rails meetup in Stockholm, at Valtech. This Tuesday (20th) 6pm at Valtechs offices. It is usually very interesting and neat to meet other people involved in Rails and Ruby here in Stockholm, and it’s usually very nice, all around.

I will have a short presentation on the new features in JRuby 0.9.8. I will provide a fast intro to JRuby, but this is not the introductionary presentation; I will also try a somewhat different presentation technique, so it is sure to be interesting. At least for me… =)

Show up! It’s worth it. You need to reserve a place, though, which can be done at http://www.rails.se/rails/show/Railstr%C3%A4ff+20+Mars+2007



Current JRuby status – AKA The what’s-cool-and-happening


This is just a small update on what’s going on in JRuby development at the moment. The first and most important item is that Tom has merged his block-work to trunk. He has done a monumental achievement with a patch on over 17k lines. The most amazing thing is that my main test case for block problems (Camping) runs perfectly. Tom also reports some performance improvements, but that isn’t the important thing. What this block patch is all about is to remove the block stacks from our ThreadContext, and instead just pass the current block along through the Java stack (in other words, as a parameter to the method call in question). This simplifies many things and also make it possible for our compiler to finally compile closures and blocks. Charles will soon continue the work on making this happening, but being able to do that means the JIT will work for vastly more of the code than it does at the moment.

The second work we’re hard at right now is Rails compatibility. Tom is looking at ActiveRecord, Charles have improved Marshalling (with the side effect that the gem local source cache finally works) and also did some work on Multibyte::Chars. This work is going fast forward. My part in this is ActionPack, where we right now are down to 9 failures and 0 errors, from 23 failures and 8 errors. Those numbers are for 1150 tests and 5202 assertions, so there isn’t much left to get this working.

My work on the YARV compiler continues, and I will soon post an update about this too.