Skip to content

szTheory/meta_presenter

Repository files navigation

Gem Version Build Status Coverage Status Inline docs Maintainability MIT License Gem GitHub stars

logo

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.

overlay-shape-clean-sm

Installation

1. Add this line to your application's Gemfile

gem 'meta_presenter'

2. Bundle from the command line

bundle install

3. Include MetaPresenter::Helpers in ApplicationController

class ApplicationController < ActionController::Base
  include MetaPresenter::Helpers
end
# mailers are supported too
class ApplicationMailer < ActionMailer::Base
  include MetaPresenter::Helpers
end

Setup

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
end

2. 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
end

Requirements

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:install that 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

  1. Fork it
  2. Create your feature branch (git checkout -b feature/my-new-feature) or bugfix branch (git checkout -b bugfix/my-helpful-bugfix)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin feature/my-new-feature)
  5. Make sure specs are passing (bundle exec rspec)
  6. 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 Ruby

License

See the LICENSE file.