Simple and easy to use presentation layer for your Rails models.
Add this line to your application's Gemfile:
gem 'decent_presenter'
And then execute:
$ bundle
Or install it yourself as:
$ gem install decent_presenter
In your controller (ApplicationController) include DecentPresenter::Exposable module:
classApplicationController < ActionController::BaseincludeDecentPresenter::Exposableendand you can start using DecentPresenters!
To decorate your model (e.g. user) just use:
@user=present(User.find(params[:id]))Works the same way with collections:
@users=present(User.all)By default it will use UserPresenter so it must be defined before decorating model. Put it in app/presenters directory. Presenters should inherit from DecentPresenter::Base:
classUserPresenter < DecentPresenter::BaseendIf you want other presenter, use with option:
@user=present(User.find(params[:id]),with: OtherUserPresenter)or
@users=present(User.all,with: OtherUserPresenter)To access decorated object within presenter use either model or object method:
classUserPresenter < DecentPresenter::Basedefname"presented #{model.name}"enddefage"presented #{object.name}"endendYou can access Rails helpers by h or helpers method:
classUserPresenter < DecentPresenter::Basedefedit_pathh.edit_user_path(model)enddefpathhelpers.user_path(model)endendAll methods not implemented by presenters are automatically delegated to decorated model.
Works with kaminari and will_paginate by default, no need to delegate and hack anything.
The same way as in controllers:
classUserPresenter < DecentPresenter::Basedefarticlespresent(model.articles)endendThis might be a bit tricky. To access helpers, presenters depend on view_context which is passed from controllers. To instantiate a new presenter, you need two arguments: model and view_context. If you don't need helpers, you can pass nil as a second argument:
presented_user=UserPresenter.new(user,nil)What if you need helpers? You can pass ActionController::Base.helpers as a second argument. The problem with that solution is that you won't have access to url helpers from your routes and your custom helpers. To handle these cases, you can stub url methods or create fake helper module for your tests:
moduleFakeUrlHelpersdefarticles_path# some codeendendand extend helpers with these modules:
helpers=ActionController::Base.helpershelpers.extendFakeUrlHelpershelpers.extendApplicaitonHelperpresented_user=UserPresenter.new(user,helpers)Future releases will handle such use cases in a cleaner way.
- Implement generators
- Provide better solution for testing
- Fork it ( https://github.com/[my-github-username]/decent_presenter/fork )
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create a new Pull Request
