MetaPresenter is a Ruby gem for writing highly focused and testable Rails view presenter classes. For each controller/action pair you get a presenter class in app/presenters that you can use in your views with presenter.method_name. This helps you decompose your helper logic into tight, easily testable classes.
Installation
1. Add this line to your application's Gemfile
gem 'meta_presenter'2. Bundle from the command line
bundle install3. Include MetaPresenter::Helpers in ApplicationController
class ApplicationController < ActionController::Base
include MetaPresenter::Helpers
end# mailers are supported too
class ApplicationMailer < ActionMailer::Base
include MetaPresenter::Helpers
endSetup
1. Create an ApplicationPresenter
ApplicationPresenter methods can be used anywhere in the app. This example makes presenter.page_title and presenter.last_login accessible from all views.
# app/presenters/application_presenter.rb
class ApplicationPresenter < MetaPresenter::BasePresenter
def page_title
"My App"
end
def last_login
# controller methods are available to
# presenters in the same namespace
time = current_user.last_login_at
distance_of_time_in_words_to_now(time)
end
end2. Create presenters for your controllers
This example makes presenter.tooltip(text) available for all actions on PagesController:
# app/presenters/pages_presenter.rb
class PagesPresenter < ApplicationPresenter
def tooltip(text)
content_tag(:p, text, class: "font-body1")
end
end<!-- app/views/pages/about.html.erb -->
<h1>About</h1>
<p data-tipsy-content="<%= presenter.tooltip("Don't Be Evil") %>">Gloogle</p>3. Create presenters for specific actions
This example makes presenter.greeting accessible from views. It also delegates undefined methods to current_user, so presenter.email would call current_user.email:
# app/presenters/pages/home_presenter.rb
class Pages::HomePresenter < PagesPresenter
# can also delegate specific methods. ex:
# delegate :email, :last, to: :current_user
delegate_all_to = :current_user
def greeting
"Hello, #{name}"
end
end<!-- app/views/pages/home.html.erb -->
<h1>Home</h1>
<p><%= presenter.greeting %></p>
<p>Last login <%= presenter.last_login %></p>Example directory structure
Note that presenters mirror the namespace of controllers.
app/
controllers/
application_controller.rb
pages_controller.rb
presenters/
application_presenter.rb
pages_presenter.rb
pages/
home_presenter.rb
logs_presenter.rb
views
pages
home.html.erb
logs.html.erb
spec/ (or test/)
presenters/
application_presenter_spec.rb
pages_presenter_spec.rb
pages/
home_presenter_spec.rb
logs_presenter_spec.rb
Aliasing the presenter methods
If you want to customize the presenter method you can specify a shorthand by adding an alias_method to your controller or mailer:
class ApplicationController < ActionController::Base
including MetaPresenter
# So convenient!
alias_method :presenter, :pr
endRequirements
MetaPresenter supports Ruby >= 3.0.0 and ActionPack/ActionMailer >= 6, or >= 7.0.1 for Rails 7 (7.0.0 has a bug)
Links
Specs
To run the specs for the currently running Ruby version, run bundle install and then bundle exec rspec. To run specs for every supported version of ActionPack, run bundle exec appraisal install and then bundle exec appraisal rspec.
Gem release
Make sure the specs pass, bump the version number in meta_presenter.gemspec, build the gem with gem build meta_presenter.gemspec. Commit your changes and push to Github, then tag the commit with the current release number using Github's Releases interface (use the format vx.x.x, where x is the semantic version number). You can pull the latest tags to your local repo with git pull --tags. Finally, push the gem with gem push meta_presenter-version-number-here.gem.
TODO High-Priority
- Add a
rake meta_presenter:installthat generates the scaffolding for you - Make sure directions are clear for manually creating presenters
TODO
- create an example app and link to the repo for it in this README
- add support for layout-level presenters
Contributing
- Fork it
- Create your feature branch (
git checkout -b feature/my-new-feature) or bugfix branch (git checkout -b bugfix/my-helpful-bugfix) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin feature/my-new-feature) - Make sure specs are passing (
bundle exec rspec) - Create new Pull Request
Running the specs
To run specs against different versions of Rails:
bundle exec appraisal install #install dependencies for each ruby version
bundle exec appraisal rails6 rspec #run rails 6 specs on current Ruby
bundle exec appraisal rails7 rspec #run rails 7 specs on current RubyLicense
See the LICENSE file.

