RailsCasts Pro episodes are now free!

Learn more or hide this

Tyler Collier's Profile

GitHub User: tylercollier

Comments by Tyler Collier

Avatar

Is there an elegant way to deal with optionally-passed locals?

For example say I call

ruby
<%= render 'posts/post', post: post, :size => :panel %>

How can I access that size value in the presenter?

One way is to pass the value into the presenter. For example, from the partial, I might write

ruby
<%= post_presenter.some_method(size) %>

But since size is an optional value passed to the partial, it might not exist, and thus would raise an exception when trying to call some_method. You could check if the local variable exists like this:

ruby
<% if defined?(size) %>
  post_presenter.some_method(size)
<% else %>
  # Don't call presenter method at all, or do other logic.
<% end %>

However, this is ugly, and defeats the point of the presenter! This is the code that we're trying to avoid in the first place.

Thoughts?

Avatar

I like it. I'm not sure if I agree with Jeremy Seitz, as I did something similar to Austin Schneider.

ruby
# presenters/post_presenter.rb
# Note the variable passed in to `present` is also the argument given to the block; this is intentional, see my explanation below.
<% present post do |post| %>
  <div class="<%= post.css_class %>">
    <div class="caption"><%= post.caption %></div>
    <div class="image">
      <%= image_tag(post.image_url) %>
    </div>
    <div class="description">
      <%= post.description %>
    </div>
    <div class="rating">
      <%= post.rating %>
    </div>
  </div>
<% end %>
ruby
class BasePresenter
  #...

  def method_missing(*args, &block)
    @object.send(*args, &block)
  end
end

In my view code, note that you can't tell the difference between post (as PostPresenter) and post (my active record model). I think the ambiguity is fine, or good actually; it's easy to read. To be able to do that, I overrode method_missing to point to the model. That way I don't have to use delegate. But this makes it a little easier to deal with when shifting code around via partials and not having to rename passed locals.