Hash Defaults and Nested OrderedHash in Rails
Thanks to ruby_switcher.sh I now have Ruby 1.9 running on my machine. Subsequently, I’ve just run into my first Ruby 1.9 induced bug: I relied upon 1.9’s Hash ordering. Fortunately, Rails’ ActiveSupport has it’s own undocumented OrderedHash implementation for Ruby 1.8. Unfortunately you can’t create an OrderdHash using the hash literal notation (i.e { :a => 1, :b => 2 }) so making a nested OrderedHash could be painful.
ActiveRecord #find_by_id with Conditions and NotFound Exception
Every so often I’ve seen code (maybe even written by yours truly) that looked something like this:
post = Post.first(:conditions => { :id => 1, :published => true })However, this won’t raise an error like a #find(id) would. So then the following line is added:
post = Post.first(:conditions => { :id => 1, :published => true })
raise ActiveRecord::RecordNotFound unless postBut this is getting a bit messy and seems overly complicated. Fortunately, we have a better solution.
Ironically, this solution is actually well documented in the Rails docs. Any call to ActiveRecord::Base#find accepts an options hash. This means we can do things like:
post = Post.first(1, :conditions => { :published => true })Now that looks much better.
Coloration in Autotest with TestUnit 2.0.3 1
I recently discovered that even though TestUnit 2.0.3 has support for for coloration, coloration does not show in Autotest. Previously, the redgreen gem had taken care of this, but now that TestUnit itself supports coloration the redgreen gem is no longer necessary (not to mention the fact that it’s broken with Ruby 1.9 and TestUnit 2.0.3). TestUnit supports a –use-color flag, but because of the unique way in which Autotest loads the tests I was unable to figure out how I could pass this flag. Furthermore, –use-color defaults to false when the command is passed to a pipe, which Autotest also does.
ActsAsNestedController with infinitely more documentation!
A while back I wrote a plugin to help with managing the logic of controllers with nested routes. Unfortunately, I was lazy and never documented it. I finally got around to refactoring it and adding proper documentation. You can find it at: http://github.com/rxcfc/acts_as_nested_controller
:use_route param for Rails URL helper
Imagine the following case. You have two landing pages, one generic one, and an account specific one. The urls are as follows:
map.landing 'landing', :controller => 'landing', :action => 'index'
map.account_landing 'accounts/:account_id/landing', :controller => 'landing', :action => 'index'Now imagine you want a path to the landing page, using the most specific route possible. If you have an account_id, use it, if not, skip it.
You could do:
url_for(:controller => 'landing', :action => 'index', :account_id => current_account)If current_account is set you’ll get “/accounts/:account_id/landing” if not, you’ll get “/landing”. However, that just looks ugly.
Enter :use_route => nil.
Path Expander
UPDATE: This is not necessary. See this post for details.
From time to time, I’ve been working on a Rails app with nested routes and ran into the situation where I want to nest the url only if I have the necessary information. Consider the following example to see what I mean:
user_projects_path(current_user) #=> /users/:id/projectsNow this will work perfectly if current_user is defined, but what if current_user is nil? Unfortunately, I’ll end up with the less than desirable “/users//projects”. To avoid this I could use an if statement along the lines of:
current_user ? user_projects_path(current_user) : projects_path
#=> /users/:id/projects or /projectsThis will work of course, but it isn’t all that elegant. Another option would be something along the lines of:
Ruby Operators and Assignment Shortcuts
Recently I was looking through some source code (probably Rails) and discovered a handy little shortcut. When using operators, Ruby doesn’t return a true or false, it returns the actual value of the last piece that it evaluated. I’m sure most of you are familiar with using the OR operator for this. Here’s a simple example:
a = nil
b = "hello"
c = a || b # => "hello"As you can see, the variable “c” isn’t assigned a true or false value. Instead Ruby tries to evaluate “a”, discovers that it returns nil (a false value would behave the same) and then moves on to “b” which it assigns to “c”.
What you might not have realized is that this same principle can also be applied to the AND operator.
Don't Just Ignore schema.rb!
It’s a long standing practice among many Rails developers to have their version control ignore schema.rb. However this practice is contrary to that recommended by the Rails source itself! As you can see from this commit, DHH himself highly encourages that you check in into version control. This alone should be good reason to pause and consider if we should keep ignoring schema.rb.
Pragmatic Programming
Recently I’ve been thinking a lot about the importance of being a pragmatic programmer. No, I don’t mean one of those guys who writes very helpful books on programming. Instead, I mean just that: a programmer who is pragmatic. The New Oxford American Dictionary defines pragmatic as "dealing with things sensibly and realistically in a way that is based on practical rather than theoretical considerations". So by that understanding a pragmatic programmer is one who takes a sensible and practical approach and doesn’t get stuck on theoretical endeavors. Now don’t get me wrong, theory is all well and good, and I’ve had lots of great theoretical discussions on all sorts of issues, but at the end of the day the work needs to get done. And for the work to be done, one needs to be pragmatic.
Regexp.new with Multiple Modifier
This may be a no brainer, but I was working with Regexp.new and ran into and wanted to make a regexp with multiple modifiers. It’s easy enough to make one, the docs show you how to:
r = Regexp.new('dog', Regexp::EXTENDED) #=> /dog/xBut what if you want more than one modifier? The docs say they should be “or-ed” together. This is as simple as:
r = Regexp.new('test', Regexp::IGNORECASE | Regexp::MULTILINE)
#=> /test/miYou can even use all three as such:
r = Regexp.new('test', Regexp::IGNORECASE | Regexp::MULTILINE | Regexp::EXTENDED)
#=> /dog/mixSort of a no-brainer once you realize what it means.
Older posts: 1 2