{"id":22027152,"url":"https://github.com/brianp/garnish","last_synced_at":"2025-10-05T14:25:47.070Z","repository":{"id":145494351,"uuid":"2648839","full_name":"brianp/garnish","owner":"brianp","description":"Provides an easy to use and transparent system for implementing the Decorator Pattern","archived":false,"fork":false,"pushed_at":"2013-10-03T05:01:48.000Z","size":260,"stargazers_count":14,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-31T09:11:26.085Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/brianp.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2011-10-26T04:27:35.000Z","updated_at":"2016-10-14T17:16:16.000Z","dependencies_parsed_at":"2023-03-22T22:31:17.144Z","dependency_job_id":null,"html_url":"https://github.com/brianp/garnish","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brianp%2Fgarnish","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brianp%2Fgarnish/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brianp%2Fgarnish/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brianp%2Fgarnish/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brianp","download_url":"https://codeload.github.com/brianp/garnish/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252862729,"owners_count":21815909,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-30T07:35:37.849Z","updated_at":"2025-10-05T14:25:42.021Z","avatar_url":"https://github.com/brianp.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Garnish](http://www.brianpearce.ca/images/garnish.png)\n\n[![Build Status](https://travis-ci.org/brianp/garnish.png?branch=master)](https://travis-ci.org/brianp/garnish)\n[![Code Climate](https://codeclimate.com/github/brianp/garnish.png)](https://codeclimate.com/github/brianp/garnish)\n\n[RDocs](http://rdoc.info/projects/brianp/garnish)\n\nGarnish is a Presenter / Decorator pattern for models in Rails. It gives a home to presentation level view logic that normally litters helpers and view files. Using it can help you:\n\n* Keep helper files and views clean of if/else statements and other logic\n* Better define an interface for views to interact with models\n* Maintain a very familiar OOP pattern within your project directory\n* Keep you controller code clean by never having to instantiate the presenters\n* Handle Decorating / Presenting standard Rails relationships\n\n## Requirements\n\nGarnish Has been tested with\n\n* Rails 3.1+\n* Ruby 1.9.3, 2.0.0, JRuby, Rubinius\n* ActiveRecord, Mongoid\n\n_Notes:_ `\u003e1.9.3` requires you to lock `activesupport` and `actionpack` at\n`\u003e4.0.0`. For this reason we have officially dropped support for ruby\n1.9.2 and earlier. Although it will most likely work without a problem.\n\n## Installation\n\nIn **Rails 3**, add this to your Gemfile and run the `bundle` command.\n\n`gem \"garnish\"`\n\n## Getting Started\n\nA lot of magic happens with Garnish in an attempt to make things incredibly simple for you.\n\n### 1. Define You Presenters\n\nCreate a folder in `app/` called presenters. ex `app/presenters/`\n\nCreate a presenter matching the name of your model in your presenters folder. ex `app/presenters/user_presenter.rb`\n\nDefine the `user_presenter`\n\n```ruby\nmodule UserPresenter\n  include Garnish::Presenter\nend\n```\n\n## 2. Add methods to your presenter\n\nDefine methods in your presenter as regular instance methods\n\n```ruby\nmodule UserPresenter\n  include Garnish::Presenter\n\n  def greeting\n    if last_login.nil?\n      \"Welcome #{name}, can we offer you a tour?\"\n    else\n      \"Welcome back #{name}\"\n    end\n  end\n\nend\n```\n\n### 3. Add the `garnish` call\n\nIn `app/controllers/application_controller.rb` add the garnish call.\n\n```ruby\nclass ApplicationController \u003c ActionController::Base\n  protect_from_forgery\n\n  garnish\nend\n```\n\nOr If you don't want to use Garnish application wide simply add the call into a specific controller.\n\n### 4. Use respond_with\n\nThe only change you need to make to start using your presenters now is to use respond_with inside any controller that has been garnished\n\n`app/controllers/user_controller.rb`\n\n```ruby\ndef show\n  @user = User.find(params[:id])\n\n  respond_with @user do |format|\n    format.html # show.html.erb\n  end\nend\n```\n\nGarnish will now find and load presenters for any instance variables you set inside your action. *NOT* just the ivar passed to the respond_with block.\n\n### 5. Start using your presenter methods\n\n`app/views/users/show.html.erb`\n\n```erb\n  \u003cspan\u003e\u003c%= @user.greeting %\u003e\u003c/span\u003e\n```\n\n## View Helpers\n\nGarnish plays very nicely when adding view helper methods into your presenter. Just treat them like a regular method.\n\n```ruby\nmodule UserPresenter\n  include Garnish::Presenter\n\n  def profile_pic\n    image_tag profile_pic unless profile_pic.nil?\n  end\nend\n```\n\n## Relationships\n\nThe real reason I got down to business. If I'm using presenters in my views I probably have presenters for multiple objects.\n\n```ruby\nclass User \u003c ActiveRecord::Base\n  has_many :items\nend\n\nclass Item \u003c ActiveRecord::Base\n  belongs_to :user\nend\n```\n\nAssuming I have presenters for both of these models\n\n```ruby\nmodule UserPresenter\n  include Garnish::Presenter\nend\n\nmodule ItemPresenter\n  include Garnish::Presenter\n\n  def picture\n    image_tag profile_pic unless profile_pic.nil?\n  end\nend\n```\n\nIn my view when I'm accessing a user's items via the association what I really want is an Item extended with presenter methods not just a regular item.\n\nGarnish handles this for us. Anytime a relationship is accessed on a garnished resource the returned resources will also be extended with their presenter methods.\n\n```erb\n\u003c%= @user.items.first.picture %\u003e\n```\n\nWorks with no effort what so ever.\n\n## Questions or Problems?\n\nIf you have any issues with Garnish which you cannot find the solution to, please add an [issue on GitHub](https://github.com/brianp/garnish/issues) or fork the project and send a pull request.\n\nTo get the specs running you should call `bundle` and then `rake`. See the [spec/README](https://github.com/brianp/garnish/blob/master/spec/README.md) for more information.\n\n## Special Thanks\n\n[Fraser Valley Ruby Brigade](http://www.fvrb.org/)\n\nThe Ruby Moguls\n\nGarnish was inspired by [draper](https://github.com/jcasimir/draper/) and the RailsCast Pro episode #287 Presenters from Scratch.\nSee the [CHANGELOG](https://github.com/brianp/garnish/blob/master/CHANGELOG.rdoc) for the full list.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrianp%2Fgarnish","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrianp%2Fgarnish","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrianp%2Fgarnish/lists"}