Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 411 lines (288 sloc) 15.762 kB
49fd635 @jcasimir Ton of tweaks/fixes to readme
jcasimir authored
1 # Draper: View Models for Rails
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
2
c222dbe @laserlemon Link build status and add dependency status to README
laserlemon authored
3 [![TravisCI Build Status](https://secure.travis-ci.org/jcasimir/draper.png)](http://travis-ci.org/jcasimir/draper)
6abf506 @jcasimir Adding status image for TravisCI
jcasimir authored
4
d4b1b91 @jcasimir Writing README instead of sleeping
jcasimir authored
5 ## Quick Start
6
7 1. Add `gem 'draper'` to your `Gemfile` and `bundle`
5549614 @steveklabnik fixing generator names in README
steveklabnik authored
8 2. When you generate a resource with `rails g resource YourModel`, you get a decorator automatically!
9 3. If YourModel exists, run `rails g decorator YourModel`
10 4. Edit `app/decorators/[your_model]_decorator.rb` using:
d4b1b91 @jcasimir Writing README instead of sleeping
jcasimir authored
11 1. `h` to proxy to Rails/application helpers like `h.current_user`
b050cd3 @jcasimir Revising README for 0.9.1 with named accessors
jcasimir authored
12 2. `[your_model]` to access the wrapped object like `article.created_at`
5549614 @steveklabnik fixing generator names in README
steveklabnik authored
13 5. Wrap models in your controller with the decorator using:
6d6ff66 @jcasimir This README takes more time than the implementation
jcasimir authored
14 1. `.find` automatic lookup & wrap
15 ex: `ArticleDecorator.find(1)`
16 2. `.decorate` method with single object or collection,
17 ex: `ArticleDecorator.decorate(Article.all)`
18 3. `.new` method with single object
19 ex: `ArticleDecorator.new(Article.first)`
5549614 @steveklabnik fixing generator names in README
steveklabnik authored
20 6. Output the instance methods in your view templates
6d6ff66 @jcasimir This README takes more time than the implementation
jcasimir authored
21 ex: `@article_decorator.created_at`
d4b1b91 @jcasimir Writing README instead of sleeping
jcasimir authored
22
9155e58 @steveklabnik Generators redux.
steveklabnik authored
23 If you need common methods in your decorators, create an `app/decorators/application_decorator.rb`:
24
25 ``` ruby
26 class ApplicationDecorator < Draper::Base
27 # your methods go here
28 end
29 ```
30
31 and make your decorators inherit from it. Newly generated decorators will respect this choice and inherit from `ApplicationDecorator`.
32
33d7fa2 @jcasimir Updating README for 0.9.4 release
jcasimir authored
33 ## Watch the RailsCast
34
35 Ryan Bates has put together an excellent RailsCast on Draper based on the 0.8.0 release:
36
37 [![RailsCast #286](https://img.skitch.com/20111021-dgxmqntq22d37fthky6pttk59n.jpg "RailsCast #286 - Draper")](http://railscasts.com/episodes/286-draper)
38
19f1fc7 @jcasimir Updated README with changelog
jcasimir authored
39 ## What's New
40
1fb9de9 fix link to commits
William Watson authored
41 Check out the full commit history at http://github.com/jcasimir/draper/commits
ebff640 @jcasimir Shoutouts and version highlights
jcasimir authored
42
43 In summary, you can now:
44
45 * [Namespace the `decorates` call](https://github.com/jcasimir/draper/commit/1c3d5667b8406b80b490d876257379087b129f92)
46 * [Use your decorators with CanCan](https://github.com/jcasimir/draper/commit/ac1f3083989107d877e2b1c918c3a3e792db99e8)
47 * [Use a more generalized `options` hash in decorator initialization](https://github.com/jcasimir/draper/commit/03910877d0461356da0968a87346592908f292a7)
48 * [Get better performance by generating methods](https://github.com/jcasimir/draper/commit/ebe30511b79eac82276413ca7ae54a4a4d86d4dc)
138e034 @jpfuentes2 Add example of decorates_association to Readme
jpfuentes2 authored
49 * [Automatically decorate associated objects](https://github.com/jcasimir/draper/commit/1580baa287997ed4e356aae0ffeeb8fe9c326ced) See Example near bottom of Readme
ebff640 @jcasimir Shoutouts and version highlights
jcasimir authored
50
2755c29 @jcasimir Fixing URL error in Readme
jcasimir authored
51 Thanks to [steveklabnik](http://github.com/steveklabnik), [i0rek](http://github.com/i0rek), [laserlemon](http://github.com/laserlemon), [michaelfairley](http://github.com/michaelfairley), [dnagir](http://github.com/dnagir), [ubermajestix](http://github.com/ubermajestix), [tmaier](http://github.com/tmaier), [angelim](http://github.com/angelim), [duncanbeevers](http://github.com/duncanbeevers), Albert Peng & JR Boyens, [leocassarani](http://github.com/leocassarani), [Jeff Felchner](http://github.com/Felchner), [shingara](http://github.com/shingara), [momolog](http://github.com/momolog), and [ayamomiji](http://github.com/ayamomiji) for their contributions to this version!
19f1fc7 @jcasimir Updated README with changelog
jcasimir authored
52
d4b1b91 @jcasimir Writing README instead of sleeping
jcasimir authored
53 ## Goals
54
6d6ff66 @jcasimir This README takes more time than the implementation
jcasimir authored
55 This gem makes it easy to apply the decorator pattern to domain models in a Rails application. This pattern gives you three wins:
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
56
b4f632b @jcasimir Adding in focus on view-layer data filtering based on current_user
jcasimir authored
57 1. Replace most helpers with an object-oriented approach
58 2. Filter data at the presentation level
59 3. Enforce an interface between your controllers and view templates.
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
60
92d2146 @jcasimir Added link to tutorial / sample project
jcasimir authored
61 ### 1. Object Oriented Helpers
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
62
203910c @jcasimir Travis trigger :)
jcasimir authored
63 Why hate normal helpers? In Ruby/Rails we approach everything from an Object-Oriented perspective, then with helpers we get procedural.The job of a helper is to take in data and output a presentation-ready string. We can do that with a decorator.
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
64
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
65 A decorator wraps an object with presentation-related accessor methods. For instance, if you had an `Article` object, then the decorator could override `.published_at` to use formatted output like this:
b4f632b @jcasimir Adding in focus on view-layer data filtering based on current_user
jcasimir authored
66
67 ```ruby
f3c8b53 @patriciomacadden changed a generator call (`rails generate decorator` instead of `rail…
patriciomacadden authored
68 class ArticleDecorator < Draper::Base
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
69 decorates :article
f3c8b53 @patriciomacadden changed a generator call (`rails generate decorator` instead of `rail…
patriciomacadden authored
70
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
71 def published_at
b050cd3 @jcasimir Revising README for 0.9.1 with named accessors
jcasimir authored
72 date = h.content_tag(:span, article.published_at.strftime("%A, %B %e").squeeze(" "), :class => 'date')
73 time = h.content_tag(:span, article.published_at.strftime("%l:%M%p"), :class => 'time').delete(" ")
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
74 h.content_tag :span, date + time, :class => 'created_at'
b4f632b @jcasimir Adding in focus on view-layer data filtering based on current_user
jcasimir authored
75 end
76 end
77 ```
78
92d2146 @jcasimir Added link to tutorial / sample project
jcasimir authored
79 ### 2. View-Layer Data Filtering
b4f632b @jcasimir Adding in focus on view-layer data filtering based on current_user
jcasimir authored
80
49fd635 @jcasimir Ton of tweaks/fixes to readme
jcasimir authored
81 Have you ever written a `to_xml` or `to_json` method in your model? Did it feel weird to put presentation logic in your model?
b4f632b @jcasimir Adding in focus on view-layer data filtering based on current_user
jcasimir authored
82
83 Or, in the course of formatting this data, did you wish you could access `current_user` down in the model? Maybe for guests your `to_json` is only going to show three attributes, but if the user is an admin they get to see them all.
84
85 How would you handle this in the model layer? You'd probably pass the `current_user` or some role/flag down to `to_json`. That should still feel slimy.
86
6e88870 @jcasimir Minor clarity edits
jcasimir authored
87 When you use a decorator you have the power of a Ruby object but it's a part of the view layer. This is where your `to_json` belongs. You can access your `current_user` helper method using the `h` proxy available in the decorator:
b4f632b @jcasimir Adding in focus on view-layer data filtering based on current_user
jcasimir authored
88
89 ```ruby
6d6ff66 @jcasimir This README takes more time than the implementation
jcasimir authored
90 class ArticleDecorator < ApplicationDecorator
49fd635 @jcasimir Ton of tweaks/fixes to readme
jcasimir authored
91 decorates :article
f3c8b53 @patriciomacadden changed a generator call (`rails generate decorator` instead of `rail…
patriciomacadden authored
92
b4f632b @jcasimir Adding in focus on view-layer data filtering based on current_user
jcasimir authored
93 ADMIN_VISIBLE_ATTRIBUTES = [:title, :body, :author, :status]
94 PUBLIC_VISIBLE_ATTRIBUTES = [:title, :body]
95
6e88870 @jcasimir Minor clarity edits
jcasimir authored
96 def to_json
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
97 attr_set = h.current_user.admin? ? ADMIN_VISIBLE_ATTRIBUTES : PUBLIC_VISIBLE_ATTRIBUTES
b050cd3 @jcasimir Revising README for 0.9.1 with named accessors
jcasimir authored
98 article.to_json(:only => attr_set)
b4f632b @jcasimir Adding in focus on view-layer data filtering based on current_user
jcasimir authored
99 end
100 end
101 ```
102
92d2146 @jcasimir Added link to tutorial / sample project
jcasimir authored
103 ### 3. Enforcing an Interface
104
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
105 Want to strictly control what methods are proxied to the original object? Use `denies` or `allows`.
106
107 #### Using `denies`
92d2146 @jcasimir Added link to tutorial / sample project
jcasimir authored
108
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
109 The `denies` method takes a blacklist approach. For instance:
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
110
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
111 ```ruby
6d6ff66 @jcasimir This README takes more time than the implementation
jcasimir authored
112 class ArticleDecorator < ApplicationDecorator
49fd635 @jcasimir Ton of tweaks/fixes to readme
jcasimir authored
113 decorates :article
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
114 denies :title
115 end
116 ```
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
117
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
118 Then, to test it:
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
119
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
120 ```irb
6e88870 @jcasimir Minor clarity edits
jcasimir authored
121 > ad = ArticleDecorator.find(1)
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
122 => #<ArticleDecorator:0x000001020d7728 @model=#<Article id: 1, title: "Hello, World">>
6e88870 @jcasimir Minor clarity edits
jcasimir authored
123 > ad.title
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
124 NoMethodError: undefined method `title' for #<ArticleDecorator:0x000001020d7728>
125 ```
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
126
49fd635 @jcasimir Ton of tweaks/fixes to readme
jcasimir authored
127 #### Using `allows`
128
129 A better approach is to define a whitelist using `allows`:
130
131 ```ruby
6d6ff66 @jcasimir This README takes more time than the implementation
jcasimir authored
132 class ArticleDecorator < ApplicationDecorator
49fd635 @jcasimir Ton of tweaks/fixes to readme
jcasimir authored
133 decorates :article
134 allows :title, :description
135 end
136 ```
137
138 ```irb
198b4fe @manuelmeurer Fixed formatting in Readme
manuelmeurer authored
139 > ad = ArticleDecorator.find(1)
140 => #<ArticleDecorator:0x000001020d7728 @model=#<Article id: 1, title: "Hello, World">>
141 > ad.title
142 => "Hello, World"
143 > ad.created_at
49fd635 @jcasimir Ton of tweaks/fixes to readme
jcasimir authored
144 NoMethodError: undefined method `created_at' for #<ArticleDecorator:0x000001020d7728>
145 ```
146
f02af58 @jcasimir More Readme errors.
jcasimir authored
147 ## Up and Running
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
148
149 ### Setup
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
150
151 Add the dependency to your `Gemfile`:
152
153 ```
154 gem "draper"
155 ```
156
5448aba @jcasimir Minor clarity revisions
jcasimir authored
157 Then run `bundle` from the project directory.
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
158
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
159 ### Generate the Decorator
160
161 To decorate a model named `Article`:
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
162
163 ```
f1bd79b @steveklabnik Updating README.
steveklabnik authored
164 rails generate decorator article
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
165 ```
166
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
167 ### Writing Methods
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
168
5448aba @jcasimir Minor clarity revisions
jcasimir authored
169 Open the decorator model (ex: `app/decorators/article_decorator.rb`) and add normal instance methods. To access the wrapped source object, use a method named after the `decorates` argument:
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
170
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
171 ```ruby
f1bd79b @steveklabnik Updating README.
steveklabnik authored
172 class ArticleDecorator < Draper::Base
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
173 decorates :article
174
175 def author_name
b050cd3 @jcasimir Revising README for 0.9.1 with named accessors
jcasimir authored
176 article.author.first_name + " " + article.author.last_name
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
177 end
178 end
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
179 ```
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
180
181 ### Using Existing Helpers
182
49fd635 @jcasimir Ton of tweaks/fixes to readme
jcasimir authored
183 You probably want to make use of Rails helpers and those defined in your application. Use the `helpers` or `h` method proxy:
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
184
185 ```ruby
f1bd79b @steveklabnik Updating README.
steveklabnik authored
186 class ArticleDecorator < Draper::Base
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
187 decorates :article
188
189 def published_at
b050cd3 @jcasimir Revising README for 0.9.1 with named accessors
jcasimir authored
190 date = h.content_tag(:span, article.published_at.strftime("%A, %B %e").squeeze(" "), :class => 'date')
191 time = h.content_tag(:span, article.published_at.strftime("%l:%M%p"), :class => 'time').delete(" ")
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
192 h.content_tag :span, date + time, :class => 'created_at'
193 end
194 end
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
195 ```
196
6d6ff66 @jcasimir This README takes more time than the implementation
jcasimir authored
197 #### Lazy Helpers
198
199 Hate seeing that `h.` proxy all over? Willing to mix a bazillion methods into your decorator? Then try lazy helpers:
200
201 ```ruby
f1bd79b @steveklabnik Updating README.
steveklabnik authored
202 class ArticleDecorator < Draper::Base
6d6ff66 @jcasimir This README takes more time than the implementation
jcasimir authored
203 decorates :article
2d3c083 @mikezter Encourage use of include keyword
mikezter authored
204 include Draper::LazyHelpers
6d6ff66 @jcasimir This README takes more time than the implementation
jcasimir authored
205
206 def published_at
b050cd3 @jcasimir Revising README for 0.9.1 with named accessors
jcasimir authored
207 date = content_tag(:span, article.published_at.strftime("%A, %B %e").squeeze(" "), :class => 'date')
208 time = content_tag(:span, article.published_at.strftime("%l:%M%p"), :class => 'time').delete(" ")
6d6ff66 @jcasimir This README takes more time than the implementation
jcasimir authored
209 content_tag :span, date + time, :class => 'created_at'
210 end
211 end
212 ```
213
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
214 ### In the Controller
215
216 When writing your controller actions, you have three options:
217
218 * Call `.new` and pass in the object to be wrapped
219
198b4fe @manuelmeurer Fixed formatting in Readme
manuelmeurer authored
220 ```ruby
d834b2d @i0rek Remove backtic.
i0rek authored
221 ArticleDecorator.new(Article.find(params[:id]))
198b4fe @manuelmeurer Fixed formatting in Readme
manuelmeurer authored
222 ```
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
223
224 * Call `.decorate` and pass in an object or collection of objects to be wrapped:
198b4fe @manuelmeurer Fixed formatting in Readme
manuelmeurer authored
225
226 ```ruby
227 ArticleDecorator.decorate(Article.first) # Returns one instance of ArticleDecorator
5448aba @jcasimir Minor clarity revisions
jcasimir authored
228 ArticleDecorator.decorate(Article.all) # Returns an enumeration proxy of ArticleDecorator instances
198b4fe @manuelmeurer Fixed formatting in Readme
manuelmeurer authored
229 ```
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
230
d39a47f @dnagir minor spelling fix
dnagir authored
231 * Call `.find` to automatically do a lookup on the `decorates` class:
198b4fe @manuelmeurer Fixed formatting in Readme
manuelmeurer authored
232
233 ```ruby
234 ArticleDecorator.find(1)
235 ```
75a8204 @rf- Remove unnecessary view_context setup
rf- authored
236
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
237 ### In Your Views
238
239 Use the new methods in your views like any other model method (ex: `@article.published_at`):
240
241 ```erb
242 <h1><%= @article.title %> <%= @article.published_at %></h1>
243 ```
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
244
358e939 @ubermajestix Moved RSpec notes under "Up and Running".
ubermajestix authored
245 ### Integration with RSpec
246
247 Using the provided generator, Draper will place specs for your new decorator in `spec/decorators/`.
75ab9bb @ubermajestix Added notes about decorator specs that might live outside spec/decora…
ubermajestix authored
248
1d6491b @steveklabnik kill set_current_view_context
steveklabnik authored
249 By default, specs in `spec/decorators` will be tagged as `type => :decorator`. Any spec tagged as `decorator` will make helpers available to the decorator.
75ab9bb @ubermajestix Added notes about decorator specs that might live outside spec/decora…
ubermajestix authored
250
251 If your decorator specs live somewhere else, which they shouldn't, make sure to tag them with `type => :decorator`. If you don't tag them, Draper's helpers won't be available to your decorator while testing.
358e939 @ubermajestix Moved RSpec notes under "Up and Running".
ubermajestix authored
252
96a9ba0 @beerlington Update note about Spork usage
beerlington authored
253 Note: If you're using Spork, you need to `require 'draper/test/rspec_integration'` in your Spork.prefork block.
c56ac5e @bdotdub Include Draper::ViewContextFilter in ActionMailer::Base
bdotdub authored
254
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
255 ## Possible Decoration Methods
256
257 Here are some ideas of what you might do in decorator methods:
258
259 * Implement output formatting for `to_csv`, `to_json`, or `to_xml`
260 * Format dates and times using `strftime`
261 * Implement a commonly used representation of the data object like a `.name` method that combines `first_name` and `last_name` attributes
262
263 ## Example Using a Decorator
264
c67edf6 @jcasimir Fixing tutorial link
jcasimir authored
265 For a brief tutorial with sample project, check this out: http://tutorials.jumpstartlab.com/topics/decorators.html
92d2146 @jcasimir Added link to tutorial / sample project
jcasimir authored
266
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
267 Say I have a publishing system with `Article` resources. My designer decides that whenever we print the `published_at` timestamp, it should be constructed like this:
268
269 ```html
270 <span class='published_at'>
271 <span class='date'>Monday, May 6</span>
272 <span class='time'>8:52AM</span>
273 </span>
274 ```
275
276 Could we build that using a partial? Yes. A helper? Uh-huh. But the point of the decorator is to encapsulate logic just like we would a method in our models. Here's how to implement it.
277
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
278 First, follow the steps above to add the dependency and update your bundle.
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
279
280 Since we're talking about the `Article` model we'll create an `ArticleDecorator` class. You could do it by hand, but use the provided generator:
281
282 ```
f3c8b53 @patriciomacadden changed a generator call (`rails generate decorator` instead of `rail…
patriciomacadden authored
283 rails generate decorator Article
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
284 ```
285
286 Now open up the created `app/decorators/article_decorator.rb` and you'll find an `ArticleDecorator` class. Add this method:
287
288 ```ruby
49fd635 @jcasimir Ton of tweaks/fixes to readme
jcasimir authored
289 def published_at
b050cd3 @jcasimir Revising README for 0.9.1 with named accessors
jcasimir authored
290 date = h.content_tag(:span, article.published_at.strftime("%A, %B %e").squeeze(" "), :class => 'date')
291 time = h.content_tag(:span, article.published_at.strftime("%l:%M%p").delete(" "), :class => 'time')
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
292 h.content_tag :span, date + time, :class => 'published_at'
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
293 end
294 ```
295
296 Then you need to perform the wrapping in your controller. Here's the simplest method:
297
298 ```ruby
626462d @kuraga Error in Readme
kuraga authored
299 class ArticlesController < ApplicationController
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
300 def show
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
301 @article = ArticleDecorator.find params[:id]
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
302 end
303 end
304 ```
305
306 Then within your views you can utilize both the normal data methods and your new presentation methods:
307
308 ```ruby
49fd635 @jcasimir Ton of tweaks/fixes to readme
jcasimir authored
309 <%= @article.published_at %>
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
310 ```
311
312 Ta-da! Object-oriented data formatting for your view layer. Below is the complete decorator with extra comments removed:
313
314 ```ruby
f1bd79b @steveklabnik Updating README.
steveklabnik authored
315 class ArticleDecorator < Draper::Base
5c948c6 @jcasimir Rough update to Readme
jcasimir authored
316 decorates :article
317
49fd635 @jcasimir Ton of tweaks/fixes to readme
jcasimir authored
318 def published_at
b050cd3 @jcasimir Revising README for 0.9.1 with named accessors
jcasimir authored
319 date = h.content_tag(:span, article.published_at.strftime("%A, %B %e").squeeze(" "), :class => 'date')
320 time = h.content_tag(:span, article.published_at.strftime("%l:%M%p"), :class => 'time').delete(" ")
34f14ff @jcasimir Fixing inconsistencies in the Readme
jcasimir authored
321 h.content_tag :span, date + time, :class => 'published_at'
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
322 end
323 end
324 ```
138e034 @jpfuentes2 Add example of decorates_association to Readme
jpfuentes2 authored
325
326 ### Example of Decorated Associations
327
328 Add a `decorates_association :association_name` to gain access to a decorated version of your target association.
329
330 ```ruby
f1bd79b @steveklabnik Updating README.
steveklabnik authored
331 class ArticleDecorator < Draper::Base
138e034 @jpfuentes2 Add example of decorates_association to Readme
jpfuentes2 authored
332 decorates :article
333 decorates_association :author # belongs_to :author association
334 end
335
f1bd79b @steveklabnik Updating README.
steveklabnik authored
336 class AuthorDecorator < Draper::Base
138e034 @jpfuentes2 Add example of decorates_association to Readme
jpfuentes2 authored
337 decorates :author
338
339 def fancy_name
340 "#{model.title}. #{model.first_name} #{model.middle_name[0]}. #{model.last_name}"
341 end
342 end
343 ```
344
345 Now when you call the association it will use a decorator.
346
347 ```ruby
348 <%= @article.author.fancy_name %>
349 ```
350
eae7c6d @avdgaag Added note about preloading issues to Readme
avdgaag authored
351 ### A note on Rails configuration
352
353 Draper loads your application's decorators when Rails start. This may lead to an issue with configuring I18n, whereby the settings you provide in `./config/application.rb` are ignored. This happens when you use the `I18n` constant at the class-level in one of the models that have a decorator, as in the following example:
354
355 ```ruby
356 # app/models/user.rb
357 class User < ActiveRecord::Base
358 validates :email, presence: { message: I18n.t('invalid_email') }
359 end
360
361 # app/decorators/user_decorator.rb
362 class UserDecorator < ApplicationDecorator
363 decorates :user
364 end
365 ```
366
367 Note how the `validates` line is executed when the `User` class is loaded, triggering the initialization of the I18n framework _before_ Rails had a chance to apply its configuration.
368
369 Using `I18n` directly in your model definition **is an antipattern**. The preferred solution would be to not override the `message` option in your `validates` macro, but provide the `activerecord.errors.models.attributes.user.email.presence` key in your translation files.
370
860fb06 @steveklabnik Add note about decorates_before_rendering.
steveklabnik authored
371 ## Extension gems
372
373 For automatic decoration, check out [decorates_before_rendering](https://github.com/ohwillie/decorates_before_rendering).
374
eb57738 @patriciomacadden adding the "Contributing" section to the readme
patriciomacadden authored
375 ## Contributing
376
377 1. Fork it.
378 2. Create a branch (`git checkout -b my_awesome_branch`)
379 3. Commit your changes (`git commit -am "Added some magic"`)
380 4. Push to the branch (`git push origin my_awesome_branch`)
381 5. Send pull request
382
4c22bec @jcasimir Added Issues/Pending
jcasimir authored
383 ## Issues / Pending
384
7392064 @jcasimir Tweaks to disabling rails helper generator and updated To-Do list
jcasimir authored
385 * Documentation
fc606e1 @jcasimir Update README and generator templates to use lazy_helpers and draper:…
jcasimir authored
386 * Add more information about using "context"
387 * Add information about the `.decorator` method
7392064 @jcasimir Tweaks to disabling rails helper generator and updated To-Do list
jcasimir authored
388 * Make clear the pattern of overriding accessor methods of the wrapped model
464ffdf @jcasimir Writing to-dos.
jcasimir authored
389 * Build sample Rails application(s)
7392064 @jcasimir Tweaks to disabling rails helper generator and updated To-Do list
jcasimir authored
390 * Generators
391 * Implement hook so generating a controller/scaffold generates a decorator
464ffdf @jcasimir Writing to-dos.
jcasimir authored
392 * Add generators for...
393 * `draper:model`: Model + Decorator
394 * `draper:controller`: Controller setup with decoration calls
395 * `draper:scaffold`: Controller, Model, Decorator, Views, Tests
7392064 @jcasimir Tweaks to disabling rails helper generator and updated To-Do list
jcasimir authored
396 * Other
397 * Implement a HATEOAS helper, maybe as a separate gem
398 * Build a fly website like http://fabricationgem.com
4c22bec @jcasimir Added Issues/Pending
jcasimir authored
399
a3804b0 @jcasimir Bring over generator structure from rails_decorators
jcasimir authored
400 ## License
401
402 (The MIT License)
403
404 Copyright © 2011 Jeff Casimir
405
406 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
407
408 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
409
4b52813 @melriffe Added blurb about turning off the automatic calling of the helper gen…
melriffe authored
410 THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Something went wrong with that request. Please try again.