Skip to content

Instantly share code, notes, and snippets.

@jcasimir
Created March 22, 2012 17:41
Show Gist options
  • Save jcasimir/2160696 to your computer and use it in GitHub Desktop.
Save jcasimir/2160696 to your computer and use it in GitHub Desktop.
class ApplicationController < ActionController::Base
extend AttributeViewable
end
module AttributeViewer
def attr_viewable(*names)
names.each do |name|
attr_accessor name
helper_method name
private "#{name}=".to_sym
end
end
end
<table>
<% messages.each do |message| %>
<tr>
<td><%= message.subject %></td>
<td><%= message.body %></td>
<td><%= link_to 'Show', message %></td>
<td><%= link_to 'Edit', edit_message_path(message) %></td>
<td><%= link_to 'Destroy', message, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</table>
class MessagesController < ApplicationController
attr_viewable :message, :messages
def index
self.messages = Message.all
end
end
@tenderlove
Copy link

@myobie you could mix in a module on each request. So something like:

class MessagesController < ApplicationController
  def index
    extend Module.new {
      attr_accessor :messages
    }

    self.messages = IndexContainer.new(Message.all)
  end
end

But I strongly advise against doing that. It breaks method caches which will slow method lookup on every request, and couples your code with the fact that the controller is a new instance on every request.

Usage of a context (or container, or presenter, or whatever you want to call it) object allows you to:

  • test behavior of the container outside of your controller (you don't need to write a functional test to test the Container)
  • decouple the view from the controller (you could test the view without instantiating a controller)
  • get NoMethodErrors raised exactly at the point where the error occurred (rather than waiting for the nil to be used)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment