forked from floere/representer
-
Notifications
You must be signed in to change notification settings - Fork 1
A Representer Pattern for Rails
License
niko/representer
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
# (Re)Presenters for Rails # A possible presenter solution. # Ask/Write florian.hanke@gmail.com if you have questions/feedback, thanks! :) # Fork if you have improvements. Tell me where to merge them from, thanks! # # Problem: Display Methods are not well placed either in # * models: Violation of the MVC principle. # * helpers: No Polymorphism. # Solution: # A thin proxy layer over a model, with access to the controller, used by the view or controller. # # IMPORTANT NOTE: # As of yet it is needed to copy the representer/views/presenters/collection # directory to the corresponding location in app/views/presenters/collection. # This is only needed if you wish to use the collection presenter. # Note: Rewrite the collection templates as needed, they are rather basic. # # * Getting a presenter in a view or a controller. # # Call presenter_for: # Note: By convention, uses Presenters::Model::Class::Name, thus prefixing Presenters:: to # the model class name. presenter_instance = presenter_for model_instance # * Getting a collection presenter in a view. # # The collection presenter renders each of the given items with its presenter. # # Call collection_presenter_for: collection_presenter_instance = collection_presenter_for enumerable_containing_model_instances # Rendering a list. collection_presenter_instance.list # Rendering a collection. collection_presenter_instance.collection # Rendering a table. collection_presenter_instance.table # Rendering a pagination. # Note: Only works if the passed parameter for collection_presenter_for is a PaginationEnumeration. collection_presenter_instance.pagination # * Writing filtered delegate methods on the presenter. # # Will create two delegate methods first_name and last_name that delegate to the model. model_reader :first_name, :last_name # Will create a description delegate method that filters the model value through h. model_reader :description, :filter_through => :h # Will create a description delegate method that filters the model value through first textilize, then h. model_reader :description, :filter_through => [:textilize, :h] # Will create both a first_name and last_name delegate method # that filters the model value through first textilize, then h. model_reader :first_name, :last_name, :filter_through => [:textilize, :h] # Note: Filter methods can be any method on the presenter with arity 1. # * Rendering presenter templates # # Use render_as(template_name, format = nil). # # Gets a Presenters::Model::Class instance presenter = presenter_for Model::Class.new # Gets a Presenters::<model_instance.class.name> instance presenter = presenter_for model_instance # Renders the 'example' partial in presenters/model/class. # Note: Renders a format depending on the request. ../index.text will render example.text.erb. presenter.render_as :example # Renders the 'example.text.erb' partial in presenters/model/class. presenter.render_as :example, :text # * Rails Helpers in Presenters # # Use helper as in the controller. helper ActionView::Helpers::UrlHelper helper ApplicationHelper # Note: It is helpful to create a superclass to all presenters in the project # with generally used helpers. # We use Presenters::Project a lot, for example. See example below. # * Controller Delegate Methods # # Use controller_method(*args). # # Delegates current_user and logger on the presenter to the controller. controller_method :current_user, :logger # * Big Example # # The following classes all have specs of course ;) But are not shown since they don't help the example. # Presenters superclass for this project. # # We include all of Rails' helpers for the presenters in this project. # Also, we include the ApplicationHelper. # # We delegate logger and current_user calls in the presenters to # the active controller. # class Presenters::Project < Presenters::Base # All of Rails' standard helpers. helper ActionView::Helpers::ActiveRecordHelper helper ActionView::Helpers::TagHelper helper ActionView::Helpers::FormTagHelper helper ActionView::Helpers::FormOptionsHelper helper ActionView::Helpers::FormHelper helper ActionView::Helpers::UrlHelper helper ActionView::Helpers::AssetTagHelper helper ActionView::Helpers::PrototypeHelper helper ActionView::Helpers::TextHelper helper ApplicationHelper controller_method :logger, :current_user end # All items have a description that needs to be filtered by textilize. # class Presenters::Item < Presenters::Project model_reader :description, :filter_through => :textilize # Use price in the view as follows: # = presenter.price - will display e.g. 16.57 CHF, since it is filtered first through localize_currency model_reader :price, :filter_through => :localize_currency # Converts a database price tag to the users chosen value, with the users preferred currency appended. # If the user is Swiss, localize_currency will convert 10 Euros to "16.57 CHF" # def localize_currency(price_in_euros) converted_price = current_user.convert_price(price_in_euros) "#{converted_price} #{current_user.currency.to_s}" end end # This class also has partial templates in the directory # app/views/presenters/book # that are called # _cart_item.html.haml # _cart_item.text.erb # # Call presenter_for on a book in the view or controller to get this presenter. # class Presenters::Book < Presenters::Item model_reader :author, :title, :pages model_reader :excerpt, :filter_through => :textilize def header content_tag(:h1, "#{author} – #{title}") end def full_description content_tag(:p, "#{excerpt} #{description}", :class => 'description full') end end # This class also has partial templates in the directory # app/views/presenters/toy # that are called # _cart_item.html.haml # _cart_item.text.erb # # Call presenter_for on a toy in the view or controller to get this presenter. # class Presenters::Toy < Presenters::Item model_reader :starting_age, :small_dangerous_parts def obligatory_parental_warning "Warning, this toy can only be used by kids ages #{starting_age} and up. Your department of health. Thank you." end end
About
A Representer Pattern for Rails
Resources
License
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published
Languages
- Ruby 100.0%