Tag: Ruby

  • Sometimes you want to raise an exception when a method fails but without losing information about an inner exception. Let me explain it with an example.

    At Watu we have a method that causes a user to be indexed in our search engine. This method is called many times in different situations. One of those situations is when indexing most or all of our users. Recently, something failed and I got this exception:

    undefined method `each' for #<String:0x10dab8fc>

    Something that should be an array is actually a string. In this case the indexing method is correct, it’s just getting broken data. I want to fix the bug in the data generation, but to locate it, I need to know which user has broken data. I added a rescue clause to my indexing method to show me that data:

    def index
      # ...
    rescue
      raise "Error when indexing user #{self}"
    end

    Now I get something like:

    Error when indexing user #<User:1234>

    which allows me know that user 1234 has something wrong in its data. The problem is that now I have no idea what the issue is. I lost the information about trying to call each on a string.

    The solution to this problem is exception wrapping (or nesting). You want the custom exception to wrap the other one so that you have both pieces of information. This, for example, exists in Java and if you search the web you’ll find ways on how to implement it in Ruby. Implementing this manually is not needed anymore since Ruby 2.1. Unfortunately, it’s a bit hidden and the tools haven’t caught up yet.

    The secret lies in a new method in the class Exception called, cause. At the time of this writing it doesn’t even have documentation:

    No documentation for the method Exception#cause
    No documentation for the method Exception#cause

    Using it is very straightforward. Just raise an exception in the rescue clause and the new exception will have the previous one as its cause. For example, in this case:

    begin
      a = 1 / 0
    rescue
      raise "Something went wrong"
    end

    you get two exceptions: the divided-by-zero wrapped inside one with the “Something went wrong” message.

    The problem arrises that nobody seems to be using the causes of exceptions yet. If you run that in IRB, this is what you get:

    RuntimeError: Something went wrong
    	from (irb):4:in `rescue in irb_binding'
    	from (irb):1
    	from /Users/pupeno/.rvm/rubies/ruby-2.1.0/bin/irb:11:in `<main>`

    But the exception’s cause is in there… hidden. If you catch the outer exception you can access its cause. For example:

    begin
      begin
        a = 1 / 0
      rescue
        raise "Something went wrong"
      end
    rescue => e
      puts e
      puts e.cause
    end
    

    would produce:

    Something went wrong
    divided by 0

    The reason why it doesn’t produce something like that by default is because whatever IRB is using to print exceptions is ignoring the exception’s cause. Now we’ll have to wait until all the tools catch up with this new feature.

    Well, we don’t actually have to wait. Aside from the fact that most of them are open source and you can fix them yourself, Ruby allows you to monkey patch so you can fix your own copy of these tools.

    In my case I needed rake to print inner exceptions, so I wrote this monkey patch (which works for rake 10.1.1):

    module Rake
      class Application
        def display_error_message(ex)
          trace "#{name} aborted!"
          display_exception(ex)
          trace "Tasks: #{ex.chain}" if has_chain?(ex)
          trace "(See full trace by running task with --trace)" unless options.backtrace
        end
    
        private
    
        def display_exception(ex, margin = "")
          trace "#{margin}#{ex.message}"
          if options.backtrace
            trace "#{margin}#{ex.backtrace.join("\n#{margin}")}"
          else
            trace "#{margin}#{Backtrace.collapse(ex.backtrace).join("\n#{margin}")}"
          end
    
          if ex.respond_to?(:cause) && !ex.cause.nil? # Ruby < 2.1.0 doesn't have *cause*
            trace "#{margin}which was caused by:"
            display_exception(ex.cause, "#{margin} ")
          end
        end
      end
    end

    This is something that I would like to see in rake itself so I created an issue request (#253). Take a look at it to follow the development of this feature and hopefully, all tools will start displaying causes in one way or another.

  • Most applications, web, desktop or mobile, handle some kind of data. When we are developing them we generally generate some sample data to play with and we forget to ever run the application without it. The problem is that the first impression people will get of our app is without data. And first impressions are important.

    In the application I’m building, Watu, we are resorting to just create some sample data for customers to play with. Making the application beautiful and meaningful without data is just too hard. It seems the guys at JetBrains spent some time thinking of this because RubyMine 4.0 shows this when there are no open files:

    I think that simple change it’s a good step towards making the application nicer in the no-data scenario, making people happier, as well as making people more productive in it, making the application more useful.

    I do wonder why they didn’t include the most useful of the shortcuts: ⌘⇧N. I think I press that more than any other. It pops up this little dialog:

    in which you can type and it’ll search among all your files (and files inside the gems, that is, libraries, of your project if it doesn’t match anything in your project or if you enable by ticking the include non-project files):

    What I really like, compared to other implementations of this feature, is that you can add more parts of the path, for example:

    Without that feature, my productivity would drop a 10%. I’m not exaggerating, that’s my estimation, as I recently have to code using TextMate instead of RubyMine.

    Before you send me the hate-mail, I know TextMate has a similar feature although I think not as advanced (not without plugins at least) but since the key shortcut was different, it was almost like it didn’t exist for me, so I experienced coding without that feature at all.

    Another potentially useful way to find code is to use ⌘N which allows you to search for a class:

    But since in a Rails projects most classes are in a file with the same name (but underscore instead of camel case) and the file dialog allows me to find views, wich the class dialog doesn’t, I never use the class dialog.

    No… I’m not affiliated with JetBrains, makers of RubyMine in any way. I just love the tool and I wish more Ruby programmers would give it a try because I think they’ll also find it useful and the more people that are using it, the more resources JetBrains is likely to put into its development which ultimately benefits me. And they are cool guys, a pleasure to deal with every time I report a bug or ask for a feature.

  • I find myself needing to have the full URLs in Rails’ logs. Normally you get something like:

    [sourcecode lang=”text”]
    Started GET "/" for 127.0.0.1 at 2011-08-27 13:13:10 +0200
    [/sourcecode]

    but I needed

    [sourcecode lang=”text”]
    Started GET "http://foo.bar:3000/&quot; for 127.0.0.1 at 2011-08-27 13:13:10 +0200
    [/sourcecode]

    because the app does different things depending on the domain and when it fails, I have to know which URL was hit. The solution I ended up with was adding this in an initializer:

    [sourcecode lang=”ruby”]
    class Rails::Rack::Logger << ActiveSupport::LogSubscriber
    protected

    def before_dispatch(env)
    request = ActionDispatch::Request.new(env)
    info "\n\nStarted #{request.request_method} \"#{request.url}\" for #{request.ip} at #{Time.now.to_default_s}"
    end
    end
    [/sourcecode]

    That’s monkey-patching Rails’ own logger. Credit for the solution goes to numbers1311407.

    My question for the people using Rails, do you think having a configurable logger in Rails would be useful or nice? If so, I could make a patch for Rails but I have made patches before that failed to gather the needed popularity and thus were ignored. I’m not wasting my time like that again.

  • A recent update to RubyGems is causing a lot of deprecation warnings like these:

    [sourcecode]
    NOTE: Gem::Specification#default_executable= is deprecated with no replacement. It will be removed on or after 2011-10-01.
    Gem::Specification#default_executable= called from /usr/lib/ruby/gems/1.8/specifications/rubygems-update-1.4.1.gemspec:11.
    NOTE: Gem::Specification#default_executable= is deprecated with no replacement. It will be removed on or after 2011-10-01.
    Gem::Specification#default_executable= called from /usr/lib/ruby/gems/1.8/specifications/bundler-1.0.7.gemspec:10.
    NOTE: Gem::Specification#default_executable= is deprecated with no replacement. It will be removed on or after 2011-10-01.
    Gem::Specification#default_executable= called from /usr/lib/ruby/gems/1.8/specifications/file-tail-1.0.5.gemspec:10.
    [/sourcecode]

    I generally like software to move forward and the way to do that is deprecate and then after a while, make backwards incompatible changes. It’s painful but there’s no other way.

    I do have a problem with all the cron jobs of my web apps like Keep on Posting or DNSk9 flooding my inbox with those warnings. Thankfully, that’s not hard to fix. Where I was doing:

    [sourcecode lang=”bash”]
    rake pre_calculate_thingies > /dev/null
    [/sourcecode]

    now I’ll be doing:

    [sourcecode lang=”bash”]
    rake pre_calculate_thingies 2>&1 >/dev/null | grep -v default_executable
    [/sourcecode]

  • When you are building systems like my Keep on Posting or my DNSk9 that send emails there’s always the danger that you’ll accidentally fire emails from your development machine to real users. You really don’t want to do that because it’s annoying and extremely unprofessional.

    It happened to me a couple of times. Thankfully, nothing serious. But I learned the lesson. That’s why in my user models now I have a safe_email method which I use instead of accessing email whenever I’m about to actually deliver a message.

    The method safe_email ensures that nobody will receive a message unless I’m in production and at the same time it’s good for testing. Obviously most of the time in development and testing mode I don’t deliver emails at all, but sometimes, I make an exception:

    def safe_email
      if Rails.env.production? || email.blank? # If the email is blank (or nil), let it be.
        email
      else
        "pupeno+#{email.gsub("@", "_AT_")}@pupeno.com"
      end
    end
    
  • When I need to run something periodically on production, I always implement it as a rake tasks and install it as a cron job. Nevertheless there’s some setup to do in the task to have proper logging and error reporting.

    This is the template I use for creating those tasks:

    namespace :projectx do
      desc "Do something"
      task :something => :environment do
        if Rails.env.development?
          # Log to stdout.
          logger = Logger.new(STDOUT)
          logger.level = Logger::INFO # DEBUG to see queries
          ActiveRecord::Base.logger = logger
          ActionMailer::Base.logger = logger
          ActionController::Base.logger = logger
        else
          logger = ActiveRecord::Base.logger
        end
    
        begin
          logger.info "Doing something"
        rescue Exception => e
          HoptoadNotifier.notify(e)
          raise e
        end
      end
    end

    While in development mode, it outputs to the console for convenience.

  • For a personal project I’m working on, I need to find out the smallest time period with more than 5 records. I essentially wrote this code:

    period = [1.week, 1.month, 1.year].select_first do |period|
      Record.where("published_at >= ?", period.ago).count >= 5
    end
    

    only to find out that the select_first method doesn’t exist. So I wrote it:

    module Enumerable
      def select_first(&predicate)
        self.each do |item|
          if yield(item)
            return item
          end
        end
        return nil
      end
    end
    

    and then of course, I tested it:

    require "test_helper"
    
    require "enumerable_extensions"
    
    class EnumerableTest  2 }
      end
    
      should "select_first the first one" do
        assert_equal 1, [1, 2, 3, 4].select_first { |i| i >= 1 }
      end
    
      should "select_first the last one" do
        assert_equal 4, [1, 2, 3, 4].select_first { |i| i >= 4 }
      end
    
      should "select_first none" do
        assert_equal nil, [1, 2, 3, 4].select_first { |i| i >= 100 }
      end
    end
    
  • I’ve just released another gem, this one extends Hash to contain another method called hmap. This solves a problem I face ofter: how to run a map in a hash that returns another hash, for example:

    {:a => 1, :b => 2, :c => 3}
    

    being converted into

    {:a => 2, :b => 3, :c => 4}
    

    With hmap it’s easy:

    hash.hmap { |a,b| {a => b + 1} }
    

    It also works with arrays, but you must make sure the array you return always contains two and only two elements:

    hash.hmap { |a,b| [a, b + 1] }
    

    And that’s all, quite a simple piece of code, but now it’s re-usable and well tested.

  • Ruby doesn’t have enums and in Rails I sometimes need it. I’ve come out with my own way of doing after some trial and error. First I want to be able to access these enums as constants in a class, like:

    Pizza::RAW
    Pizza::COOKED
    Pizza::BOXED
    Pizza::DELIVERED
    Pizza::EATEN

    That’s actually quite easy:

    class Pizza
      RAW = 1
      COOKED = 2
      BOXED = 3
      DELIVERED = 4
      EATEN = 5
    end

    If I’m storing those values on the database, I’d like to have my database be more readable, so, I just store strings:

    class Pizza
      RAW = "raw"
      COOKED = "cooked"
      BOXED = "boxed"
      DELIVERED = "delivered"
      EATEN = "eaten"
    end

    That’s not very efficient and there are better ways these days. But it’s simple and premature optimization is the root of all evil. Anyway, back to Ruby, I’d like to be able to get a list of all possible enum values, to be able to populate selections for example:

    class Pizza
      RAW = "raw"
      COOKED = "cooked"
      BOXED = "boxed"
      DELIVERED = "delivered"
      EATEN = "eaten"
    
      STATES = [RAW, COOKED, BOXED, DELIVERED, EATEN]
    end

    Simple enough except that it doesn’t follow DRY style. In Ruby we can do better:

    class Pizza
      STATES = [
        RAW = "raw",
        COOKED = "cooked",
        BOXED = "boxed",
        DELIVERED = "delivered",
        EATEN = "eaten"
      ]
    end

    That defines the constant and since the result of RAW = "raw" is "raw" we can also add it to an array at the same time.

    John, the manager of the Ruby Pizza Shop was concerned that some pizzas were devoured immediately and others took as long as 15 minutes. Decided to improve his business he started investigating the whole procedure and he noticed that as soon as the pizza left the kitchen, some cooks considered delivered and marked them as such. That was wrong so instead of doing a pizza-state training, he decided we should improve the UI. Let’s describe the state.

    class Pizza
      STATES = [
        RAW = "raw",
        COOKED = "cooked",
        BOXED = "boxed",
        DELIVERED = "delivered",
        EATEN = "eaten"
      ]
    
      STATE_EXPLANATIONS {
        RAW => "The pizza is not a pizza yet, just a bunch of ingredients.",
        COOKED => "OMG! That smells good!",
        BOXED => "It's ready to go.",
        DELIVERED => "The pizza has been snatched out of the hands of a delivery boy.",
        EATEN => "The pizza is no more."
      }
    end

    Of course we can do better than that and merge it in one:

    class Pizza
      STATE {
        (RAW = "raw") => "The pizza is not a pizza yet, just a bunch of ingredients.",
        (COOKED = "cooked") => "OMG! That smells good!",
        (BOXED = "boxed") => "It's ready to go.",
        (DELIVERED = "delivery") => "The pizza has been snatched out of the hands of a delivery boy.",
        (EATEN = "eaten") => "The pizza is no more."
      }
    end

    Stylistically I’m not a fan, but semantically, that’s dryer. Now, we can get the list of states like this:

    Pizza::STATE.keys