Gray Soft

The programming blog of James Edward Gray II (JEG2).
  • 7

    OCT
    2008

    DSL Block Styles

    There's an argument that rages in the Ruby camps: to instance_eval() or not to instance_eval(). Most often this argument is triggered by DSL discussions where we tend to want code like:

    configurable.config do
      width 100
      mode  :wrap
    end
    

    You can accomplish something like this by passing the block to instance_eval() and changing self to an object that defines the width() and mode() methods. Of course changing self is always dangerous. We may have already been inside an object and planning to use methods from that namespace:

    class MyObject
      include Configurable       # to get the config() method shown above
    
      def initialize
        config do
          width calculate_width  # a problem:  may not work with instance_eval()
        end
      end
    
      private
    
      def calculate_width        # the method we want to use
        # ...
      end
    end
    

    In this example, if width() comes from a different configuration object, we're in trouble. The instance_eval() will shift the focus away from our MyObject instance and we will get a NoMethodError when we try to call calculate_width(). This may prevent us from being able to use Configurable in our code.

    Read more…

    In: Ruby Voodoo | Tags: DSLs & Style | 7 Comments
  • 6

    OCT
    2008

    Conversion Methods

    I want to take a step back from all the syntax I've been covering lately and just talk about some simple methods in Ruby's core. Ruby ships with so many great helpers, it's often hard to keep track of what everything can do. Specifically, let's talk about the type conversion methods.

    I assume we all make calls to to_s() and to_i() regularly:

    255.to_s    # => "255"
    "255".to_i  # => 255
    

    There shouldn't be any surprises there. Even these two simple methods can do more though. They make it possible to convert to and from various numeric bases. For example, here are the same conversions into and out of base 16 (hexadecimal):

    255.to_s(16)   # => "ff"
    "ff".to_i(16)  # => 255
    

    Ruby has other ways to do these same conversions. Here are two unusual methods (beginning with capital letters) that are similar:

    String(255)     # => "255"
    Integer("255")  # => 255
    

    I'll be honest and tell you that I don't really find String() useful as it just calls to_s() for you, but Integer() is a different story. First of all, to_i() is very lenient about what it converts while Integer() is more strict:

    Read more…

    In: Ruby Voodoo | Tags: APIs | 0 Comments
  • 3

    OCT
    2008

    I'm Addicted to the Word Array

    Continuing with my recent trend of showing of fun uses of Ruby syntax, I have a confession to make: I'm addicted to Ruby's "word Array." I really am.

    I suspect most of you know this, but the word Array is a shortcut that can lessen the quote-comma-quote syndrome of simple a simple Array like:

    ["a", "wordy", "Array"]
    

    You can create the same Array with the word Array syntax:

    %w[a wordy Array]
    

    That's essentially just a String that will automatically be split() on whitespace to build an Array. You can use any amount of space any place you like, so you can layout the data in whatever way makes the most sense for you:

    require "pp"
    pp %w[ one   two   three
           four  five  six
           seven eight nine
                 zero        ]
    # >> ["one",
    # >>  "two",
    # >>  "three",
    # >>  "four",
    # >>  "five",
    # >>  "six",
    # >>  "seven",
    # >>  "eight",
    # >>  "nine",
    # >>  "zero"]
    

    Note that you can chose the punctuation characters used at either ends of the Array, some of which are paired while others just repeat:

    Read more…

  • 2

    OCT
    2008

    Interpolation and Statements

    I still cringe anytime I see code like:

    "1 + 2 = " + (1 + 2).to_s  # => "1 + 2 = 3"
    

    Some books even advocate the above, which is a real shame for Ruby.

    I imagine most of you know that you can rewrite the above to use String interpolation:

    "1 + 2 = #{1 + 2}"  # => "1 + 2 = 3"
    

    Let's think about that simple code a little bit more than we usually do though. What's really going on here? Obviously #{ … } inserts the result of the embedded code in the String, but it's important to realize that it also calls to_s() on that result to make it fit in the String.

    We can really make use of that knowledge if we try. Here's an example:

    Name = Struct.new(:first, :last) do
      def full
        "#{first} #{last}".strip  # trick 1
      end
      alias_method :to_s, :full   # trick 2
    end
    
    Name.new("James").full                     # => "James"
    Name.new(:James, :Gray).full               # => "James Gray"
    "My name is #{Name.new('James', 'Gray')}." # => "My name is James Gray."
    

    I've built a trivial data class for managing names here. In that, I've tried to make use of interpolation to the fullest.

    Read more…

    In: Ruby Voodoo | Tags: Syntax | 7 Comments
  • 2

    OCT
    2008

    Working With Multiline Strings

    I imagine most Rubyists are aware that Ruby has "heredocs," but do you really know all they can do? Let's find out.

    A "here document" is a literal syntax for a multiline String. In the most basic form, they look like this:

    p <<END_HEREDOC
    This is a
      multiline,
    as is String!
    END_HEREDOC
    # >> "This is a\n  multiline,\nas is String!\n"
    

    The <<NAME syntax introduces the heredoc, but it actually begins at the start of the following line. It continues until NAME occurs again, at the beginning of a line. Note the trailing newline in the example above. All of the data between start and finish is packaged up into a String and dropped in where the original <<NAME designator appeared.

    There are some important details in that description, namely that the String begins on the next line and that it's inserted where the heredoc was started. This means that the rest of the line where the heredoc is started can have normal Ruby code (though your editor may syntax highlight it badly):

    p <<END_SQL.gsub(/\s+/, " ").strip
    SELECT * FROM     users
             ORDER BY users.id DESC
    END_SQL
    # >> "SELECT * FROM users ORDER BY users.id DESC"
    

    Read more…

  • 1

    OCT
    2008

    Lone Star Rubyconf Slides

    I've had a couple of requests for my slides from Lone Star Rubyconf. Here are those links for those who want them:

    • At LSRC 2007 I gave a Ruby as a Glue Language speech. My slides are available.
    • I also gave a Hidden Gems talk at LSRC 2008. Those slides are available as well.
    • For LSRC 2009 I talked mainly about Japan, but also mentioned Ruby's modules a little. The talk was called Module Magic. I've made those slides available.
  • 26

    JUN
    2008

    Summoning Error Classes As Needed

    In the past, I've written a lot of code like this:

    class SomeThing
      class SomeError       < RuntimeError; end
      class AnotherError    < RuntimeError; end
      class YetAnotherError < RuntimeError; end
    
      # some methods that can raise the above errors...
    end
    

    I have a new strategy I've been using for code like this and it has really been working out well. Here is how I do the same thing today:

    class SmarterThing
      def self.const_missing(error_name)  # :nodoc:
        if error_name.to_s =~ /Error\z/
          const_set(error_name, Class.new(RuntimeError))
        else
          super
        end
      end
    
      # error raising methods here...
    end
    

    Let's discuss how this works. The const_missing() method is a hook in Ruby, much like the beloved method_missing(). Note that const_missing() is a class method though, instead of an instance method. When a constant is used and Ruby can't find it, a call to the hook will be triggered.

    In this version, I just check to see if the constant name ends in Error. If it does, I summon an Exception subclass on the fly. Other calls to this hook are forwarded on to Ruby's default error raising implementation via super.

    Read more…

  • 25

    JUN
    2008

    The One Method Config

    I've used this technique a couple of times now for dirt-simple configurations. The idea is to provide a trivial way to read and write configuration values with just a single method. Let me show you what I mean:

    module Configurable
      module_function
    
      def config(new_config = nil)
        if new_config.nil?
          @config ||= { }
        else
          config.merge!(new_config)
        end
      end
    end
    
    include Configurable
    
    config                    # => {}
    
    config :a => 1, :b => 2
    config                    # => {:a=>1, :b=>2}
    config[:a]                # => 1
    
    config :a => -1, :c => 3
    config                    # => {:a=>-1, :b=>2, :c=>3}
    
    config.clear
    config                    # => {}
    

    There's no deep magic here, obviously. The method has two function: read and write for the configuration. Read is handled with what I like refer to as Ruby's "caching operator" (||=). The first time that line is triggered, it will cache an empty Hash in the variable. Thereafter, the same call is just a cache hit to get the same Hash back.

    Read more…

  • 8

    JUN
    2008

    Getting Git Thanks to PeepCode

    It's pretty clear that Git has landed. More and more projects are migrating to Git for their version control needs and developers have another system we need to get up to speed on.

    I'm usually a traditional dead-tree book learner, but this time I decided to try the PeepCode approach. I had heard good things about them and I can now tell you that reputation is well deserved.

    PeepCode has two resources available for those wanting to learn more about Git. First, there is a one hour screencast called Git covering everything from installing through basic usage. There's also a newer 120 page PDF book called Git Internals, that ships with some different screencast material. You can purchase either product for $9, which really is a steal in my opinion. Both are well done, but let me break down their strengths for you below.

    The original screencast is a great resource for the developer who wants to get up to speed on Git in a hurry. You just watch for an hour, perhaps try a few examples as you go, and you should come out the other side with basic Git usage skills. An added bonus is that the screencast covers Git's Subversion integration which is a topic you don't want to miss, but it's sadly missing in the PDF book. It also has some good tips on configuring the gitk browser under Mac OS X.

    Read more…

  • 8

    JUN
    2008

    Programming Amazon Web Services

    I really wanted to love Programming Amazon Web Services and it does have some things going for it, but there are enough minuses to keep me from giving it full marks. Let me start by talking about what the book covers, then we will take a look at what it did well and not so well.

    This book provides full coverage of Amazon's suite of Web services. You'll find detailed chapters on Amazon's file storage service S3, their cloud computing service EC2, their messaging service SQS, their payment gateway FPS, and their document database service SimpleDB. The book begins by explaining Amazon's philosophies for these services, how they affect the suite as a whole, and why that should be important to you. For each service you will find detailed information about the design and intent of the service, how to interact with the API (including a full client implementation), and example applications making use of the service. The larger and more complicated services span multiple chapters to make sure all key aspects of using that service are covered.

    Read more…