Upgrading to Snow Leopard

Last Friday, Apple released their new OS version: Snow Leopard. Upgrading to SL is very easy and even gives you back quite a lot of HD space. However a few things have changed in the OS and you need to understand what is going on so you won’t get frustrated with the updating process and won’t be wasting time fighting with the system.

Snow Leopard

The key change for us Ruby developers, is the fact that, in Snow Leopard, all the interpreted languages (including Ruby) are now running in 64-bit by default (obviously, only if you have a 64-bit machine). For pure Ruby applications and libraries this shouldn’t pose any problems. But if you are migrating from a Leopard environment where you compiled C extensions for 32-bit only, these gems won’t properly load in Snow Leopard. Same thing goes for libraries you might have compiled in 32-bit mode and that you might want to use on your migrated system.

Something else you need to know: Snow Leopard now comes bundled with Ruby 1.8.7 instead of 1.8.6. This should not be a problem since Rails has been running on Ruby 1.8.7 for a long time and Rails 3 will require Ruby 1.8.7 and prefer Ruby 1.9.2.

Here is a quick rundown of common tasks you might have to do to migrate properly.

Install Snow Leopard developer tools

On the Snow Leopard DVD, under “Optional Installs”, install “Xcode.mpkg”. Use all default options.

Passenger

$ sudo gem install -r passenger
$ sudo passenger-install-apache2-module Press Enter when prompted. Passenger will compile and install its Apache module. Press Enter when prompted the second time too.

$ cd /etc/apache2

Open httpd.conf in your text editor (if you use TextMate, try running mate httpd.conf from the command line) and look for a line like “LoadModule passenger_module” and some lines following that have “passenger” in them too. Delete them. If you don’t see them them, move your cursor to the end of the file.

Then insert these lines:

LoadModule passenger_module /Library/Ruby/Gems/1.8/gems/passenger-2.2.4/ext/apache2/mod_passenger.so
PassengerRoot /Library/Ruby/Gems/1.8/gems/passenger-2.2.4
PassengerRuby /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby

MySQL

To avoid weird issues with MySQL, it’s strongly recommended to upgrade to the 64-bit version. Start by shutting down mysqld if it’s running. (Depending on how you installed MySQL, you might be able to use the preference panel, or use sudo /opt/local/share/mysql5/mysql/mysql.server stop if you installed it using MacPorts)

Now install the Mac OS X 10.5 (x86_64) version of mysql from here

When the disk image opens, first install “mysql-5.1.37-osx10.5-x86_64.pkg”. Use all default options.

Next install “MySQLStartupItem.pkg”. Use all default options.

Next install “MySQL.prefPane”. Double-click to install it. Choose to replace the existing preference pane when prompted. (Apparently the preference pane is still 32-bit.) At this point you can click “Start MySQL Server” to start the server and verify it works.

Unmount the MySQL disk image.

Since you are upgrading from Leopard, your mysql gem is compiled for 32-bit only and therefore needs to be recompiled. However, it’s not that simple, the mysql gem is a bit of an exception. Under Snow Leopard when you do a gem install for a C extension it tries to build the extension for two architectures: i386 (32-bit) as well as x86_64 (64-bit). The problem is that the binary from mysql.com is not universal and therefore we need to force the C extension to be only compiled in 64-bit.

$ sudo env ARCHFLAGS="-arch x86_64" gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config

note: You shouldn’t have to set the ARCHFLAGS to compile any other gems.

MacPorts

You should be all set. However, if you are relying on any libraries you compiled on Leopard, you probably will have to recompile them. MacPorts users shouldn’t think that it will be automatically done for them.

You have different options to upgrade your ports.

The easiest way is to upgrade MacPorts:

$ sudo port selfupdate
$ sudo port sync
$ sudo port upgrade --force installed

Other native gems

Check this script to get a precise list of gems requiring to be reinstalled and some help with the upgrade process. Basically, you just need to reinstall the few gems using C extensions.

What's New in Edge Rails: No REST for the weary

This week’s post will be rather short and sweet. The notable commits of the week seemed to revolve mainly around refactoring and even slightly altering the way some of the bits work. Lets get into it:

I’m Partially impressed

Yehuda Katz was able to simplify some of the partial rendering logic this week, although in doing so seems to very slightly alter the call methodology. So now, when calling the local object from within a partial, you will have the choice of using either the partial name (i.e. “_post.html.erb” would be “post”) as the reference for the local object, or you may make it unique by passing in the :as option (i.e. render :partial => "post", :as => "poster_boy" would be “poster_boy”). You no longer have the option of using both interchangeably from within your partial. Also, the :object option for render :partial has been removed, in favor of the methods previously mentioned.

We won’t Accept it

The way in which Rails handles incoming Accept headers has been updated. This was primarily due to the fact that web browsers do not always seem to know what they want … let alone are able to consistently articulate it. So, Accept headers are now only used for XHR requests or single item headers - meaning they’re not requesting everything. If that fails, we fall back to using the params[:format].

It’s also worth noting that requests to an action in which you’ve only declared an XML template will no longer be automatically rendered for an HTML request (browser request). This had previously worked, not necessarily by design, but because most browsers send a catch-all Accept header (“*/*”). So, if you want to serve XML directly to a browser, be sure to provide the :xml format or explicitly specify the XML template (render “template.xml”).

I’ll tell you where you can go…

Josh Peek finally removed the deprecated “best fit” route generation support. Mostly for the sake of speed and maintainability, the new router will simply use the first matching route in your routes.rb file, rather than the “best” match. If you’ve been working at all on the Edge and haven’t noticed the deprecation warnings, then this probably won’t affect you.

Oh, so that’s why!

Jay Pignata provided a patch this week to help out all of you RESTful API developers. Previously, when a client sent invalid XML or JSON to your server, Rails would 500 with an oh-so-descriptive /!\ FAILSAFE /!\ error in your logs. This wasn’t much help if you were trying to debug it. So, with this patch, you’ll now get to look at the raw data that was posted to your server in your logs.

Speaking of Resources

Finally, a few updates went into ActiveResource this week which will make it a lot more familiar to those of us who are more comfortable with ActiveRecord. Validation support has been added, which will allow you to both validate your resources locally - before transmission - and remotely. ActiveResource no longer throws a ResourceNotFound error when you attempt to find a set of undefined resources [Resource.find(:all)]. Instead, ActiveResource is reverting to the more ActiveRecord-like empty set/nil response. And last, but not least, resource.save! will now raise a ResourceInvalid unless the resource is, actually .. well .. valid?

That’s it for this week’s update on Edge Rails. I hope that you’ve enjoyed it.

Photo: Hood River Sunset by Bernt Rostad

What's New in Edge Rails: The BugMash Edition

Another week, another update on Edge Rails. And man, you aren’t making this easy on me, are ya? This weekend, in case you hadn’t already heard, was the first Rails and RailsBridge BugMash. If my count is correct, there were roughly 300 commits to the Rails master over the past six days, with most of them pushing in over the weekend. Talk about a trial by fire! There’s a lot of really good stuff in here, so let’s get started:

All I ever wanted was a little Validation

ActiveRecord (or probably more accurately, ActiveModel) received a lot of validation love this weekend.

  • Thanks to James Hill you can now have your validations read from a custom method. This will allow you to more easily validate non-column - instance variable - data, for example.
  • Adam Keys added support for exclusive ranges in validates_length_of. So, validates_length_of :name, :within => (5...10) will actually restrict the valid length to between 5 and 9.
  • Thanks to Zac Williams, validates_length_of :name, :maximum => 10 will now allow nil values to validate, by default.
  • What good is validates_format_of if you can’t validates_format_of :without => /.../? Well, not much, let me tell you… Elliot Winkler provided a patch do to just that.
  • And last, but certainly not least Jeff Dean committed a great patch, which now brings to us: validates_with. This little beauty now allows you place validation code into an external class. And that, my friends, means better encapsulation of responsibility, I’ll bet on better readability, and even shared validation logic across your application or possibly even gems. Nice job, Jeff.

We’re so much more Resourceful

There were quite a number of updates to ActiveResource over the weekend. And, I’m sure many of you are going to be quite thankful for some of these:

  • ActiveResource now supports HTTP proxies thanks to Marshall Huss. This should be highly useful in large corporate and other firewalled or isolated environments.
  • ActiveResource gets SSL options from Roy Nicholson. This allows you to use X509 certificates, SSL timeouts, peer verification, and more.
  • ActiveResource.exists? got some polish from Jatinder Singh. And, by polish, I really mean that now it works. Instead of raising Net::HTTP errors.
  • Fabien Jakimowicz added JSON error reporting support. So, now regardless of whether you’re using either XML or JSON, errors will be correctly reported back to you.

There’s strength in numbers

Thanks to Dan Cheail, we finally get a grouped_collection_select helper. I mean come on, there’s no way you can tell me that you can’t love this:

class Continent < ActiveRecord::Base
class Country < ActiveRecord::Base
class City < ActiveRecord::Base

<%= grouped_collection_select(:city, :country_id, @continents, :countries, :name, :id, :name) %>

<select name="city[country_id]">
  <optgroup label="Africa">
    <option value="1">South Africa</option>
<option value="3">Somalia</option>
  </optgroup>
<optgroup label="Europe">
<option value="7" selected="selected">Denmark</option>
    <option value="2">Ireland</option>
</optgroup>
</select>

I have massive Routes

This weekend brought a small, but incredibly useful patch to rake routes by Mike Breen. Now you can filter the listed results by passing in CONTROLLER=foo. That’s. just. awesome. Personally, it’s gotten to the point that my fingers just assume that they are to append the “| grep foo” portion whenever I type rake routes.. apparently I have nerd muscle memory. *sigh*

Short and sweet

I’ll end the BugMash portion here with just a few more commits worth mentioning. Certainly this wasn’t the extent of the BugMash and I could probably fill up another post just as long with even more mashed bugs and features, but it’s gotta end somewhere, right?

  • Rizwan Reza added support for you to define custom RedCloth options via the textilize helper. So, now, textilize("Testing <b>HTML</b>", :filter_html) will actually filter the HTML!
  • You can now redirect_to(User) - note that User is a class not an instance here - as a synonym for redirect_to(users_url). Thanks to Niklas Holmgren for that.
  • Delivered mail items now have the ability to save to disk because of Eric Davis. When using the new :file delivery method, you can even define your own custom :location for directory storage.
  • And finally, it’s not necessarily BugMash-related, but José Valim - among dozens of other commits - added model.destroyed?. This nifty method will return true only if the instance you’re currently looking at has been successfully destroyed.

Now that we’re clear of those, here are a couple of non-BugMash-related topics which were addressed:

A visit to the Oracle

There’s a difference between knowing the path and walking the path. And this week saw some updates to Rails, mostly around testing, adding improved Oracle database support. A large amount of this effort appears to be coming from one man, Raimonds Simanovskis. I know when we talk about databases with Rails, it’s always the big four - SQLite, MySQL, PostgreSQL, and that other one which shall not be named - so it’s nice to get a little more focus the 800lb. gorilla in the room.

This update fixed failing test cases due to offset and limits, empty strings storing as null, numeric results from ActiveRecord.sum, Oracle not utilizing an ‘AS’ keyword on joins, and many more.

AbstractController::Responder

José Valim and Yehuda Katz (and many others, I’m sure) have put in some excellent work in refactoring the Rails renderer. In fact, the majority of the rendering code has come to find a home in a common object, the AbstractController::Responder. Certainly, this may not be its final resting place, but it’s interesting to note that once a lot of the render logic was brought together the core team was able to quickly identify and refactor the logic to see some dramatic speed increases. At one point, Yehuda even mentioned a tested benchmark showing, “10% faster partial rendering,” than Rails 2.3.

I know that in the RailsEnvy podcast I jabbed a few ribs about the amount of time it’s taken to see a Rails 3.0 release, but it’s important to note that these guys are doing some seriously awesome work. I’m seeing extensive testing and benchmarking and very intelligent refactorings. We’ve really got some great things yet to come.

I’m sure I’ve left out several important and/or interesting commits this week. So, I apologize if one of those was yours. I, and the rest of the community, certainly appreciate the effort you all put in this weekend and Rails is certainly better for it. So, thank you, thank you, thank you to all of you BugMashers out there. And, if you missed out on getting your commit in this round, we’re certainly ready to welcome you into the next.

If you prefer to have a shorter audio summary of this content, you should check out a new podcast just launched by Envy Labs, called Ruby5; a 5 minute, twice-weekly podcast covering Ruby and Ruby on Rails news.

Photo: Brooklyn Bridge Virtual Tour by Diego_3336

Community Highlights: IronRuby

As Rubyists migrate from Ruby 1.8 to Ruby 1.9, new Ruby implementations are gaining in maturity. Recently, IBM's Antonio Cangiano wrote an interesting article comparing the performance between Ruby 1.8, 1.9 and IronRuby on Windows which surprised quite a lot of people.

Unfortunately, IronRuby isn't very well known in the Rails community yet.

Here is an interview with Jimmy Schementi, lead developer for IronRuby, to help give you a little insight.

iron ruby logo

Matt: Hi Jimmy, thank you very much for taking the time to answer our questions. Could you please introduce yourself?
Jimmy: Thanks for sending me questions; it's great to see the ever-increasing interest in IronRuby! I live in Seattle and work at Microsoft on a small team making an open-source implementation of Ruby called "IronRuby". I personally split my efforts between making the IronRuby codebase better, integrating IronRuby with .NET-related technologies like Silverlight or ASP.NET MVC, getting our monthly binary releases are in order, discussing IronRuby with the community, and making sure Microsoft's management knows how awesome Ruby is. But I'm definitely not alone on the core team. John Lam fueled the interest of a .NET-Ruby implementation with the RubyCLR project, and started the IronRuby project. Tomas Matousek is the brains behind the IronRuby compiler, and gets credit for all the compiler code and the recent performance gains. Jim Deville is the man keeping IronRuby working with tons of tests and a fantastic test infrastructure. Shri Borde is our manager, and he spends his non-managing time fixing the libraries and hosting the infamous "IronRuby pair-programming" sessions. And of course all the IronRuby contributors over the past two years have been an enormous help.
Matt: As a follow up on a recent blog post, could you tell us know how you learned Ruby and maybe give some advice or an important point not to miss for people wanting to learn Ruby?
Jimmy: I heard about Ruby from my Computer Science professor/advisor Gary Pollice, who taught all the programming language classes at Worcester Polytechnic Institute. I was searching for an expressive programming language for making games, and Ruby was a perfect fit. A couple years later I worked for the same university building a computer-tutoring system called Assistment, where myself and a couple of other people fed up with the Java codebase ported it to Ruby on Rails. It was a success, and http://assistment.org is now a Rails system. That's where I really learned everything about Ruby and became extremely interested in how Ruby worked. I learned the most from Ruby when I had a substantial Ruby project to work on, since I got to see its expressiveness making me more productive on a large scale. I'd still suggest trying to learn Ruby on small things here and there, but you'll really be amazed if you use it for something larger.
Matt: IronRuby certainly looks very interesting, can you run Rails on it?
Jimmy: Yes, at RailsConf 2009 I showed IronRuby running non-trivial Rails applications. IronRuby can run Rails on WEBrick, as well as on the web-server that comes with Windows, IIS. For the database you can use SQLServer Express (which is free), or any .NET based database, like the recent csharp-sqlite port. Here's a detailed post the IronRuby on Rails talk at RailsConf 2009: http://blog.jimmy.schementi.com/2009/05/ironruby-at-railsconf-2009.html.
Matt: Are there any limitations that our readers should be aware of before starting to develop on IronRuby?
Jimmy: The main limitation is that IronRuby does not support any of the C-based Ruby libraries, and only after 1.0 will we consider building an interop layer between the Ruby C API and IronRuby. In the meantime, people have been porting their favorite C-based Ruby libraries over to C# so it can be used from IronRuby, like Hpricot. While this seems like a large limitation, most of the C-based libraries Ruby code depends on have an equivalent API in the .NET framework, which IronRuby has direct integration with, making either using directly or porting really easy. For example, the Rails app I showed at RailsConf did image resizing directly with the System.Windows.Drawing APIs rather than ImageMagick. If your code does not depend on anything outside of the Ruby standard library that is C-based, you should have no problems. Take a look at the documentation for running Rails on IronRuby to make sure things go smoothly: http://ironruby.net/Documentation/Rails.
Matt: What are the pros/cons of using IronRuby versus the standard Ruby (Ruby1.8 or Ruby1.9) on Windows?
Jimmy: IronRuby is a very fast Ruby interpreter/compiler due to our own tricks we pull to make Ruby fast, the tricks the DLR does to make dynamic languages fast, and the CLR's just-in-time compiler which generates very efficient code. We're definitely aiming to be the fastest Ruby implementation on Windows. The most recent performance work we did was only in the core libraries ("Array", "Hash", etc), and that helped IronRuby surpass Ruby 1.8.6 on Windows and gets much closer to Ruby 1.9.1. IronRuby is continuing to investigate ways of gaining performance in each release. IronRuby is also a very 1.8.6 compliant Ruby implementation. There is a "-19" flag for any 1.9 specific features you might need, and a "-20" flag for any Ruby 2.0 features we might have in there, but there are no guarantees on those; we only test the 1.8.6 behavior today. We pass ~85% of the RubySpec test suite, the best test suite for Ruby implementations to verify their correctness. However, the numbers I'm more concerned with are whether specific Ruby libraries' test-suites work. We pass Rails, RubyGems, Rake, and RSpec's test suites at well over 90%, and fix compatibility issues when asked about them, so please let us know if your applications run into any compatibility problems. Other than the limitations that I mentioned in the previous question, you should have no problems. I love people to try running their Rails applications on the latest IronRuby bits hosted on GitHub, and please report any issues you find on http://ironruby.codeplex.com.
Matt: Are they any extra advantages to use IronRuby?
Jimmy: The most notable advantage is that IronRuby works in Silverlight, a subset of the .NET framework which installs as a browser plugin in Mozilla-based browsers (eg. Firefox on Mac and Windows), Webkit-based browsers (eg. Safari on Windows), and IE (on Windows, duh). The Mono project is implementing an open-source version of Silverlight called "Moonlight" so Linux developers can run Silverlight applications, which I talked about at OSCON 2009. This enables you to write Ruby in the browser instead of JavaScript, for controlling HTML or vector graphics. The best place for documentation/examples today is on the Gestalt website, a little portal designed to bring awareness to Ruby and Python in Silverlight: http://visitmix.com/labs/gestalt. The IronRuby website is in flux at the moment, but clearer documentation is on its way. I also built a little Ruby on Rails plugin called "Silverline" to make it really easy to use Silverlight from Rails. Worth checking out if you want to use Ruby as a client scripting language. IronRuby has direct integration with the .NET framework, so anything that is in, or run on, the .NET framework can be used directly from IronRuby. .NET namespaces are exposed as Ruby modules, .NET classes as Ruby classes, and you can call methods on them just like you call Ruby methods. This makes it really easy to build pieces of your system in a static language (if it makes sense to use, like for a high-performance message queue, game engine, etc) and then interact with it through Ruby.
Matt: Why is Microsoft interested in a Ruby project? What advantage do they find in sponsoring such a project?
Jimmy: I see it as a "you scratch my back, I'll scratch yours" situation. Microsoft sponsoring IronRuby helps the Ruby community by making Ruby a first-class language on Windows and .NET, also giving the .NET crowd the choice of using Ruby, and in return the IronRuby project helps promote innovation in the languages that drive Visual Studio purchases (C#, VB.NET, and F#). As a kind-of related side-note: some people feel it's a bad thing that there are so many implementations of Ruby, kind of like MRI is so bad that others had to fix it, but I completely disagree. IronRuby, JRuby, MacRuby, and most of the other implementations accomplish the same thing for their respective communities; building a bridge between Ruby developers and themselves. Rather than needing to recreate MRI, most have been inspired by it and wanted to bring the language to their platform. It's a great thing for the Ruby community because it gives access to more platforms, operating systems, and libraries than any other language. Anyway, back to the question: as an example of how IronRuby has helped language innovation, the next version of C# will now have a "dynamic" keyword, indicating that the variable statically-typed as "dynamic" (=P) should perform dynamic dispatch on any method calls, rather than verify the method call at compile-time. This infrastructure uses the Dynamic Language Runtime directly, so C# can use Ruby objects just like they were defined in C#, or any other dynamic-enabled object.
Matt: How will IronRuby make Rails developer lives easier and what are the plans for the future of IronRuby?
Jimmy: My hope is that IronRuby can benefit existing Rails developers by making Windows a great option to develop and deploy on. By building a Rack adapter specifically for IronRuby and IIS (like I showed at RailsConf), Rails applications can tie directly into the same web-server pipeline that ASP.NET does, significantly reducing the overhead deploying via IIS+FCGI gives you today. This makes deploying Rails applications on IIS just like deploying ASP.NET apps, so system administrators don't have to learn a whole new framework; to them it's just ASP.NET. Then any existing ASP.NET shops who want to offer Rails applications to their customers can, with the same infrastructure and deployment know-how. This is bringing choice to the technologies you choose to deploy on Windows, just like how Microsoft has helped make PHP run well on IIS. The only definite future plans for IronRuby is continue pushing on performance on compatibility, as well as continue supporting the latest version of Silverlight and Mono. 1.0 will be released when the community is happy with the state of those metrics, and future work should be driven by what IronRuby users want. If you start using IronRuby and want a feature either by 1.0 or post 1.0, please post the request to the mailing list or to CodePlex. We have tons of hopes and dreams for what IronRuby can do in the future, so please come help out!
Matt: Is there anything you would like to add or share with the readers?
Jimmy: Thanks to Matt for the interview, and thanks to the readers for getting this far! Go grab the 0.9 release from http://ironruby.net/download, or the latest source from http://github.com/ironruby/ironruby, tell us if you have any problems with it, and we hope you'll help IronRuby get to a 1.0 release.

What's New in Edge Rails: The Hodgepodgery

It’s been quite a while since we’ve had a new Edge Rails post. I’ve really missed them and there have been a lot of changes, both big and small, on the Edge in the time since. In this post I’ll cover a little bit of everything that’s been happening over the past week or so in Rails. Along with this, you should expect to see more frequent and regular updates on all that is currently going on.

Goodbye SQLite dbfile

This is a relatively minor change, unless you still refer to your SQLite database as a dbfile in your database.yml. The dbfile option key is now gone, having been replaced a long time ago by the more standard, database key. So, if you’re suddenly seeing, “No database file specified” errors after you update, this may be your cause.

Кирилица\n祝您好運 ??? We got your Кирилица\n祝您好運 RIGHT HERE

Sava Chankov provided a patch fixing Content-length HTTP response headers being incorrectly calculated with Ruby 1.9 and multi-byte characters. The content length is now calculated based off of the String#bytesize rather than just the String#size. This takes advantage of the multi-byte character support built in to Ruby 1.9, just as long as you remember to always properly tag your multi-byte file with the correct encoding header (i.e. # encoding: utf-8).

That’s not our job

Some spring cleaning, mostly made possible through Rack support, allowed Edge to hand-off some additional responsibilities to the stack. The most interesting of which is now off-loading some of the content-length calculation to your web server rather than being processed directly from within Rails. The largest benefit of this is not so much for the application developers as for you middleware developers. This means that you no longer have to re-calculate the content length when manipulating the body of an HTTP response.

This does not appear to affect the previously mentioned update by Sava, because his fix seems to most largely affect streaming file responses directly through Rails.

We <3 the Hash, and now so does the Cache

Cache control is now being handled by an internal Hash rather than independent string values. Old and busted: headers['Cache-Control'] = 'private', new hotness: response.cache_control[:public] = true. Additional cache_control options include: :public, :max_age, :must_revalidate, and the oh-so-descriptive :extras, which is used mostly for your custom header content.

What time is it!?

Geoff Buesing provided a useful fix for Time, specifically when used in conjunction with ActiveRecord. Now you can save and search ActiveRecord objects using whichever local time zone you like, regardless of what your default time zone is configured for and everything now will just work. You no longer need to be concerned about converting your user’s local time into your default application time or vice versa.

It’s STATE of the art

ActiveRecord now has easy access to ActiveModel’s StateMachine implementation. I don’t know about you, but somehow I always seem to find a way to bring state machines into my Rails applications, and now building in - even fairly complex - state machines just got a whole lot easier.

For an example of ActiveModel::StateMachine and to get an idea of how you might use it, check out my more detailed blog post over at Envy Labs.

Front. Back. Side to side.

Paul Gillard committed a patch which now allows for both custom suffixes (which really isn’t new) and prefixes (omg THAT IS!) on your ActiveRecord attributes. This gives you access to attribute_method_prefix, attribute_method_suffix, and now attribute_method_affix. While it may sound a little silly, check this out:


class Person < ActiveRecord::Base
  attribute_method_affix :prefix => 'me_mateys_', :suffix => '_is_in_pirate?'
  
  private
  
  def me_mateys_attribute_is_in_pirate?(attr)
    send(attr).to_s =~ /\bYAR\b/i
  end
end

person = Person.find(1)
person.name                               #=> 'Paul Gillard'
person.profession                         #=> 'A Pirate, yar!'
person.me_mateys_name_is_in_pirate?       #=> false
person.me_mateys_profession_is_in_pirate? #=> true

Okay, well, that’s still a little silly, but hopefully you get the idea and can think of a few usage scenarios of your own. So, basically, now you can add your own dynamic ActiveRecord methods that can potentially affect any or all of it’s attributes.

Clean yourself up

Paul Gillard posted another useful patch, utilizing that one previously mentioned, to now provide us all with this syntactic sugar: reset_attribute! And he even provided us with a pirate of his own to show off this new bounty:


pirate = Pirate.create!(:catchphrase => 'Yar!')
pirate.catchphrase = 'Ahoy!'
pirate.reset_catchphrase!
assert_equal "Yar!", pirate.catchphrase
assert_equal Hash.new, pirate.changes
assert !pirate.catchphrase_changed?

Nobody likes a dirty pirate.

How do I learn Ruby & Rails?

This is a question I get quite a lot.

Where should I start? What should I do? What can I do to become a better Ruby/Rails developer etc.. (more common questions)

I wish there was a “simple/right” answer to these questions. Something like: “Read this book and you will become an awesome developer”. Unfortunately, things are not that simple. We are all different and we learn differently, we also come from different backgrounds.

So instead of telling you what I think is the best way to learn, I decided to ask the community. Here is a quick compilation of some of the responses I received:

What the community says:

How did you learn Ruby and/or Rails?

  • DHH DHH: I learned Ruby by programming in anger. Attempting to make something real. Not just a toy program.
  • David Black David Black: I learned ruby via pickaxe and lots of practice and both reading and answering questions on ruby-talk.
  • Evan Phoenix Evan Phoenix: reading code WHILE writing code
  • Yehuda Katz Yehuda Katz: I tried impossibly hard things to force myself to learn.
  • Laurent Sansonetti Laurent Sansonetti: I learned ruby via pickaxe, reading the posts on ruby-talk and then reading MRI’s source code
  • Ninh Bui Ninh Bui: I was quite a java fanboy back, writing struts + j2ee enterprise apps, Hongli forced me to look at Ruby over a weekend and I learned the Ruby basics. I then learned Rails by googling, reading books and source code.
  • Tim Connor Tim Connor: the rails community habit of obsessively blogging was probably the biggest help
  • Lar Van Der Jagt Lar Van Der Jagt: Ryan Bates’ railscasts for sure. The Rails Way once I knew enough to dig deeper. What I wish I’d done tho is work with experts!
  • Arun Gupta Arun Gupta: The Rails guides and Agile Development with Rails book.
  • Geoffrey Grosenbach Geoffrey Grosenbach: After I had read a few tutorials, I started by spending a few hours reading through the API docs. Even if you don’t understand everything, it’s a fantastic way to become familiar with what’s available.
  • Nate Todd Nate Todd: I learned MVC with a few CakePHP apps first. It helped me learn best practices in a language I was familiar with.
  • Chris Wanstrath Chris Wanstrath: I learned Ruby on Rails by writing apps and reading the framework’s source.

What advice would you give?

  • Bob Martens: Get involved in the community in some way. They know more than you. ;)
  • Ismael Celis: understanding the relationship between the parts of MVC. Loads of people coming to Rails don’t know what a design pattern is.
  • @jeromegn: I find the best trick to learn RoR is to simply try building something. Rails docs and learning Ruby in parallel helped me the most
  • @johnbender: knowing why instance vars are available in templates, etc. Essentially knowing the basics of ruby would be my initial advice
  • @ryandotsmith: writers read. Find popular projects on github (i.e. radiant ) and study their specs.
  • Sunil Karkera: understanding MVC in Rails was the most important thing for me when I started.
  • Luke Burton: basic screencasts showing something impressive being achieved in small amounts of code were a great start
  • DHH: Pick a real project and program in anger. That’s how I’d recommend learning any language including Rails and Ruby.
  • Anthony Green: Accept that there’s a Rails Way and you need to learn it. What helped me most ? - the community.
  • Kent Fenwick: Learn by doing a REAL project. Pick something you want to build and slowly chip away at it.
  • Trevor Turk: learn by reading and writing code… meaning you should try to build something you want instead of dumbly following tutorials…
  • Ryan Bates: Rails is made up of many technologies (HTML, CSS, Ruby, OOP, SQL, etc.). If you’re struggling with Rails, focus on weakest part.
  • Geoffrey Grosenbach: And there are many examples throughout that will help a new developer get a feel for the philosophy of Rails. Many people have learned from the Rails from Scratch series at PeepCode
  • @eifon: A good grasp of MVC is invaluable as is knowing some Ruby before you start.
  • John Yerhot: don’t be afraid to ask questions and use support channels - irc, mail list, rails bridge, etc…
  • Roy Wright: use the same version of rails as is in the book you are using.
  • @brianthecoder: read other people’s code
  • Ninh Bui: I learned by having discussions with a lot of people, I can definitely recommend that
  • Chris Wanstrath: Stop asking other people for advice and start coding something.

Different opinions but very interesting answers. I tried to compile some of what I thought were great resources that helped me and/or other people I talked to.

Never heard of Rails or Ruby, what is it?

newbie

Start by watching one of the many screencasts/presentations about Rails. Rails and software developed using Rails are written in a programming language called Ruby. If you are new to software developer, you can quickly learn Ruby and I would recommend a great book called Learn to program by Chris Pine. Ruby is a very elegant and intuitive language that you will be able to pick up quickly while learning new tricks for many years. However, don’t expect that after installing Rails, you will have a Drupal clone in Ruby. Rails is a web framework, in other words, a tool to help you write your own web application quickly and efficiently.

Tip: The Ruby website has a lot of information and resource to get started.

I hacked some PHP/Perl/ scripts but I don’t know anything about MVC or Object Oriented development:

Here it really depends on how you learn things. Are you a “How” or a “Why” person? A “How” person will learn by being shown how to do something and will then reproduce it and learn from it. A “Why” person needs to understand why things are done a certain way so they can re apply their knowledge on other challenges.

building

The good news is that Rails uses many conventions and if you pick them up, you will quickly get things done and feel rewarded by what you have done. That’s great for “How” people, but “Why” people might have to be a bit more patient and start playing with the framework before that can fully understand everything.

“How” people should definitely watch Ryan Bates’ excellent railscasts and read the Rails guides “Why” people might want to read Ruby Programming Language and The Well-Grounded Rubyist, aka Ruby for Rails 2nd edition

You should also check the Rails wiki and contribute info that might be potentially missing. (If you have a problem that is not covered/discussed in the wiki, try to solve it and then post your solution. If you come across the same problem at a later time, you will be able to quickly find how you solved it. By contributing, you will also save other developers’ time.)

Start reading Ruby/Rails related blogs, subscribe to rubyinside RSS feed and visit your local Ruby group.

Tip: Start a blog and keep track of what you learned. That will help you and other people facing the same challenges

I started writing a Rails app but I feel limited by my knowledge of the framework and the language

That’s a normal stage, don’t give up! Here are a couple of great reads: The Ruby Way and The Rails Way. the Ruby Way should satisfy primarily the “why” people, while the Rails way should primarily please the “how” people. I’d recommend to read both. Don’t hesitate to ask questions, check google, use twitter, blog comments, mailing lists. Try to find some local rubyists to share knowledge with. Pick a topic you would like to know better and prepare a talk for your friends/local Ruby group or write a blog post about it. One thing for sure, don’t be ashamed or discouraged. Persevere, it’s worth it (or get out, relax for a while, and then come back and give it another go).

hacking

A good way to improve your Ruby/Rails skills is to look at other people’s code. Check GitHub and see how people have solved the same problems you are facing. You can also attend a Ruby/Rails training, a lot of companies offer classes around the world. RailsBridge is trying to reach out to people aspiring to become better developer, check their site.

Tip: I often use apiDock when I’m looking for documentation on a method/class.

I wrote a Rails app, I adopted and understood the Rails conventions and I feel comfortable writing new apps.

party dog

Congratulations, you should be proud of what you have accomplished! But don’t stop learning! Did you write tests for your application? Do your tests really test your application, or are they just there to make you feel better (i.e: change your code, are your tests still passing? they shouldn’t)? Do you use plugins? Did you look at their code? Do you understand how they work? Could you write your own plugin? What about a Ruby gem? Also, how are your javascript skills? What about CSS and DBA stuff? focus on your weaknesses.

I would strongly suggest contributing code at this point. Contribute a patch to one of the many GitHub projects, or even Rails, you will learn a lot!

Tip: Check out Gregg Pollack’s Scaling Rails series

I wrote a couple of Rails app, I even wrote a plugin/gem.

That’s great, by now you probably are very familiar with Rails and Ruby. You might want to dive in a bit deeper. Maybe check how to wisely use metaprogramming and/or check on how to write C/FFI extensions. Why not look at Ruby’s source code to learn how things really work?

strength

It’s also probably a good time for you to start learning new languages to see how other communities do things. Look at other frameworks and try to understand how and why people chose other conventions/ways. Play with Python, Java, Scala, Clojure, Objective-C, Ocaml, Scheme or whatever language sounds interesting to you. You don’t have to master other languages, but you should try to understand the reasoning behind each approach and understand the pros/cons. It will honestly help your Ruby skills and broaden your horizons.

Tip: Prepare a couple of talks and send proposals to various conferences. (Don’t limit yourself to Ruby conferences)

I know Ruby and Rails like nobody else, I could even quote Rails and MRI’s source code by heart. (just ask a LOC)

Then I hope you are helping with the Ruby 1.9 efforts, contributing code to other implementations (IronRuby, JRuby, MacRuby, Rubinius) and helping with Rails 3 :)


If you are reading this post, you are probably in one of the above categories. Pairing and tutoring are great ways to learn, it’s all about karma. Helping others will help you becoming a better developer. Feel free to leave advise, links and info in the comments.

Community Highlights: Yehuda Katz

Over the past few months, Rails core team member Yehuda Katz has posted a series of great blog articles describing some of the process and technique he’s used while coding Rails 3 with Carl Lerche. In case you haven’t followed his blog posts, I thought I’d repost them here for your educational reading.

Rails 3: The Great Decoupling
is about decoupling components like ActionController and ActionView.

New Rails Isolation Testing
is about the creation of a new test mixin that runs each test case in its own process.

6 Steps to Refactoring Rails
is about the refactoring philosophy he’s using when coding Rails 3.

Rails Edge Architecture
is about Rails 3 Architecture including AbstractController::Base & ActionController::Http

Better Module Organization
is about cleaning up the way modules are included.

alias_method_chain in models
is about alternatives to using alias_method_chain, some of which made it into Rails 3 refactorings.

Rails 3 Extension API
is where on the new wiki Yehuda has started documenting the new extension APIs which are being added for Rails 3. There’s not a whole lot there yet, but be sure to watch this space in the coming weeks.

Rails BugMash

Some of you may remember the Rails Hackfests that were conducted in 2007 and 2008. Well, with some help from the RailsBridge folks, we’re bringing back something similar :

The First Rails and RailsBridge BugMash

The idea is simple: RailsBridge has a lot of energy. The Rails Lighthouse has a lot of open tickets. By combining the RailsBridge enthusiasm with guidance from some Rails Core team members, we’re going to see what we can do to cut down the number of open tickets, encourage more people to get involved with the Rails source, and have some fun.

Here’s how it will work: the BugMash will run over the weekend of August 8-9. The Rails team will identify open issues that need some help and tag them in Lighthouse. Participants will draw from this pool with four goals:

  1. Confirm that the bug can be reproduced
  2. If it can’t be reproduced, try to figure out what information would make it possible to reproduced
  3. If it can be reproduced, add the missing pieces: better repro instructions, a failing patch, and/or a patch that applies cleanly to the current Rails source
  4. Bring promising tickets to the attention of the Core team

RailsBridge is organizing both face-to-face and online support for BugMash participants. The plan is to do everything possible to make it easy to start contributing to Rails, and to increase even further the substantial pool of developers who have helped make Rails what it is.

For more details, including a checklist of what you can do to get ready to work in the Rails source and details on a scoring system and rewards for the most active participants, keep an eye on the RailsBridge Wiki (a work in progress). For now, though, there are two things for you to do:

  1. Reserve at least a chunk of that weekend to roll up your sleeves and work on the BugMash
  2. Speak up by updating the wiki or posting on the mailing lists ( rubyonrails-core or railsbridge ) if you can contribute prizes, familiarity with the Rails source, or other help to the project.

Rails 2.3.3: Touching, faster JSON, bug fixes

We’ve released Ruby on Rails version 2.3.3. This release fixes a lot of bugs and introduces a handful of new features.

Active Record

  • touch is a convenient method to update a record’s timestamp and nothing else. This is extracted from apps whose models “touch” others when they change, such as a comment updating the parent.replies_changed_at timestamp after save and destroy. Timestamping an entire has_many association makes it easy to build a key for fragment caching that covers changes to the parent object and any of its children. This pattern is wrapped up as belongs_to :parent, :touch => :replies_changed_at. When the child changes, parent.replies_changed_at is touched. :touch => true is defaults to :touch => :updated_at.
  • :primary_key option for belongs_to for broader support of legacy schemas and those using a separate UUID primary key: belongs_to :employee, :primary_key => 'SSN', :foreign_key => 'EMPID' changeset

JSON

  • decoding backends for the json and yajl libraries. Both are significantly faster than the default YAML backend. To get started, install the json gem and set ActiveSupport::JSON.backend = 'JSONGem'.
  • leaner user-facing encoding API. Since a JSON libraries implement to_json with varying compatibility, safely overriding it is difficult. Most custom to_json looks like
    
    def to_json(*encoder_specific_args)
      { :some => "json representation" }.to_json(*encoder_specific_args)
    end
    so we DRYed the user-facing API down to a more natural
    
    def as_json(options = {})
      { :some => "json representation" }
    end
    without the ugly internal state exposed by overloading to_json as both public-facing and internal builder API. Rails 3 splits the API explicitly, so prepare now by switching from to_json to as_json.

Other Features

  • Add :concat option to asset tag helpers to force concatenation. changeset
  • Restore backwards compatibility for AR::Base#to_xml. changeset
  • Move from BlueCloth to Markdown for the markdown helper. Users using BlueCloth to provide their markdown functionality should upgrade to version 1.0.1 or 2.0.5 in order to restore compatibility.

Notable Bug Fixes

  • Fix errors caused by class-reloading with streaming responses in development mode.
  • Several fixes to the gem bundling, unpacking and installing system.
  • Make text_area_tag escape contents by default.
  • Make filter_parameters work correctly with array parameters.
  • Thread-safety fixes for postgresql string quoting.
  • Performance fixes for large response bodies.

Remaining Ruby & Rails Conferences in 09

The Ruby and Rails community is still growing strong and the sheer number of conferences coming up is proof of that. Below I’ve put together a list of all the conferences/events I could find before 2010 so you can hopefully make it out to at least one. ;-)

If you do attend one of these conferences, do me a favor and thank the organizer for taking the time to produce the event. Most of them spend a great deal of unpaid time making the event happen and most of them aren’t making a profit. Their passion and hard work helps keep our community strong.

Jul 17 – Jul 20 Rails Camp in Bryant Pond, Maine.

Cost: $120

Jul 17 – Jul 19 Ruby Kaigi 2009 in Tokyo, Japan.

Cost: Sold Out

Jul 24 – Jul 25 Rails Underground in London, UK

Cost: £240

Jul 31 – Aug 1 Rails Outreach Workshop for Women in San Francisco, CA

Cost: FREE

Jul 30 – Aug 1 RubyRx in Philadelphia, PA

Cost: $550

Aug 7 – Aug 9 eRubyCon in Columbus, OH

Cost: $299.00

Sep 10 – Sep 11 Ruby Rx in Washington DC

Cost: $550

Aug 7 – Aug 8 Oxente Rails in Natal, Brazil

Cost: R$ 200,00

Aug 27 – Aug 29 Lone Star Ruby Conf in Austin, TX

Cost: $250

Aug 28 – Aug 29 Ruby Hoedown in Nashville, TN

Cost: FREE

Aug 29 RS on Rails in Porto Alegre, Brazil Cost

Cost: R$50

Sep 1 – Sep 2 Rails Konferenz in Frankfurt, Germany

Cost: €215

Sep 7 – Sep 8 RubyWorld Conference in Matsue, Japan

Cost: ¥5000

Sep 12 Windy City Rails in Chicago, Il

Cost: $99

Sep 26 – Sep 27 Central eUropean RUby camp in Wien, Austria

Cost: Free

Oct 2 – Oct 3 Ruby Foo in London, UK

Cost: £ 220

Oct 5 – Oct 6 Aloha on Rails in Waikiki, HI

Cost: $199

Oct 13 – Oct 14 Rails Summit Latin America in São Paulo, Brazil

Cost: R$ 400

Oct 16 – Oct 19 Rails Camp UK in Margate, UK

Cost: £50

Oct 16 ArrrrCamp in Ghent, Belgium

Cost: Free

Nov 7 – Nov 8 Rupy 2009 in Poznań, Poland

Cost: ? (registration not open yet)

Nov 13- Nov 14 Conferencia Rails in Madrid, Spain

Cost: ?

Nov 19 – Nov 21 Rubyconf in San Francisco, CA

Cost: ? (registration not open yet)

Nov 20 – Nov 23 Rails Camp Australia in Melbourne, Australia

Cost: $180

Let me know if I forgot any events, I’ll be happy to add them to this list.