is_a? in a view helper

I’ve got a partial view that I can use to show several types of models. The only difference I have between objects is a subtitle otherwise the partial is unchanged between objects. I’ve gone with:

module TitleHelper
  def title(object)
    if object.is_a? SomethingA
      #show this
    elsif object.is_a? SomethingB
      #show that
    else
      #show default
    end
  end
end

However, I’ve read that is_a? is something to be avoided. How should I be handling this snippet of view logic?

One way: define to_partial_path on each object. Have a different partial for each object type and use those to hold the differences.

So your view would look like this:

<%= render @object %>

Each object would define to_partial_path (which Rails uses to find the partial to render in our call above.

For further discussion and examples, check out Ruby Science; specifically the Polymorphic Partials section.

1 Like

Thanks @benorenstein, what would be the strategy if you had already used the to_partial_path?

I love the concept of to to_partial_path and it seems like a powerful tool. Our application is showing objects in lots of different ways throughout the application and I wonder if there is a way to have several to_partial_path options? Maybe:

def to_partial_path(style = :default)
  case style
  when default
    # default path
  when :awesome
    # super awesome path
  else
    # raise UnkownStyleError
  end
end

Can you see any reason this would be a bad idea? Can you even pass the argument through?

That would break the normal api for to_partial_path (which normally takes no argument) and so I would recommend against it. And as you guess, I don’t think you can even pass an argument through.

Instead, you can make a new helper method that builds on top of to_partial_path

module TitleHelper
  def title_partial_path(object)
    "#{object.to_partial_path}_title"
  end
end

So if you have an Episode model, it would make it so that the helper would return episodes/episode_title

The helper can be used like this:

render title_partial_path(episode), episode: episode
2 Likes

Thanks @cpytel. That will work great!