Code Monkey home page Code Monkey logo

basic_presenter's Introduction

Code Climate Gem Version

BasicPresenter

BasicPresenter adds a layer of presentation logic to your application.

Its inspired from https://github.com/railscasts/287-presenters-from-scratch/ and http://svs.io/day/2012/12/27

Inspiration

Rails being a flexible framework starts with all methods being part of model and when it gets big, developers are haunted with the daunting task of its maintenance.

Leveraging Presentation pattern with Presenters requires lot of context loading with separating view/derived methods from actual objects and moving them to presenters and making relevant changes to instantiate right object wherever needed.

By letting the knowledge of Presenters slip through model leveraging delegation helps us with the movement of view/derived methods from actual objects to presenters without letting other code to know about the delegation and change. Strict movement and no other code change.

Why use Presenters?

Presenters deal with presentation, so your models can concentrate on domain logic. Instead of polluting models with presenter logic, you can implement the presenter method in a presenter instead.

Installation

Requires active_support

Add this line to your application's Gemfile:

gem 'basic_presenter'

And then execute:

$ bundle

Or install it yourself as:

$ gem install basic_presenter

Or to use the edge version, add this to your Gemfile:

gem 'basic_presenter', :github => 'vinsol/basic_presenter'

Usage

Creating Presenter Directory

rails g basic_presenter:install

Generating Presenters

To generate a presenter by itself:

rails g basic_presenter:presenter User

Writing Presenters

Presenters are stored in app/presenters, they inherit from BasicPresenter::BasePresenter and are named based on the model they present. We also recommend you create an ApplicationPresenter.

Accessing the Model

You can access the model using the domain_object method, or the model name (in this case user). For example:

# app/models/user.rb
class User
  attr_accessor :first_name, :last_name

  def initialize(first_name, last_name)
    @first_name = first_name
    @last_name = last_name
  end 
end

# app/presenters/application_presenter.rb
class ApplicationPresenter < BasicPresenter::BasePresenter 
end
  

# app/presenters/user_presenter.rb
class UserPresenter < ApplicationPresenter
  # You can access the model using the `domain_object` method,
  # or the model name (in this case `user`). For example:

  presents :user

  @delegation_methods = [:first_name, :last_name]

  # Use ActiveSupport `delegate`
  delegate *@delegation_methods, to: :user

  def full_name
    first_name + last_name
  end
end

The model name is either inferred from the model class name - taking User and adding Presenter to it.
presents creates a wrapper for domain model object to call it close to domain than something like domain_object

Wrapping Models with Presenters

Just pass the model to a new presenter instance:

user = User.new('Vinsol', 'User')
user_presenter = UserPresenter.new(user)
user_presenter.full_name # Output: VinsolUser

Use model #presenter method

# app/models/user.rb
class User
  include BasicPresenter::Concern

  attr_accessor :first_name, :last_name

  def initialize(first_name, last_name)
    @first_name = first_name
    @last_name = last_name
  end
end

user = User.new('Vinsol', 'User')
user.presenter.full_name # Output: VinsolUser

Override default_presenter class UserPresenter for User, you can set AdminPresenter

# app/presenters/admin_presenter.rb
class AdminPresenter < ApplicationPresenter
  # You can access the model using the `domain_object` method,
  # or the model name (in this case `admin`). For example:

  presents :admin

  @delegation_methods = [:first_name, :last_name]

  # Use ActiveSupport `delegate`
  delegate *@delegation_methods, to: :admin

  def full_name
    "#{first_name}-#{last_name}"
  end
end

user = User.new('Vinsol', 'User')
user.presenter.full_name # Output: VinsolUser
user.presenter_class = AdminPresenter
user.presenter.full_name # Output: Vinsol-User

Enhancing User to allow calls like user.presenter.full_name to be user.full_name

# app/models/user.rb
class User
  include BasicPresenter::Concern

  attr_accessor :first_name, :last_name

  @delegation_methods = [:full_name]

  # Use ActiveSupport `delegate`
  # No change in this line needed
  # As BasicPresenter::Concern Module always exposes presenter method
  # to return presenter instance

  delegate *@delegation_methods, to: :presenter

  def initialize(first_name, last_name)
    @first_name = first_name
    @last_name = last_name
  end
end

user = User.new('Vinsol', 'User')
user.presenter.full_name # Output: VinsolUser
user.full_name # Output: VinsolUser
user.presenter_class = AdminPresenter
user.presenter.full_name # Output: Vinsol-User
user.full_name # Output: Vinsol-User

Testing

RSpec

PENDING: The specs are placed in spec/presenters. Add type: :presenter if they are placed elsewhere.

Acknowledgements

License

Mozilla Public License Version 2.0

Free to use in open source or proprietary applications, with the caveat that any source code changes or additions to files covered under MPL V2 can only be distributed under the MPL V2 or secondary license as described in the full text.

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

Credits

vinsol.com: Ruby on Rails, iOS and Android developers

Copyright (c) 2014 vinsol.com, released under the New MIT License

basic_presenter's People

Contributors

bansalakhil avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

basic_presenter's Issues

Can we use SimpleDelegator ?

Can we use SimpleDelegator instead of explicitly hand picking and delegating method to the concerned model ? This would automatically delegate the methods to the concerned model if the method is not present in the presenter.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.