keynote 1.1.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +71 -27
- data/{LICENSE → LICENSE.txt} +2 -6
- data/README.md +119 -47
- data/lib/generators/presenter_generator.rb +16 -24
- data/lib/keynote/cache.rb +1 -1
- data/lib/keynote/controller.rb +4 -5
- data/lib/keynote/core.rb +64 -0
- data/lib/keynote/helper.rb +4 -5
- data/lib/keynote/inline.rb +51 -109
- data/lib/keynote/presenter.rb +13 -19
- data/lib/keynote/railtie.rb +7 -24
- data/lib/keynote/rumble.rb +21 -12
- data/lib/keynote/testing/{minitest_rails.rb → minitest.rb} +1 -2
- data/lib/keynote/testing/rspec.rb +5 -5
- data/lib/keynote/testing/test_present_method.rb +2 -2
- data/lib/keynote/testing/test_unit.rb +1 -1
- data/lib/keynote/version.rb +2 -2
- data/lib/keynote.rb +7 -65
- metadata +68 -96
- data/.editorconfig +0 -14
- data/.gitignore +0 -18
- data/.travis.yml +0 -11
- data/.yardopts +0 -4
- data/Gemfile +0 -4
- data/Rakefile +0 -21
- data/keynote.gemspec +0 -37
- data/lib/generators/templates/keynote_mini_test_unit.rb +0 -11
- data/lib/keynote/testing/minitest_rails.rake +0 -7
- data/scenarios/rails31.docker-compose.yml +0 -15
- data/scenarios/rails31.dockerfile +0 -5
- data/scenarios/rails31.gemfile +0 -7
- data/scenarios/rails32.docker-compose.yml +0 -15
- data/scenarios/rails32.dockerfile +0 -5
- data/scenarios/rails32.gemfile +0 -6
- data/scenarios/rails40.docker-compose.yml +0 -15
- data/scenarios/rails40.dockerfile +0 -5
- data/scenarios/rails40.gemfile +0 -6
- data/scenarios/rails41.docker-compose.yml +0 -15
- data/scenarios/rails41.dockerfile +0 -5
- data/scenarios/rails41.gemfile +0 -6
- data/scenarios/rails42.docker-compose.yml +0 -15
- data/scenarios/rails42.dockerfile +0 -5
- data/scenarios/rails42.gemfile +0 -6
- data/scenarios/rails50.docker-compose.yml +0 -15
- data/scenarios/rails50.dockerfile +0 -5
- data/scenarios/rails50.gemfile +0 -6
- data/scenarios/rails51.docker-compose.yml +0 -15
- data/scenarios/rails51.dockerfile +0 -5
- data/scenarios/rails51.gemfile +0 -6
- data/scenarios.yml +0 -25
- data/spec/benchmarks.rb +0 -73
- data/spec/generator_spec.rb +0 -159
- data/spec/helper.rb +0 -90
- data/spec/inline_spec.rb +0 -157
- data/spec/keynote_spec.rb +0 -130
- data/spec/presenter_spec.rb +0 -179
- data/spec/railtie_spec.rb +0 -33
- data/spec/rumble_spec.rb +0 -277
- data/spec/test_case_spec.rb +0 -12
- /data/lib/generators/templates/{keynote_mini_test_spec.rb → keynote_mini_test_spec.rb.tt} +0 -0
- /data/lib/generators/templates/{keynote_test_unit.rb → keynote_mini_test_unit.rb.tt} +0 -0
- /data/lib/generators/templates/{keynote_presenter.rb → keynote_presenter.rb.tt} +0 -0
- /data/lib/generators/templates/{keynote_rspec.rb → keynote_rspec.rb.tt} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 961b8bbb609c798ba7dd9e9d2896132bc87856f2059724a3cf2be80596cd8be1
|
4
|
+
data.tar.gz: 3a242df538467281e4a5df928e4fc1eab7ffad18a715813b8abc86ec5a815565
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3575f94138d3ccf5a0f45dce0137d616dc79c967753b616f64e02152eb4ed3e5dca8ae91ace4f95206ae082d9a3591b5d39826d2ca7073045dc22331d5a27a2d
|
7
|
+
data.tar.gz: 24ed666d1ee71ebf9e14cee38faf41cf51ad6000260cd695ec3eabd9ab1095270d8588fcdc0cd9d3aff86bff1578864d6e52f92519974ef6717c2e421c883069
|
data/CHANGELOG.md
CHANGED
@@ -1,62 +1,106 @@
|
|
1
|
+
# Change log
|
2
|
+
|
3
|
+
## v2.0.0 (2025-01-10)
|
4
|
+
|
5
|
+
- Update the inline template API to pass source as string instead of parsing comments. [@palkan][]
|
6
|
+
|
7
|
+
```rb
|
8
|
+
# BEFORE:
|
9
|
+
def method_with_a_template
|
10
|
+
a = "foo"
|
11
|
+
|
12
|
+
erb
|
13
|
+
# <div><%= a %></div>
|
14
|
+
end
|
15
|
+
|
16
|
+
# AFTER:
|
17
|
+
def method_with_a_template
|
18
|
+
a = "foo"
|
19
|
+
|
20
|
+
erb(a:) { "<div><%= a %></div>" }
|
21
|
+
end
|
22
|
+
```
|
23
|
+
|
24
|
+
This change makes inline templates less magical, IDE-friendly, and much faster.
|
25
|
+
|
26
|
+
- **Ruby 3+** and **Rails 7+** are required. [@palkan][]
|
27
|
+
|
1
28
|
## v1.1.1
|
2
|
-
|
3
|
-
|
29
|
+
|
30
|
+
- Rumble: Fix passing `true` as an attribute value, which was broken by the
|
31
|
+
escaping changes in v1.0.0. [@igas][]
|
4
32
|
|
5
33
|
## v1.1.0
|
6
|
-
|
34
|
+
|
35
|
+
- Rumble: Fix bug in v1.0.0 that caused an exception if the user passed a `nil`
|
7
36
|
value for an attribute.
|
8
|
-
|
37
|
+
- Rumble: Add support for `aria` attr hashes, behaving the same way as `data`.
|
9
38
|
|
10
39
|
## v1.0.0
|
11
|
-
|
12
|
-
|
13
|
-
|
40
|
+
|
41
|
+
- Add support for Rails 5.1.
|
42
|
+
- Fix all Ruby warnings generated by Keynote itself.
|
43
|
+
- Rumble: Always escape quotation marks in HTML attributes, even if the string
|
14
44
|
is already marked as HTML-safe.
|
15
|
-
|
16
|
-
|
45
|
+
- Rumble: Allow user to pass in a `data` hash to generate data attributes.
|
46
|
+
- Rumble: Allow user to pass in an array value for an attribute, which will be
|
17
47
|
joined by spaces.
|
18
48
|
|
19
49
|
## v0.3.1
|
20
|
-
|
50
|
+
|
51
|
+
- Add support for Rails 5.0. [@dra][]
|
21
52
|
|
22
53
|
## v0.3.0
|
23
|
-
|
24
|
-
|
25
|
-
|
54
|
+
|
55
|
+
- Drop support for Rails 3.0 and Ruby 1.9.2; add support for Rails 4.2.
|
56
|
+
- Drop support for MiniTest::Rails versions older than 2.0; add support for 2.0
|
57
|
+
and higher. [@kirs][]
|
26
58
|
|
27
59
|
## v0.2.3
|
28
|
-
|
60
|
+
|
61
|
+
- Allow user to pass the string version of the presenter name into
|
29
62
|
`Keynote.present` as an alternative to passing a symbol. This makes it less
|
30
63
|
awkward to use namespaced presenters, but it does remove the possibility of
|
31
64
|
defining a `StringPresenter` and using it with code like
|
32
65
|
`k('some string').format_as_markdown`. It seems unlikely that anyone is
|
33
|
-
actually doing that though.
|
34
|
-
|
35
|
-
|
66
|
+
actually doing that though. [@outpunk][]
|
67
|
+
- Update RSpec integration to not print deprecation warnings with RSpec 3.
|
68
|
+
[@DarthSim][]
|
36
69
|
|
37
70
|
## v0.2.2
|
38
|
-
|
71
|
+
|
72
|
+
- Fix another RSpec integration bug, which happened in cases where the app's
|
39
73
|
Gemfile included rspec-rails but not the rspec gem itself.
|
40
|
-
|
74
|
+
- Fix a bug in the generation of specs for zero-arg presenters.
|
41
75
|
|
42
76
|
## v0.2.1
|
43
|
-
|
77
|
+
|
78
|
+
- Update configuration to test across MRI 1.9.2/1.9.3/2.0.0/2.1.0, Rubinius,
|
44
79
|
JRuby, Rails 3.0/3.1/3.2/4.0/4.1.
|
45
|
-
|
80
|
+
- Fix issue #6, in which the order of dependencies in the Gemfile could keep
|
46
81
|
Keynote's RSpec integration from loading correctly.
|
47
82
|
|
48
83
|
## v0.2.0
|
49
|
-
|
84
|
+
|
85
|
+
- Add `Keynote::Inline`, a module that presenters can extend to enable inline
|
50
86
|
templating in any language supported by Rails.
|
51
|
-
|
87
|
+
- Presenters now have a `use_html_5_tags` class method that adds a more
|
52
88
|
complete set of Rumble tag methods to the class.
|
53
|
-
|
89
|
+
- Add `object_names` class method to presenters, returning an array of the
|
54
90
|
symbols that have been passed into the `presents` method.
|
55
|
-
|
91
|
+
- Add an implementation of the `present`/`k` method that's available in test
|
56
92
|
cases. Update test generators accordingly.
|
57
|
-
|
93
|
+
- Update minitest-rails integration to be compatible with the newest
|
58
94
|
version of minitest-rails (on Rails 3.0, 3.1, 3.2, and 4.0).
|
59
95
|
|
60
96
|
## v0.1.3
|
61
|
-
|
97
|
+
|
98
|
+
- Add block form of `present`. If you pass a block into a `present` call, it
|
62
99
|
yields the presenter.
|
100
|
+
|
101
|
+
[@palkan]: https://github.com/palkan
|
102
|
+
[@igas]: https://github.com/igas
|
103
|
+
[@dra]: https://github.com/dra
|
104
|
+
[@kirs]: https://github.com/kirs
|
105
|
+
[@outpunk]: https://github.com/outpunk
|
106
|
+
[@DarthSim]: https://github.com/DarthSim
|
data/{LICENSE → LICENSE.txt}
RENAMED
@@ -1,9 +1,4 @@
|
|
1
|
-
Copyright (c)
|
2
|
-
|
3
|
-
Includes a modified version of Rumble, which is (c) 2011 Magnus Holm.
|
4
|
-
|
5
|
-
Some Rails integration code inspired by Draper, which is (c) 2011-2012 Jeff
|
6
|
-
Casimir and other contributors.
|
1
|
+
Copyright (c) 2025 Ryan Fitzgerald
|
7
2
|
|
8
3
|
MIT License
|
9
4
|
|
@@ -25,3 +20,4 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
25
20
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
26
21
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
27
22
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
data/README.md
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
-
|
1
|
+
[](https://rubygems.org/gems/keynote)
|
2
|
+
[](https://github.com/evilmartians/keynote/actions)
|
2
3
|
|
3
|
-
|
4
|
+
# Keynote
|
4
5
|
|
5
|
-
[!
|
6
|
-
|
6
|
+
> [!TIP]
|
7
|
+
> Flexible presenters for Rails.
|
7
8
|
|
8
9
|
A presenter is an object that encapsulates view logic. Like Rails helpers,
|
9
10
|
presenters help you keep complex logic out of your templates.
|
@@ -11,16 +12,30 @@ presenters help you keep complex logic out of your templates.
|
|
11
12
|
Keynote provides a consistent interface for defining and instantiating
|
12
13
|
presenters.
|
13
14
|
|
15
|
+
## Requirements
|
16
|
+
|
17
|
+
- Ruby >= 3.0.0
|
18
|
+
- Rails >= 7.0
|
19
|
+
|
20
|
+
For older Ruby and Rails versions, you can use Keynote <2.0.
|
21
|
+
|
14
22
|
## Usage
|
15
23
|
|
24
|
+
Add Keynote to your Gemfile:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
gem "keynote", "~> 2.0"
|
28
|
+
```
|
29
|
+
|
30
|
+
Don't forget to run `bundle install`.
|
31
|
+
|
16
32
|
### The basic idea
|
17
33
|
|
18
34
|
A simple case is making a presenter that's named after a model class and holds
|
19
35
|
helper methods related to that model.
|
20
36
|
|
21
|
-
```
|
37
|
+
```ruby
|
22
38
|
# app/presenters/user_presenter.rb
|
23
|
-
|
24
39
|
class UserPresenter < Keynote::Presenter
|
25
40
|
presents :user
|
26
41
|
|
@@ -29,7 +44,7 @@ class UserPresenter < Keynote::Presenter
|
|
29
44
|
end
|
30
45
|
|
31
46
|
def profile_link
|
32
|
-
link_to user, display_name, data: {
|
47
|
+
link_to user, display_name, data: {user_id: user.id}
|
33
48
|
end
|
34
49
|
end
|
35
50
|
```
|
@@ -55,22 +70,25 @@ Keynote looks for a class called `UserPresenter`.
|
|
55
70
|
|
56
71
|
### Generating HTML
|
57
72
|
|
58
|
-
To make it easier to generate slightly more complex chunks of HTML, Keynote
|
59
|
-
|
73
|
+
To make it easier to generate slightly more complex chunks of HTML, Keynote provides several ways to generate HTML fragments.
|
74
|
+
|
75
|
+
#### Using `build_html`
|
76
|
+
|
77
|
+
Keynote includes a modified version of Magnus Holm's [Rumble](https://github.com/judofyr/rumble)
|
60
78
|
library. Rumble gives us a simple block-based syntax for generating HTML
|
61
79
|
fragments. Here's a small example:
|
62
80
|
|
63
|
-
```
|
81
|
+
```ruby
|
64
82
|
build_html do
|
65
83
|
div id: :content do
|
66
|
-
h1
|
84
|
+
h1 "Hello World", class: :main
|
67
85
|
end
|
68
86
|
end
|
69
87
|
```
|
70
88
|
|
71
89
|
Becomes:
|
72
90
|
|
73
|
-
```
|
91
|
+
```html
|
74
92
|
<div id="content">
|
75
93
|
<h1 class="main">Hello World</h1>
|
76
94
|
</div>
|
@@ -81,6 +99,32 @@ to the `build_html` method. The `build_html` method returns a safe string. See
|
|
81
99
|
[the documentation for `Keynote::Rumble`](http://rubydoc.info/gems/keynote/Keynote/Rumble)
|
82
100
|
for more information.
|
83
101
|
|
102
|
+
#### Using inlined partials
|
103
|
+
|
104
|
+
You can extend your presenter class with the `Keynote::Inline` module to enable inline templating in any template language supported by Rails. This is useful for small, self-contained templates that don't need to be extracted into separate files.
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
# app/presenters/user_presenter.rb
|
108
|
+
class UserPresenter < Keynote::Presenter
|
109
|
+
presents :user
|
110
|
+
|
111
|
+
include Keynote::Inline
|
112
|
+
# To user Haml or Slim, enabled them explicitly
|
113
|
+
# inline :haml, :slim
|
114
|
+
|
115
|
+
def profile_link
|
116
|
+
erb do
|
117
|
+
<<~ERB
|
118
|
+
<div class="profile_link">
|
119
|
+
<%= link_to user, display_name, data: { user_id: user.id } %>
|
120
|
+
<i class="fa-user"></i>
|
121
|
+
</div>
|
122
|
+
ERB
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
```
|
127
|
+
|
84
128
|
### A more complex example
|
85
129
|
|
86
130
|
Let's add to our original example by introducing a named presenter. In addition
|
@@ -158,33 +202,76 @@ end
|
|
158
202
|
You can also generate prefixed methods like `user_first_name` by passing
|
159
203
|
`prefix: true` to the `delegate` method.
|
160
204
|
|
205
|
+
## Testing
|
206
|
+
|
207
|
+
Testing a Keynote presenter is similar to using it in views or controllers. You
|
208
|
+
can test presenters with RSpec, Test::Unit, MiniTest, or MiniTest::Unit.
|
209
|
+
|
210
|
+
### RSpec
|
211
|
+
|
212
|
+
Your test files should be in `spec/presenters` or labeled with
|
213
|
+
[`type: :presenter` metadata].
|
214
|
+
|
215
|
+
Here's an example:
|
216
|
+
|
217
|
+
```ruby
|
218
|
+
# spec/presenters/user_presenter_spec.rb
|
219
|
+
|
220
|
+
RSpec.describe UserPresenter do
|
221
|
+
describe "#display_name" do
|
222
|
+
it "returns the name of the user" do
|
223
|
+
user = User.new(first_name: "Alice", last_name: "Smith")
|
224
|
+
|
225
|
+
expect(present(user).display_name).to eq("Alice Smith")
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
```
|
230
|
+
|
231
|
+
### MiniTest
|
232
|
+
|
233
|
+
Your test classes should inherit from Keynote::TestCase.
|
234
|
+
|
235
|
+
```ruby
|
236
|
+
class UserPresenterTest < Keynote::TestCase
|
237
|
+
setup do
|
238
|
+
user = User.new(first_name: "Alice", last_name: "Smith")
|
239
|
+
@presenter = present(user)
|
240
|
+
end
|
241
|
+
|
242
|
+
test "display name" do
|
243
|
+
assert_equal @presenter.display_name, "Alice Smith"
|
244
|
+
end
|
245
|
+
end
|
246
|
+
```
|
247
|
+
|
161
248
|
## Rationale
|
162
249
|
|
163
|
-
### Why use presenters or decorators at all
|
250
|
+
### Why use presenters or decorators at all
|
164
251
|
|
165
252
|
The main alternative is to use helpers. Helpers are fine for many use cases --
|
166
253
|
Rails' built-in tag and form helpers are great. They have some drawbacks,
|
167
254
|
though:
|
168
255
|
|
169
|
-
|
256
|
+
- Every helper method you write gets mixed into the same view object as the
|
170
257
|
built-in Rails helpers, URL generators, and all the other junk that comes
|
171
258
|
along with `ActionView::Base`. In a freshly-generated Rails project:
|
172
259
|
|
173
260
|
```ruby
|
174
|
-
|
175
|
-
=> 318
|
176
|
-
|
177
|
-
=> 119
|
261
|
+
ApplicationController.new.view_context.public_methods.count
|
262
|
+
# => 318
|
263
|
+
ApplicationController.new.view_context.private_methods.count
|
264
|
+
# => 119
|
178
265
|
```
|
179
266
|
|
180
|
-
|
267
|
+
- Helpers can't have state that isn't "global" relative to the view, which
|
181
268
|
can make it hard to write helpers that work together.
|
182
269
|
|
183
|
-
|
270
|
+
- By default, every helper is available in every view. This makes it difficult
|
184
271
|
to set boundaries between different parts of your app and organize your view
|
185
272
|
code cleanly.
|
186
273
|
|
187
|
-
### Why not use decorators
|
274
|
+
### Why not use decorators
|
188
275
|
|
189
276
|
The biggest distinction between Keynote and similar libraries like [Draper] and
|
190
277
|
[DisplayCase] is that Keynote presenters aren't decorators – undefined method
|
@@ -193,17 +280,17 @@ calls don't fall through to an underlying model.
|
|
193
280
|
Applying the Decorator pattern to generating views is a reasonable thing to do.
|
194
281
|
However, this practice also has some downsides.
|
195
282
|
|
196
|
-
|
283
|
+
- Decorators make the most sense when there's exactly one object that's
|
197
284
|
relevant to the methods you want to encapsulate. They're less helpful when
|
198
285
|
you want to do things like define a class whose responsibility is to help
|
199
286
|
render a specific part of your user interface, which may involve bringing in
|
200
287
|
data from multiple models or collections.
|
201
288
|
|
202
|
-
|
289
|
+
- When reading code that uses decorators, it often isn't obvious if a given
|
203
290
|
method is defined on the decorator or the underlying model, especially when
|
204
291
|
the decorator is applied in the controller instead of the view.
|
205
292
|
|
206
|
-
|
293
|
+
- Passing decorated models between controllers and views can make it unclear
|
207
294
|
whether a view (especially a nested partial) depends on a model having some
|
208
295
|
specific decorator applied to it. This makes refactoring view and decorator
|
209
296
|
code harder than it needs to be.
|
@@ -214,7 +301,7 @@ Keynote doesn't automatically generate presenters when you generate models or
|
|
214
301
|
resources. To generate a presenter, you can use the `presenter` generator,
|
215
302
|
like so:
|
216
303
|
|
217
|
-
```
|
304
|
+
```sh
|
218
305
|
$ rails g presenter FooBar foo bar
|
219
306
|
create app/presenters/foo_bar_presenter.rb
|
220
307
|
create spec/presenters/foo_bar_presenter_spec.rb
|
@@ -223,34 +310,19 @@ $ rails g presenter FooBar foo bar
|
|
223
310
|
That project uses RSpec, but the generator can also create test files for
|
224
311
|
Test::Unit or MiniTest::Rails if applicable.
|
225
312
|
|
226
|
-
##
|
227
|
-
|
228
|
-
Keynote is supported on Rails 3.1 through 5.1. Keynote presenters are testable
|
229
|
-
with Test::Unit, RSpec, and MiniTest::Rails (>= 2.0).
|
230
|
-
|
231
|
-
If you find problems with any of the above integrations, please open an issue.
|
313
|
+
## Contributing
|
232
314
|
|
233
|
-
|
315
|
+
Bug reports and pull requests are welcome on GitHub at [https://github.com/evilmartians/keynote](https://github.com/evilmartians/keynote).
|
234
316
|
|
235
|
-
|
236
|
-
supported version of Rails (with a compatible version of Ruby for each one).
|
317
|
+
For gem development, clone the repo and run `bundle install` to install the dependencies. Then, run `bundle exec rake` to run the tests.
|
237
318
|
|
238
|
-
|
239
|
-
run `roadshow run`, or use Docker Compose directly:
|
240
|
-
|
241
|
-
```
|
242
|
-
$ for fn in scenarios/*.docker-compose-yml; do docker-compose -f $fn run --rm scenario; done
|
243
|
-
```
|
319
|
+
(Optionally) Run `bundle exec lefthook install` to configure git hooks (so you never miss linter complaints before opening a PR).
|
244
320
|
|
245
|
-
|
246
|
-
generate`, although the Gemfiles in the `scenarios` directory need to be
|
247
|
-
maintained manually.
|
321
|
+
## License
|
248
322
|
|
249
|
-
|
250
|
-
projects.
|
323
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
251
324
|
|
252
325
|
[DisplayCase]: https://github.com/objects-on-rails/display-case
|
253
326
|
[Draper]: https://github.com/drapergem/draper
|
254
327
|
[Roadshow]: https://github.com/rf-/roadshow
|
255
|
-
[
|
256
|
-
[get the Roadshow tool]: https://github.com/rf-/roadshow/releases
|
328
|
+
[`type: :presenter` metadata]: https://relishapp.com/rspec/rspec-rails/docs/directory-structure
|
@@ -1,34 +1,29 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Rails::Generators
|
4
4
|
class PresenterGenerator < Rails::Generators::NamedBase
|
5
5
|
desc "This generator creates a Keynote::Presenter subclass in " \
|
6
6
|
"app/presenters."
|
7
7
|
|
8
|
-
argument :targets, :
|
8
|
+
argument :targets, type: :array, default: []
|
9
9
|
|
10
|
-
check_class_collision :
|
11
|
-
source_root File.expand_path(
|
10
|
+
check_class_collision suffix: "Presenter"
|
11
|
+
source_root File.expand_path("../templates", __FILE__)
|
12
12
|
|
13
13
|
def create_presenter_file
|
14
|
-
template
|
15
|
-
File.join(
|
14
|
+
template "keynote_presenter.rb",
|
15
|
+
File.join("app/presenters", class_path, "#{file_name}_presenter.rb")
|
16
16
|
end
|
17
17
|
|
18
18
|
def create_test_file
|
19
19
|
case Rails.application.config.generators.rails[:test_framework]
|
20
20
|
when :rspec
|
21
|
-
template
|
22
|
-
when :test_unit
|
23
|
-
# In Rails 4 this is kind of a weird place to generate tests into.
|
24
|
-
# Unfortunately it isn't really fixable without changing the Rails
|
25
|
-
# test tasks, so that's a TODO.
|
26
|
-
template 'keynote_test_unit.rb', test_unit_path
|
21
|
+
template "keynote_rspec.rb", rspec_path
|
27
22
|
when :mini_test
|
28
23
|
if Rails.application.config.generators.mini_test[:spec]
|
29
|
-
template
|
24
|
+
template "keynote_mini_test_spec.rb", mini_test_path
|
30
25
|
else
|
31
|
-
template
|
26
|
+
template "keynote_mini_test_unit.rb", mini_test_path
|
32
27
|
end
|
33
28
|
end
|
34
29
|
end
|
@@ -37,29 +32,26 @@ module Rails::Generators
|
|
37
32
|
|
38
33
|
def rspec_path
|
39
34
|
File.join(
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def test_unit_path
|
44
|
-
File.join(
|
45
|
-
'test/unit/presenters', class_path, "#{file_name}_presenter_test.rb")
|
35
|
+
"spec/presenters", class_path, "#{file_name}_presenter_spec.rb"
|
36
|
+
)
|
46
37
|
end
|
47
38
|
|
48
39
|
def mini_test_path
|
49
40
|
File.join(
|
50
|
-
|
41
|
+
"test/presenters", class_path, "#{file_name}_presenter_test.rb"
|
42
|
+
)
|
51
43
|
end
|
52
44
|
|
53
45
|
def presenter_name_and_target_list
|
54
|
-
[presenter_name, *target_names].join(
|
46
|
+
[presenter_name, *target_names].join(", ")
|
55
47
|
end
|
56
48
|
|
57
49
|
def target_list
|
58
|
-
target_names.join(
|
50
|
+
target_names.join(", ")
|
59
51
|
end
|
60
52
|
|
61
53
|
def presenter_name
|
62
|
-
class_name.sub(/Presenter$/,
|
54
|
+
class_name.sub(/Presenter$/, "").underscore.to_sym.inspect
|
63
55
|
end
|
64
56
|
|
65
57
|
def target_names
|
data/lib/keynote/cache.rb
CHANGED
data/lib/keynote/controller.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Keynote
|
4
4
|
# `Keynote::Controller` is mixed into `ActionController::Base` and
|
@@ -7,9 +7,8 @@ module Keynote
|
|
7
7
|
module Controller
|
8
8
|
# Instantiate a presenter.
|
9
9
|
# @see Keynote.present
|
10
|
-
def present(
|
11
|
-
|
12
|
-
|
13
|
-
alias k present
|
10
|
+
def present(...) = Keynote.present(view_context, ...)
|
11
|
+
|
12
|
+
alias_method :k, :present
|
14
13
|
end
|
15
14
|
end
|
data/lib/keynote/core.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Keynote is a library for defining and instantiating presenters,
|
4
|
+
# objects that encapsulate view logic.
|
5
|
+
#
|
6
|
+
# @see file:README.md
|
7
|
+
module Keynote
|
8
|
+
class << self
|
9
|
+
# Create or retrieve a presenter wrapping zero or more objects.
|
10
|
+
# If a block is given, yield the presenter into it.
|
11
|
+
#
|
12
|
+
# The first parameter is a Rails view context, but you'll usually access
|
13
|
+
# this method through `Keynote::Helper#present`,
|
14
|
+
# `Keynote::Controller#present`, or `Keynote::Presenter#present`, all of
|
15
|
+
# which handle the view context parameter automatically.
|
16
|
+
#
|
17
|
+
# @see Keynote::Helper#present
|
18
|
+
# @see Keynote::Controller#present
|
19
|
+
# @see Keynote::Presenter#present
|
20
|
+
#
|
21
|
+
# @overload present(view, *objects)
|
22
|
+
# Return a presenter wrapping the given objects. The type of the
|
23
|
+
# presenter will be inferred from the type of the first object.
|
24
|
+
# @example
|
25
|
+
# present(view, MyModel.new) # => #<MyModelPresenter:0x0001>
|
26
|
+
# @param [ActionView::Base] view
|
27
|
+
# @param [Array] objects
|
28
|
+
# @return [Keynote::Presenter]
|
29
|
+
#
|
30
|
+
# @overload present(view, presenter_name, *objects)
|
31
|
+
# Return a presenter wrapping the given objects. The type of the
|
32
|
+
# presenter is specified in underscore form by the first parameter.
|
33
|
+
# @example
|
34
|
+
# present(view, :foo_bar, MyModel.new) # => #<FooBarPresenter:0x0002>
|
35
|
+
# @param [ActionView::Base] view
|
36
|
+
# @param [Symbol, String] presenter_name
|
37
|
+
# @param [Array] objects
|
38
|
+
# @return [Keynote::Presenter]
|
39
|
+
#
|
40
|
+
def present(view, *objects)
|
41
|
+
name = if objects[0].is_a?(Symbol) || objects[0].is_a?(String)
|
42
|
+
objects.shift
|
43
|
+
else
|
44
|
+
presenter_name_from_object(objects[0])
|
45
|
+
end
|
46
|
+
|
47
|
+
Cache.fetch(name, view, *objects) do
|
48
|
+
presenter_from_name(name).new(view, *objects).tap do |presenter|
|
49
|
+
yield presenter if block_given?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def presenter_name_from_object(object)
|
57
|
+
object.class.to_s.underscore
|
58
|
+
end
|
59
|
+
|
60
|
+
def presenter_from_name(name)
|
61
|
+
"#{name.to_s.camelize}Presenter".constantize
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/keynote/helper.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Keynote
|
4
4
|
# `Keynote::Helper` is mixed into `ActionView::Base`, providing a `present`
|
@@ -6,9 +6,8 @@ module Keynote
|
|
6
6
|
module Helper
|
7
7
|
# Instantiate a presenter.
|
8
8
|
# @see Keynote.present
|
9
|
-
def present(
|
10
|
-
|
11
|
-
|
12
|
-
alias k present
|
9
|
+
def present(...) = Keynote.present(self, ...)
|
10
|
+
|
11
|
+
alias_method :k, :present
|
13
12
|
end
|
14
13
|
end
|