Hoopla!

now with extra whiz-bang!

Hoopla!

"Warning: colon will be obsoleted; use semicolon"

August 23, 2006 · 9 comments

If you’re getting the title of this post as a strange error showing up in your rails app you’re not alone. If you happen to see this you’re probably running a new version of Ruby (1.8.5).

The source behind this error is in the syntax for Ruby’s control structures (particularly using case and if. Here’s an example of some code from the Rails trunk that follows the currently popular style:

active_record/base.rb:

      def convert_number_column_value(value)
        case value
          when FalseClass: 0
          when TrueClass:  1
          when '':         nil
          else value
        end
      end
action_view/base.rb:

      def find_template_extension_for(template_path)
        if match = delegate_template_exists?(template_path)
          match.first.to_sym
        elsif erb_template_exists?(template_path):        :rhtml
        elsif builder_template_exists?(template_path):    :rxml
        elsif javascript_template_exists?(template_path): :rjs
        else
          raise ActionViewError, "No rhtml, rxml, rjs or delegate template found for #{template_path} in #{@base_path}" 
        end
      end

If you’re getting the title of this post as a strange error showing up in your rails app you’re not alone. If you happen to see this you’re probably running a new version of Ruby (1.8.5).

The source behind this error is in the syntax for Ruby’s control structures (particularly using case and if. Here’s an example of some code from the Rails trunk that follows the currently popular style:

active_record/base.rb:

      def convert_number_column_value(value)
        case value
          when FalseClass: 0
          when TrueClass:  1
          when '':         nil
          else value
        end
      end
action_view/base.rb:

      def find_template_extension_for(template_path)
        if match = delegate_template_exists?(template_path)
          match.first.to_sym
        elsif erb_template_exists?(template_path):        :rhtml
        elsif builder_template_exists?(template_path):    :rxml
        elsif javascript_template_exists?(template_path): :rjs
        else
          raise ActionViewError, "No rhtml, rxml, rjs or delegate template found for #{template_path} in #{@base_path}" 
        end
      end

The warning comes from the use of colons to separate a condition from a statement. Apparently Ruby is working toward eliminating the use of this colon in favor of a semicolon. Since a semicolon marks the end of a line of code it already does what this colon is doing. Here’s the code rewritten to use semicolons (so Ruby won’t barf out errors)

      def convert_number_column_value(value)
        case value
          when FalseClass; 0
          when TrueClass;  1
          when '';         nil
          else value
        end
      end
which is really just the same as:
      def convert_number_column_value(value)
        case value
          when FalseClass then        0
          when TrueClass  then        1
          when ''         then        nil
          else value
        end
      end
and with newlines instead of “then”s:
      def convert_number_column_value(value)
        case value
          when FalseClass
           0
          when TrueClass
           1
          when ''
           nil
          else value
        end
      end
and
      def find_template_extension_for(template_path)
        if match = delegate_template_exists?(template_path)
          match.first.to_sym
        elsif erb_template_exists?(template_path);        :rhtml
        elsif builder_template_exists?(template_path);    :rxml
        elsif javascript_template_exists?(template_path); :rjs
        else
          raise ActionViewError, "No rhtml, rxml, rjs or delegate template found for #{template_path} in #{@base_path}" 
        end
      end
which is really:
      def find_template_extension_for(template_path)
        if match = delegate_template_exists?(template_path)
          match.first.to_sym
        elsif erb_template_exists?(template_path)        then     :rhtml
        elsif builder_template_exists?(template_path)    then     :rxml
        elsif javascript_template_exists?(template_path) then     :rjs
        else
          raise ActionViewError, "No rhtml, rxml, rjs or delegate template found for #{template_path} in #{@base_path}" 
        end
      end
and with newlines:
      def find_template_extension_for(template_path)
        if match = delegate_template_exists?(template_path)
          match.first.to_sym
        elsif erb_template_exists?(template_path) 
         :rhtml
        elsif builder_template_exists?(template_path)
         :rxml
        elsif javascript_template_exists?(template_path)
         :rjs
        else
          raise ActionViewError, "No rhtml, rxml, rjs or delegate template found for #{template_path} in #{@base_path}" 
        end
      end

As is often the case with Ruby/Rails this is largely an aesthetic issue. You can see some discussion about it here: http://www.ruby-forum.com/topic/75349

I’m curious what you think, are the colons pretty enough to stay or should the Rails code be adopted?

Edit: Ryan’s right, I’ve been making some alterations to this code while the post was live – my apologies for the underhandedness. Also I’m totally sorry for my spazzy comments. Even if it gives you some weird error it probably saved just fine. I’m working on un-jacking it.

Edit: If you’re running some form of *x system (macs included) and you’re getting annoyed by the warning output theres a simple way to hide everything but the regular ruby output:
rake test:units 2> /dev/null 

Tags:······

9 responses so far ↓

  • 1 Ryan Bates // Aug 23, 2006 at 07:52 AM

    How about the "then" keyword? I haven't heard any mention of that relating to this subject, even though it does what the colon would do. I'm fine with using semi-colons, but I wonder if it was really necessary to break a lot of existing code for this change. There must be a major motive behind this, perhaps it cleans up the Ruby core a bit. Still, you would think they would save a change this significant for 2.0 or atleast 1.9.
  • 2 Ben Kittrell // Aug 23, 2006 at 01:41 PM

    Uh, hello, earth to Ryan, 'then' is four characters and a semi-colon is only one! But seriously, I just tend to use a new-line anyway. I left trying to fit everything on one line back with Perl in the 90's.
  • 3 Ryan Bates // Aug 24, 2006 at 03:39 AM

    Either I'm going crazy or Danger edited the post and added "then". Sneaky Danger. ;) Looking at them all side by side, the colon is prettiest, but we'll get used to the semi-colon and it does make more sense logically. Speaking of the colon, I've never been fond of the syntax for a symbol. I wish they used a different character other than the colon. I think it's cause for a lot of beginner confusion. I know it was for me. :/ Okay, sorry for the off-topic rant.
  • 4 Ben Kittrell // Aug 24, 2006 at 06:23 AM

    I think you're crazy :) For some reason I really like the semi-colon for symbols. I think it's concept of symbols that's confusing for noobs.
  • 5 Danger // Aug 24, 2006 at 06:41 AM

    @Ryan - I was just playing with options, I actually did the edit before your comment. Uhhh, I mean, yeah I totally am sneaky :-)
  • 6 Danger // Aug 24, 2006 at 06:45 AM

    I totally agree with you Ryan that this seems like a major version change - not the kind of thing that should be introduced between 1.8.4 and 1.8.5. I don't know if you guys are running off 1.8.5 yet but when I run my tests my console fills up with crap. I don't really care what solution is found to this - I just want the warnings to go away.
  • 7 Ben Kittrell // Aug 25, 2006 at 12:29 AM

    Does your console fill up because of stuff in Rails, or your own code? I'm sure Rails 1.2 will probably have all of this refactored.
  • 8 Danger // Aug 25, 2006 at 02:04 AM

    I'm sure they'll fix this eventually (there's already a patch for it) but I don't know how long it'll take them to implement it. My code doesn't contain any of this syntax, it's all coming from my ./vendor/rails directory (edge has it as well as every gem version).
  • 9 Vinnie // Sep 14, 2006 at 01:27 AM

    I prefer the newline over the others really. "then" reminds me too much of VB6 :)

Leave a Comment