ruby-on-railsrubyruby-on-rails-4activeview

Catching exceptions in a render call from a rails helper


This is for a rails 4.0.2 application running ruby 2.0.0-p353.

I have a helper that has the following method

def render_feed_row(activity_item)
  begin
    if activity_item.type == "comment"
      render "newsfeed/comment", :item => activity_item
    elsif activity_item.type == "post"
      render "newsfeed/post", :item => activity_item
    else
      raise NameError
    end
  rescue NameError => e # note: NoMethodError is a subclass of NameError
    render "newsfeed/other", :item => activity_item
  end
end

But if a NoMethodError is raised in the newsfeed/post partial, it is not caught in this helper. Why is that? It don't render newsfeed/other, it actually raises an exception.


Solution

  • I've just checked with a simplified version of your code, and it worked correctly.

    def render_feed_row
      raise NoMethodError
    rescue NameError
      puts "kaboom"
    end
    
    render_feed_row
    # => kaboom
    

    However, please note it's a very bad practice to use exceptions for control flow in such way. Moreover, if you really want to use exceptions, you should create your own classes, not use NoMethodError or NameError that have specific meanings in Ruby programs.

    Here's a more clean version of your method

    def render_feed_row(activity_item)
      case (type = activity_item.type)
      when "comment", "post"
        render "newsfeed/#{type}", item: activity_item
      else
        render "newsfeed/other", item: activity_item
      end
    end
    

    Or a more concise version

    def render_feed_row(activity_item)
      name = case activity_item.type
      when "comment", "post"
        activity_item.type
      else
        "other"
      end
      render "newsfeed/#{name}", item: activity_item
    end