nice_partials 0.1.9 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dc6e751d8a192aa46fe3ee5401fe924c4dc1f5c6c3c7fabe8c22f468ff3a344c
4
- data.tar.gz: de5a48e0d84e96a40b85293933af3dadd4977e6dfa2dd06522c85e1a6fbd0576
3
+ metadata.gz: b3b70755595cff02588aa600004e44ec9f20847a4fdd026e0326876a2cad7f52
4
+ data.tar.gz: 24e42267606eb6a56ed481d2b82d137210618dff3282f6586036aa68bfad71c0
5
5
  SHA512:
6
- metadata.gz: 5f56fb3b92520c7a818b6ced0225def224a265a9ca2400d70e283300df8eef3fc266c6b65fa2e4e24856d7eccb6c0b39bdadf056bdec76c499be68fd9d90a982
7
- data.tar.gz: 6a58763a68c0aa76cfee32432c730166cd96a19b2c8a1e8428c26260663ff706fc4883af07e9b1782da0d7e493ca7f4f8883fde223b75674967acce7a3780bc1
6
+ metadata.gz: de339636e922f606a268eb0a9888686e3f0c6b3bdd0f874c8c50998a55437dfc8dff7f4a1c4293d4814277f75a49a959aa47ba9318ad9d9898d651c87d5fc6f8
7
+ data.tar.gz: ed7d3ff442df563d12aba16982a7a3ecae8a5f5b3022255e733bd2b5fd816c828064ddb659162839ef234fc26b22bd3f3a3a6be175e918a5518688a5cfe8bde2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,163 @@
1
1
  ## CHANGELOG
2
2
 
3
+ * Fix rendering with special characters in a view path.
4
+
5
+ Ref: https://github.com/bullet-train-co/nice_partials/pull/70
6
+
7
+ * Seed Nice Partials content from `local_assigns`
8
+
9
+ Previously, the only way to assign content to a Nice Partial was through passing a block:
10
+
11
+ ```erb
12
+ # app/views/posts/show.html.erb
13
+ <%= render "posts/post", byline: "Some guy" %>
14
+
15
+ # app/views/posts/_post.html.erb
16
+ <%= render "card" do |partial| %>
17
+ <% partial.title "Hello there" %>
18
+ <% partial.byline byline %> <%# `byline` comes from the outer `render` call above. %>
19
+ <% end %>
20
+
21
+ Now, Nice Partials will automatically use Rails' `local_assigns`, which contain any `locals:` passed to `render`, as the seed for content. So this works:
22
+
23
+ ```erb
24
+ <%= render "card", title: "Hello there", byline: byline %>
25
+ ```
26
+
27
+ And the `card` partial is now oblivious to whether its `title` or `byline` were passed as render `locals:` or through the usual assignments in a block.
28
+
29
+ ```erb
30
+ # app/views/_card.html.erb
31
+ <%= partial.title %> written by <%= partial.byline %>
32
+ ```
33
+
34
+ Previously to get this behavior you'd need to write:
35
+
36
+ ```erb
37
+ # app/views/_card.html.erb
38
+ <%= partial.title.presence || local_assigns[:title] %> written by <%= partial.byline.presence || local_assigns[:byline] %>
39
+ ```
40
+
41
+ Passing extra content via a block appends:
42
+
43
+ ```erb
44
+ <%= render "card", title: "Hello there" do |partial| %>
45
+ <% partial.title ", and welcome!" %> # Calling `partial.title` outputs `"Hello there, and welcome!"`
46
+ <% end %>
47
+ ```
48
+
49
+ * Add `NicePartials::Partial#slice`
50
+
51
+ Returns a Hash of the passed keys with their contents, useful for passing to other render calls:
52
+
53
+ ```erb
54
+ <%= render "card", partial.slice(:title, :byline) %>
55
+ ```
56
+
57
+ * Fix `partial.helpers` accidentally adding methods to `ActionView::Base`
58
+
59
+ When using `partial.helpers {}`, internally `class_eval` would be called on the Partial instance, and through `delegate_missing_to` passed on to the view context and thus we'd effectively have a global method, exactly as if we'd just used regular Rails view helpers.
60
+
61
+ * Let partials respond to named content sections
62
+
63
+ ```erb
64
+ <% partial.content_for :title, "Title content" %> # Before
65
+ <% partial.title "Title content" %> # After
66
+
67
+ # Which can then be output
68
+ <% partial.title %> # => "Title content"
69
+ <% partial.title? %> # => true
70
+ ```
71
+
72
+ Note, `title` responds to `present?` so rendering could also be made conditional with:
73
+
74
+ ```erb
75
+ <% partial.title if partial.title? %> # Instead of this…
76
+ <% partial.title.presence %> # …you can do this
77
+ ```
78
+
79
+ #### Passing procs or components
80
+
81
+ Procs and objects that implement `render_in`, like ViewComponents, can also be appended as content:
82
+
83
+ ```erb
84
+ <% partial.title { "some content" } %>
85
+ <% partial.title TitleComponent.new(Current.user) %>
86
+ ```
87
+
88
+ #### Capturing `options`
89
+
90
+ Options can also be captured and output:
91
+
92
+ ```erb
93
+ <% partial.title class: "text-m4" %> # partial.title.options # => { class: "text-m4" }
94
+
95
+ # When output `to_s` is called and options automatically pipe through `tag.attributes`:
96
+ <h1 <% partial.title.options %>> # => <h1 class="text-m4">
97
+ ```
98
+
99
+ #### Proxying to the view context and appending content
100
+
101
+ A content section appends to its content when calling any view context method on it, e.g.:
102
+
103
+ ```erb
104
+ <% partial.title.t ".title" %>
105
+ <% partial.title.link_to @document.name, @document %>
106
+ <% partial.title.render "title", user: Current.user %>
107
+ <% partial.title.render TitleComponent.new(Current.user) do |component| %>
108
+ <% … %>
109
+ <% end %>
110
+ ```
111
+
112
+ #### Building elements with `tag` proxy
113
+
114
+ These `tag` calls let you generate elements based on the stored content and options:
115
+
116
+ ```erb
117
+ <% partial.title "content", class: "post-title" %> # Adding some content and options…
118
+ <% partial.title.h2 %> # => <h2 class="post-title">content</h2>
119
+ <% partial.title.h2 "more" %> # => <h2 class="post-title">contentmore</h2>
120
+ ```
121
+
122
+ * Add `NicePartials#t` to aid I18n.
123
+
124
+ When using NicePartials with I18n you end up with lots of calls that look like:
125
+
126
+ ```erb
127
+ <% partial.title t(".title") %>
128
+ <% partial.description t(".header") %>
129
+ <% partial.byline t("custom.key") %>
130
+ ```
131
+
132
+ With NicePartials' `t` method, you can write the above as:
133
+
134
+ ```erb
135
+ <% partial.t :title, description: :header, byline: "custom.key" %>
136
+ ```
137
+
138
+ Clarifying what keys get converted to what content sections on the partial rather than the syntax heavy `partial.… t(".…")`.
139
+
140
+ Like the Rails built-in `t` method, it's just a shorthand alias for `translate` so that's available too.
141
+
142
+ * Add `Partial#content_from`
143
+
144
+ `content_from` lets a partial extract contents from another partial.
145
+ Additionally, contents can be renamed by passing a hash:
146
+
147
+ ```erb
148
+ <% partial.title "Hello there" %>
149
+ <% partial.byline "Somebody" %>
150
+
151
+ <%= render "shared/title" do |cp| %>
152
+ # Here the inner partial `cp` accesses the outer partial through `partial`
153
+ # extracting the `title` and `byline` contents.
154
+ # `byline` is renamed to `name` in `cp`.
155
+ <% cp.content_from partial, :title, byline: :name %>
156
+ <% end %>
157
+ ```
158
+
159
+ ### 0.1.9
160
+
3
161
  * Remove need to insert `<% yield p = np %>` in partials.
4
162
 
5
163
  Nice Partials now automatically captures blocks passed to `render`.
data/Gemfile CHANGED
@@ -1,7 +1,17 @@
1
1
  source "https://rubygems.org"
2
+ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
2
3
 
3
4
  gemspec
4
5
 
5
6
  gem "minitest"
6
7
  gem "rake"
7
8
  gem "irb"
9
+
10
+ if ENV["RAILS_MAIN"]
11
+ gem "rails", github: "rails/rails", branch: "main"
12
+ else
13
+ gem "rails"
14
+ end
15
+
16
+ gem "view_component"
17
+ gem "capybara"
data/README.md CHANGED
@@ -1,150 +1,254 @@
1
- # nice_partials [![[version]](https://badge.fury.io/rb/nice_partials.svg)](https://badge.fury.io/rb/nice_partials) [![[travis]](https://travis-ci.org/andrewculver/nice_partials.svg)](https://travis-ci.org/andrewculver/nice_partials)
1
+ # nice_partials [![[version]](https://badge.fury.io/rb/nice_partials.svg)](https://badge.fury.io/rb/nice_partials)
2
2
 
3
- Nice Partials lets [`content_for` and `yield`](https://guides.rubyonrails.org/layouts_and_rendering.html#using-the-content-for-method) calls be partial specific, to provide named "content areas" or "slots". This optional layer of magic helps make traditional Rails view partials a better fit for extracting components from your views, like so:
3
+ Nice Partials adds ad-hoc named content areas, or sections, to Action View partials with a lot of extra power on top.
4
+
5
+ Everything happens through a new `partial` method, which at the base of it have method shorthands for partial specific `content_for` and `content_for?`s.
6
+
7
+ See, here we're outputting the `image`, `title`, and `body` sections:
4
8
 
5
9
  `app/views/components/_card.html.erb`:
6
10
  ```html+erb
7
11
  <div class="card">
8
- <%= partial.yield :image %>
12
+ <%= partial.image %> # Same as `partial.content_for :image`
9
13
  <div class="card-body">
10
- <h5 class="card-title"><%= title %></h5>
11
- <% if partial.content_for? :body %>
14
+ <h5 class="card-title"><%= partial.title %></h5>
15
+ <% if partial.body? %>
12
16
  <p class="card-text">
13
- <%= partial.yield :body %>
17
+ <%= partial.body %>
14
18
  </p>
15
19
  <% end %>
16
20
  </div>
17
21
  </div>
18
22
  ```
19
23
 
20
- Then you can call `render`, but specify how to populate the content areas:
24
+ Then in `render` we populate them:
21
25
 
22
26
  ```html+erb
23
- <%= render 'components/card', title: 'Some Title' do |partial| %>
24
- <% partial.content_for :body do %>
25
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
26
- tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
27
- <strong>quis nostrud exercitation ullamco laboris</strong> nisi ut aliquip
28
- ex ea commodo consequat.
27
+ <%= render "components/card", title: "Some Title" do |partial| %>
28
+ <% partial.title t(".title") %> # Same as `partial.content_for :title, t(".title")`
29
+
30
+ <% partial.body do %>
31
+ Lorem ipsum dolor sit amet,
29
32
  <% end %>
30
33
 
31
- <% partial.content_for :image do %>
32
- <%= image_tag image_path('example.jpg'), alt: 'An example image' %>
34
+ <% partial.image do %>
35
+ <%= image_tag image_path("example.jpg"), alt: "An example image" %>
33
36
  <% end %>
34
37
  <% end %>
35
38
  ```
36
39
 
37
- Nice Partials is a lightweight and hopefully more Rails-native alternative to [ViewComponent](http://viewcomponent.org). It aims to provide many of the same benefits as ViewComponent while requiring less ceremony. This specific approach originated with [Bullet Train](https://bullettrain.co)'s "Field Partials" and was later reimagined and completely reimplemented by Dom Christie.
40
+ So far these uses are pretty similar to Rails' global `content_for` & `content_for?`, except these sections are local to the specific partial, so there's no clashing or leaking.
38
41
 
42
+ ### More-in depth compared to regular Rails partials
39
43
 
40
- ## Sponsored By
44
+ Consider this regular Rails partials rendering:
41
45
 
42
- <a href="https://bullettrain.co" target="_blank">
43
- <img src="https://github.com/CanCanCommunity/cancancan/raw/develop/logo/bullet_train.png" alt="Bullet Train" width="400"/>
44
- </a>
45
- <br/>
46
- <br/>
46
+ ```html+erb
47
+ <%= render "components/card" do %>
48
+ <% content_for :title, "Title content" %>
49
+ <% end %>
47
50
 
48
- > Would you like to support Nice Partials development and have your logo featured here? [Reach out!](http://twitter.com/andrewculver)
51
+ # app/views/components/_card.html.erb
52
+ <%= yield :title %>
53
+ <%= yield %>
54
+ ```
55
+
56
+ There's a number of gotchas here:
49
57
 
58
+ - The `content_for` writes to `:title` across every partial, thus leaking.
59
+ - The rendering block isn't called until `<%= yield %>` is, so the `content_for` isn't called and `<%= yield :title %>` outputs nothing.
50
60
 
51
- ## Benefits of Nice Partials
61
+ With Nice Partials the yield is automatic and we can write content for just that partial without leaking:
62
+
63
+ ```html+erb
64
+ <%= render "components/card" do |partial| %>
65
+ <% partial.title "Title content" %>
66
+ <% end %>
67
+
68
+ # app/views/components/_card.html.erb
69
+ <%= partial.title %>
70
+ ```
71
+
72
+ This happens because Nice Partials checks the partial source code for any `yield` calls that calls Rails' `capture` helper — e.g. `yield` and `yield something` but not `yield :title`. If there's no capturing yields Nice Partials calls `capture` for you.
73
+
74
+ This means Nice Partials also respect existing yield calls in your partial, so you can upgrade existing partials bit by bit or not at all if you don't want to.
52
75
 
53
76
  Nice Partials:
54
77
 
55
- - is just regular Rails view partials like you're used to.
56
- - reduces the friction when extracting components.
57
- - only ends up in the specific partials you need its functionality in.
58
- - reduces context switching.
59
- - allows isolated helper logic alongside your partial view code.
60
- - doesn't require any upgrades to existing partials for interoperability.
61
- - are still testable!
78
+ - are still regular Rails view partials.
79
+ - reduces the friction when extracting components.
80
+ - only ends up in the specific partials you need the functionality.
81
+ - reduces context switching.
82
+ - allows isolated helper logic alongside your partial view code.
83
+ - doesn't require any upgrades to existing partials for interoperability.
84
+ - are still testable!
62
85
 
86
+ Nice Partials are a lightweight and more Rails-native alternative to [ViewComponent](http://viewcomponent.org). Providing many of the same benefits as ViewComponent with less ceremony.
63
87
 
64
- ## Can't I do the same thing without Nice Partials?
88
+ ## What extra powers does `partial` give me?
65
89
 
66
- You can almost accomplish the same thing without Nice Partials, but in practice you end up having to flush the content buffers after using them, leading to something like this:
90
+ Having a `partial` object lets us add abstractions that are hard to replicate in standard Rails partials.
91
+
92
+ ### Passing content from the render call
93
+
94
+ Nice Partials will use Action View's `local_assigns`, which stores any `locals` passed to `render`, as the basis for contents.
95
+
96
+ Given a partial like
67
97
 
68
98
  ```html+erb
69
- <div class="card">
70
- <%= yield :image %>
71
- <% content_for :image, flush: true do '' end %>
72
- <div class="card-body">
73
- <h5 class="card-title"><%= title %></h5>
74
- <% if content_for? :body %>
75
- <p class="card-text">
76
- <%= yield :body %>
77
- <% content_for :body, flush: true do '' end %>
78
- </p>
79
- <% end %>
80
- </div>
81
- </div>
99
+ <%# app/views/components/_card.html.erb %>
100
+ <%= partial.title %> written by <%= partial.byline %>
82
101
  ```
83
102
 
84
- Earlier iterations of Nice Partials aimed to simply clean up this syntax with helper methods like `flush_content_for`, but because the named content buffers were in a global namespace, it was also possible to accidentally create situations where two partials with a `:body` content area would end up interfering with each other, depending on the order they're nested and rendered.
103
+ Can then be used like this:
104
+
105
+ ```html+erb
106
+ <%= render "components/card", title: "Hello there", byline: "Some guy" do |partial| %>
107
+ <% partial.byline ", who writes stuff" %>
108
+ <% end %>
109
+ ```
85
110
 
86
- Nice Partials resolves the last-mile issues with standard view partials and content buffers by introducing a small, generic object that helps transparently namespace your named content buffers. This same object can also be used to define helper methods specific to your partial that are isolated from the global helper namespace.
111
+ This will then output "Hello there written by Some guy, who writes stuff"
87
112
 
113
+ You can also use `slice` to pass on content from an outer partial:
88
114
 
89
- ## Setup
115
+ ```html+erb
116
+ <%= render "components/card", partial.slice(:title, :byline) %>
117
+ ```
90
118
 
91
- Add to your `Gemfile`:
119
+ ### Appending content from the view into a section
92
120
 
93
- ```ruby
94
- gem "nice_partials"
121
+ Nice Partials supports calling any method on `ActionView::Base`, like the helpers shown here, and then have them auto-append to the section.
122
+
123
+ ```html+erb
124
+ <%= render "components/card" do |partial| %>
125
+ <% partial.title.t ".title" %>
126
+ <% partial.body.render "form", tangible_thing: @tangible_thing %>
127
+ <% partial.image.image_tag image_path("example.jpg"), alt: "An example image" %>
128
+ <% end %>
95
129
  ```
96
130
 
97
- ## Usage
131
+ ### I18n: translating and setting multiple keys at a time
98
132
 
99
- ### When to use Nice Partials
133
+ `partial.t` is a shorthand to translate and assign multiple keys at once:
100
134
 
101
- You only need to use Nice Partials when:
135
+ ```html+erb
136
+ <% partial.t :title, description: :header, byline: "custom.key" %>
102
137
 
103
- - you want to define one or more named content areas in your partial. If you don't have multiple named content areas in your partial, you could just pass your content into the partial using the standard block and `yield` approach.
138
+ # The above is the same as writing:
139
+ <% partial.title t(".title") %>
140
+ <% partial.description t(".header") %>
141
+ <% partial.byline t("custom.key") %>
142
+ ```
104
143
 
105
- - you want to specifically isolate your helper methods for a specific partial.
144
+ ### Capturing options in the rendering block and building HTML tags in the partial
106
145
 
107
- ### Using Nice Partials
146
+ You can pass keyword options to a writer method and they'll be auto-added to `partial.x.options`, like so:
108
147
 
109
- Nice Partials is invoked automatically when you render your partial with a block like so:
148
+ ```html+erb
149
+ <%= render "components/card" do |partial| %>
150
+ <% partial.title "Title content", class: "text-m4", data: { controller: "title" } %>
151
+ <% end %>
152
+
153
+ # app/views/components/_card.html.erb:
154
+ # From the render above `title.options` now contain `{ class: "text-m4", data: { controller: "title" } }`.
155
+ # The options can be output via `<%=` and are automatically run through `tag.attributes` to be converted to HTML attributes.
156
+
157
+ <h1 <%= partial.title.options %>><%= partial.title %></h1> # => <h1 class="text-m4" data-controller="title">Title content</h1>
158
+ ```
159
+
160
+ `partial` also supports auto-generating an element by calling any of Rails' `tag` methods e.g.:
110
161
 
111
162
  ```html+erb
112
- <%= render 'components/card' do |partial| %>
113
- <%= partial.content_for :some_section do %>
114
- Some content!
115
- <% end %>
163
+ # This shorthand gets us the same h1 element from the previous example:
164
+ <%= partial.title.h1 %> # => <h1 class="text-m4" data-controller="title">Title content</h1>
165
+
166
+ # Internally, this is similar to doing:
167
+ <%= tag.h1 partial.title.to_s, partial.title.options %>
168
+ ```
169
+
170
+ ### Yielding tag builders into the rendering block
171
+
172
+ The above example showed sending options from the rendering block into the partial and having it construct elements.
173
+
174
+ But the partial can also prepare tag builders that the rendering block can then extend and finalize:
175
+
176
+ ```html+erb
177
+ <% render "components/card" do |partial|
178
+ <% partial.title { |tag| tag.h1 "Title content" } %>
116
179
  <% end %>
180
+
181
+ # app/views/components/_card.html.erb
182
+ <% partial.title.yield tag.with_options(class: "text-m4", data: { controller: "title" }) %> # => <h1 class="text-m4" data-controller="title">Title content</h1>
117
183
  ```
118
184
 
119
- Now within the partial file itself, you can use `<%= partial.yield :some_section %>` to render whatever content areas you want to be passed into your partial.
185
+ ### Smoother conditional rendering
120
186
 
121
- ### Accessing the content returned from `yield`
187
+ In regular Rails partials it's common to see `content_for?` used to conditionally rendering something. With Nice Partials we can do this:
122
188
 
123
- In a regular Rails partial:
189
+ ```html+erb
190
+ <% if partial.title? %>
191
+ <% partial.title.h1 %>
192
+ <% end %>
193
+ ```
194
+
195
+ But since sections respond to and leverage `present?`, we can shorten the above to:
124
196
 
125
197
  ```html+erb
126
- <%= render 'components/card' do %>
198
+ <% partial.title.presence&.h1 %>
199
+ ```
200
+
201
+ This way no empty h1 element is rendered.
202
+
203
+ ### Accessing the content returned via `partial.yield`
204
+
205
+ To access the inner content lines in the block here, partials have to manually insert a `<%= yield %>` call.
206
+
207
+ ```html+erb
208
+ <%= render "components/card" do %>
127
209
  Some content!
128
210
  Yet more content!
129
211
  <% end %>
130
212
  ```
131
213
 
132
- You can access the inner content lines through what's returned from `yield`:
214
+ With Nice Partials, `partial.yield` returns the same content:
133
215
 
134
216
  ```html+erb
135
- <%# app/views/components/_card.html.erb %>
136
- <%= yield %> # => "Some content!\n\nYet more content!"
217
+ # app/views/components/_card.html.erb
218
+ <%= partial.yield %> # => "Some content!\n\nYet more content!"
219
+ ```
220
+
221
+ ### Referring to the outer partial while rendering another
222
+
223
+ During a rendering block `partial` refers to the outer partial, so you can compose them.
224
+
225
+ ```html+erb
226
+ <% partial.title "Title content" %>
227
+
228
+ <%= render "components/card" do |cp| %>
229
+ <% cp.title partial.title %>
230
+ <% end %>
231
+ ```
232
+
233
+ ### Passing content from one partial to the next
234
+
235
+ If you need to pass content into another partial, `content_from` lets you pass the keys to extract and then a hash to rename keys.
236
+
237
+ ```html+erb
238
+ <%= render "components/card" do |cp| %>
239
+ <% cp.content_from partial, :title, byline: :header %>
240
+ <% end %>
137
241
  ```
138
242
 
139
- With Nice Partials, you can call `partial.yield` without arguments and return the same `"Some content!\n\nYet more content!"`.
243
+ Here, we copied the `partial.title` to `cp.title` and `partial.byline` became `cp.header`.
140
244
 
141
245
  ### Defining and using well isolated helper methods
142
246
 
143
- To minimize the amount of pollution in the global helper namespace, you can use the shared context object to define helper methods specifically for your partials _within your partial_ like so:
247
+ If you want to have helper methods that are available only within your partials, you can call `partial.helpers` directly:
144
248
 
145
249
  ```html+erb
250
+ # app/views/components/_card.html.erb
146
251
  <% partial.helpers do
147
-
148
252
  # references should be a link if the user can drill down, otherwise just a text label.
149
253
  def reference_to(user)
150
254
  # look! this method has access to the scope of the entire view context and all the other helpers that come with it!
@@ -154,17 +258,30 @@ To minimize the amount of pollution in the global helper namespace, you can use
154
258
  object.name
155
259
  end
156
260
  end
157
-
158
261
  end %>
159
- ```
160
262
 
161
- Then later in the partial you can use the helper method like so:
162
-
163
- ```html+erb
263
+ # Later in the partial we can use the method:
164
264
  <td><%= partial.reference_to(user) %></td>
165
265
  ```
166
266
 
167
- ## Development
267
+ ## Sponsored By
268
+
269
+ <a href="https://bullettrain.co" target="_blank">
270
+ <img src="https://github.com/CanCanCommunity/cancancan/raw/develop/logo/bullet_train.png" alt="Bullet Train" width="400"/>
271
+ </a>
272
+ <br/>
273
+ <br/>
274
+
275
+ > Would you like to support Nice Partials development and have your logo featured here? [Reach out!](http://twitter.com/andrewculver)
276
+
277
+
278
+ ## Setup
279
+
280
+ Add to your `Gemfile`:
281
+
282
+ ```ruby
283
+ gem "nice_partials"
284
+ ```
168
285
 
169
286
  ### Testing
170
287
 
@@ -174,4 +291,4 @@ bundle exec rake test
174
291
 
175
292
  ## MIT License
176
293
 
177
- Copyright (C) 2020 Andrew Culver <https://bullettrain.co> and Dom Christie <https://domchristie.co.uk>. Released under the MIT license.
294
+ Copyright (C) 2022 Andrew Culver <https://bullettrain.co> and Dom Christie <https://domchristie.co.uk>. Released under the MIT license.
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
1
  # # #
2
2
  # Get gemspec info
3
3
 
4
+ require "bundler/gem_tasks"
5
+
4
6
  gemspec_file = Dir["*.gemspec"].first
5
7
  gemspec = eval File.read(gemspec_file), binding, gemspec_file
6
8
  info = "#{gemspec.name} | #{gemspec.version} | " \
@@ -26,12 +28,3 @@ desc "#{gemspec.name} | IRB"
26
28
  task :irb do
27
29
  sh "irb -I ./lib -r #{gemspec.name.gsub '-','/'}"
28
30
  end
29
-
30
- # # #
31
- # Run specs
32
-
33
- desc "#{gemspec.name} | Test"
34
- task :test do
35
- sh "for file in test/{**/,}*_test.rb; do ruby -Ilib:test $file; done"
36
- end
37
- task default: :test
@@ -1,6 +1,10 @@
1
1
  require_relative "partial"
2
2
 
3
3
  module NicePartials::Helper
4
+ def nice_partial_with(local_assigns)
5
+ NicePartials::Partial.new(self, local_assigns)
6
+ end
7
+
4
8
  def nice_partial
5
9
  NicePartials::Partial.new(self)
6
10
  end
@@ -48,8 +48,9 @@ module NicePartials::RenderingWithAutoContext
48
48
 
49
49
  # Overrides `ActionView::Helpers::RenderingHelper#render` to push a new `nice_partial`
50
50
  # on the stack, so rendering has a fresh `partial` to store content in.
51
- def render(*)
52
- __partials.prepend nice_partial
51
+ def render(options = {}, locals = {}, &block)
52
+ partial_locals = options.is_a?(Hash) ? options[:locals] : locals
53
+ __partials.prepend nice_partial_with(partial_locals)
53
54
  super
54
55
  ensure
55
56
  __partials.shift
@@ -115,6 +116,6 @@ module NicePartials::CapturingYieldDetection
115
116
  # Note: `<%= yield %>` becomes `yield :layout` with no `render` `block`, though this method assumes a block is passed.
116
117
  def has_capturing_yield?
117
118
  defined?(@has_capturing_yield) ? @has_capturing_yield :
118
- @has_capturing_yield = source.match?(/\byield[\(? ]+(%>|[^:])/)
119
+ @has_capturing_yield = source.match?(/[^\.\b]yield[\(? ]+(%>|[^:])/)
119
120
  end
120
121
  end
@@ -0,0 +1,54 @@
1
+ class NicePartials::Partial::Content
2
+ class Options < Hash
3
+ def initialize(view_context)
4
+ @view_context = view_context
5
+ end
6
+
7
+ def to_s
8
+ @view_context.tag.attributes(self)
9
+ end
10
+ end
11
+
12
+ def initialize(view_context, content = nil)
13
+ @view_context, @options = view_context, Options.new(view_context)
14
+ @content = ActiveSupport::SafeBuffer.new and concat content
15
+ end
16
+ delegate :to_s, :present?, to: :@content
17
+
18
+ # Contains options passed to a partial:
19
+ #
20
+ # <% partial.title class: "post-title" %> # partial.title.options # => { class: "post-title" }
21
+ #
22
+ # # Automatically runs `tag.attributes` when `to_s` is called, e.g.:
23
+ # <h1 <% partial.title.options %>> # => <h1 class="post-title">
24
+ attr_reader :options
25
+
26
+ def write?(content = nil, **new_options, &block)
27
+ @options.merge! new_options
28
+ append content or capture block
29
+ end
30
+
31
+ def write(...)
32
+ write?(...)
33
+ self
34
+ end
35
+
36
+ private
37
+
38
+ def append(content)
39
+ case
40
+ when content.respond_to?(:render_in) then concat content.render_in(@view_context)
41
+ when content.respond_to?(:call) then capture content
42
+ else
43
+ concat content
44
+ end
45
+ end
46
+
47
+ def capture(block)
48
+ append @view_context.capture(&block) if block
49
+ end
50
+
51
+ def concat(string)
52
+ @content << string.to_s if string.present?
53
+ end
54
+ end
@@ -1,43 +1,48 @@
1
- class NicePartials::Partial::Section
2
- def initialize(view_context)
3
- @view_context = view_context
4
- @content = @pending_content = nil
1
+ class NicePartials::Partial::Section < NicePartials::Partial::Content
2
+ def yield(*arguments)
3
+ chunks.each { append @view_context.capture(*arguments, &_1) }
4
+ self
5
5
  end
6
6
 
7
- def content_for(*arguments, &block)
8
- if write_content_for(arguments.first, &block)
9
- nil
10
- else
11
- capture_content_for(*arguments) if pending?
12
- @content
13
- end
7
+ def present?
8
+ chunks.present? || super
14
9
  end
15
10
 
16
- def content?
17
- pending? || @content
18
- end
19
-
20
- private
11
+ undef_method :p # Remove Kernel.p here to pipe through method_missing and hit tag proxy.
21
12
 
22
- def write_content_for(content = nil, &block)
23
- if content && !pending?
24
- concat content
13
+ # Implements our proxying to the `@view_context` or `@view_context.tag`.
14
+ #
15
+ # `@view_context` proxying forwards the message and automatically appends any content, so you can do things like:
16
+ #
17
+ # <% partial.body.render "form", tangible_thing: @tangible_thing %>
18
+ # <% partial.body.link_to @document.name, @document %>
19
+ # <% partial.body.t ".body" %>
20
+ #
21
+ # `@view_context.tag` proxy lets you build bespoke elements based on content and options provided:
22
+ #
23
+ # <% partial.title "Some title content", class: "xl" %> # Write the content and options to the `title`
24
+ # <% partial.title.h2 ", appended" %> # => <h2 class="xl">Some title content, appended</h2>
25
+ #
26
+ # Note that NicePartials don't support deep merging attributes out of the box.
27
+ # For that, bundle https://github.com/seanpdoyle/attributes_and_token_lists
28
+ def method_missing(meth, *arguments, **keywords, &block)
29
+ if meth != :p && @view_context.respond_to?(meth)
30
+ append @view_context.public_send(meth, *arguments, **keywords, &block)
25
31
  else
26
- @pending_content = block if block
32
+ @view_context.tag.public_send(meth, @content + arguments.first.to_s, **options.merge(keywords), &block)
27
33
  end
28
34
  end
35
+ def respond_to_missing?(...) = @view_context.respond_to?(...)
29
36
 
30
- def capture_content_for(*arguments)
31
- concat @view_context.capture(*arguments, &@pending_content)
32
- @pending_content = nil
33
- end
37
+ private
34
38
 
35
- def concat(string)
36
- @content ||= ActiveSupport::SafeBuffer.new
37
- @content << string.to_s if string.present?
39
+ def capture(block)
40
+ if block&.arity&.nonzero?
41
+ chunks << block
42
+ else
43
+ super
44
+ end
38
45
  end
39
46
 
40
- def pending?
41
- @pending_content
42
- end
47
+ def chunks() = @chunks ||= []
43
48
  end
@@ -1,57 +1,111 @@
1
1
  module NicePartials
2
2
  class Partial
3
+ autoload :Content, "nice_partials/partial/content"
3
4
  autoload :Section, "nice_partials/partial/section"
4
5
  autoload :Stack, "nice_partials/partial/stack"
5
6
 
6
7
  delegate_missing_to :@view_context
7
8
 
8
- # <%= render "nice_partial" do |p| %>
9
- # <% p.content_for :title, "Yo" %>
10
- # This content can be accessed through calling `yield`.
11
- # <% end %>
12
- #
13
- # Then in the nice_partial:
14
- # <%= content.content_for :title %> # => "Yo"
15
- # <%= content.output_buffer %> # => "This line is printed to the `output_buffer`."
16
- attr_accessor :output_buffer
17
-
18
- def initialize(view_context)
19
- @view_context = view_context
20
- @contents = Hash.new { |h, k| h[k] = Section.new(@view_context) }
9
+ def initialize(view_context, local_assigns = nil)
10
+ @view_context, @local_assigns = view_context, local_assigns
21
11
  end
22
12
 
23
13
  def yield(*arguments, &block)
24
14
  if arguments.empty?
25
- output_buffer
15
+ @captured_buffer
26
16
  else
27
17
  content_for(*arguments, &block)
28
18
  end
29
19
  end
30
20
 
31
21
  def helpers(&block)
32
- class_eval &block
22
+ self.class.class_eval(&block)
23
+ end
24
+
25
+ # `translate` is a shorthand to set `content_for` with content that's run through
26
+ # the view's `translate`/`t` context.
27
+ #
28
+ # partial.t :title # => partial.content_for :title, t(".title")
29
+ # partial.t title: :section # => partial.content_for :title, t(".section")
30
+ # partial.t title: "some.custom.key" # => partial.content_for :title, t("some.custom.key")
31
+ # partial.t :description, title: :header # Mixing is supported too.
32
+ #
33
+ # Note that `partial.t "some.custom.key"` can't derive a `content_for` name, so an explicit
34
+ # name must be provided e.g. `partial.t title: "some.custom.key"`.
35
+ def translate(*names, **renames)
36
+ names.chain(renames).each do |name, key = name|
37
+ content_for name, @view_context.t(key.is_a?(String) ? key : ".#{key}")
38
+ end
39
+ end
40
+ alias t translate
41
+
42
+ # Allows an inner partial to copy content from an outer partial.
43
+ #
44
+ # Additionally a hash of keys to rename in the new partial context can be passed.
45
+ #
46
+ # First, an outer partial gets some content set:
47
+ # <% partial.title "Hello there" %>
48
+ # <% partial.byline "Somebody" %>
49
+ #
50
+ # Second, a new partial is rendered, but we want to extract the title, byline content but rename the byline key too:
51
+ # <%= render "shared/title" do |cp| %>
52
+ # <% cp.content_from partial, :title, byline: :name %>
53
+ # <% end %>
54
+ #
55
+ # # Third, the contents with any renames are accessible in shared/_title.html.erb:
56
+ # <%= partial.title %> # => "Hello there"
57
+ # <%= partial.name %> # => "Somebody"
58
+ def content_from(partial, *names, **renames)
59
+ names.chain(renames).each { |key, new_key = key| public_send new_key, partial.public_send(key).to_s }
33
60
  end
34
61
 
35
62
  # Similar to Rails' built-in `content_for` except it defers any block execution
36
63
  # and lets you pass arguments into it, like so:
37
64
  #
38
65
  # # Here we store a block with some eventual content…
39
- # <% partial.content_for :title do |tag|
40
- # <%= tag.h1 %>
41
- # <% end %>
66
+ # <% partial.title { |tag| tag.h1 } %>
42
67
  #
43
- # # …which is then invoked with some predefined options later.
44
- # <%= partial.content_for :title, tag.with_options(class: "text-bold") %>
45
- def content_for(name, content = nil, *arguments, &block)
46
- @contents[name].content_for(content, *arguments, &block)
68
+ # # …which we can then yield into with some predefined options later.
69
+ # <%= partial.title.yield tag.with_options(class: "text-bold") %>
70
+ def section(name, content = nil, **options, &block)
71
+ section_from(name).then { _1.write?(content, **options, &block) ? nil : _1 }
72
+ end
73
+
74
+ def section?(name)
75
+ @sections&.dig(name).present?
47
76
  end
77
+ alias content_for? section?
48
78
 
49
- def content_for?(name)
50
- @contents[name].content?
79
+ def content_for(...)
80
+ section(...)&.to_s
81
+ end
82
+
83
+ def slice(*keys)
84
+ keys.index_with { content_for _1 }
51
85
  end
52
86
 
53
87
  def capture(*arguments, &block)
54
- self.output_buffer = @view_context.capture(*arguments, self, &block)
88
+ @captured_buffer = @view_context.capture(*arguments, self, &block)
89
+ end
90
+
91
+ private
92
+
93
+ def section_from(name)
94
+ @sections ||= {} and @sections[name] ||= Section.new(@view_context, @local_assigns&.dig(name))
95
+ end
96
+
97
+ def method_missing(meth, *arguments, **keywords, &block)
98
+ if @view_context.respond_to?(meth)
99
+ @view_context.public_send(meth, *arguments, **keywords, &block)
100
+ else
101
+ define_accessor meth and public_send(meth, *arguments, **keywords, &block)
102
+ end
103
+ end
104
+
105
+ def define_accessor(name)
106
+ name = name.to_s.chomp("?").to_sym
107
+ self.class.define_method(name) { |content = nil, **options, &block| section(name, content, **options, &block) }
108
+ self.class.define_method("#{name}?") { section?(name) }
55
109
  end
56
110
  end
57
111
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NicePartials
4
- VERSION = "0.1.9"
4
+ VERSION = "0.9.0"
5
5
  end
data/lib/nice_partials.rb CHANGED
@@ -4,9 +4,8 @@ require_relative "nice_partials/version"
4
4
 
5
5
  module NicePartials
6
6
  def self.locale_prefix_from(lookup_context, block)
7
- root_paths = lookup_context.view_paths.map(&:path)
8
7
  partial_location = block.source_location.first.dup
9
- root_paths.each { |path| partial_location.gsub!(/^#{path}\//, '') }
8
+ lookup_context.view_paths.each { partial_location.delete_prefix!(_1.path)&.delete_prefix!("/") }
10
9
  partial_location.split('.').first.gsub('/_', '/').gsub('/', '.')
11
10
  end
12
11
  end
@@ -12,9 +12,15 @@ Gem::Specification.new do |gem|
12
12
  gem.homepage = "https://github.com/bullet-train-co/nice_partials"
13
13
  gem.license = "MIT"
14
14
 
15
- gem.files = Dir["{**/}{.*,*}"].select{ |path| File.file?(path) && path !~ /^pkg/ }
16
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ # Specify which files should be added to the gem when it is released.
16
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
17
+ gem.files = Dir.chdir(__dir__) do
18
+ `git ls-files -z`.split("\x0").reject do |f|
19
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
20
+ end
21
+ end
22
+ gem.bindir = "exe"
23
+ gem.executables = gem.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
18
24
  gem.require_paths = ["lib"]
19
25
 
20
26
  gem.required_ruby_version = ">= 2.0"
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nice_partials
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Culver
8
8
  - Dom Christie
9
9
  autorequire:
10
- bindir: bin
10
+ bindir: exe
11
11
  cert_chain: []
12
- date: 2022-08-15 00:00:00.000000000 Z
12
+ date: 2023-01-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionview
@@ -61,8 +61,6 @@ executables: []
61
61
  extensions: []
62
62
  extra_rdoc_files: []
63
63
  files:
64
- - ".gitignore"
65
- - ".travis.yml"
66
64
  - CHANGELOG.md
67
65
  - CODE_OF_CONDUCT.md
68
66
  - Gemfile
@@ -73,25 +71,11 @@ files:
73
71
  - lib/nice_partials/helper.rb
74
72
  - lib/nice_partials/monkey_patch.rb
75
73
  - lib/nice_partials/partial.rb
74
+ - lib/nice_partials/partial/content.rb
76
75
  - lib/nice_partials/partial/section.rb
77
76
  - lib/nice_partials/partial/stack.rb
78
77
  - lib/nice_partials/version.rb
79
- - nice_partials-0.1.8.gem
80
78
  - nice_partials.gemspec
81
- - test/fixtures/_basic.html.erb
82
- - test/fixtures/_card.html.erb
83
- - test/fixtures/_clobberer.html.erb
84
- - test/fixtures/_partial_accessed_in_outer_context.html.erb
85
- - test/fixtures/card_test.html.erb
86
- - test/fixtures/translations/_nice_partials_translated.html.erb
87
- - test/fixtures/translations/_translated.html.erb
88
- - test/fixtures/yields/_object.html.erb
89
- - test/fixtures/yields/_plain.html.erb
90
- - test/fixtures/yields/_plain_nested.html.erb
91
- - test/fixtures/yields/_symbol.html.erb
92
- - test/renderer/translation_test.rb
93
- - test/renderer_test.rb
94
- - test/test_helper.rb
95
79
  homepage: https://github.com/bullet-train-co/nice_partials
96
80
  licenses:
97
81
  - MIT
@@ -111,22 +95,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
95
  - !ruby/object:Gem::Version
112
96
  version: '0'
113
97
  requirements: []
114
- rubygems_version: 3.3.7
98
+ rubygems_version: 3.4.1
115
99
  signing_key:
116
100
  specification_version: 4
117
101
  summary: A little bit of magic to make partials perfect for components.
118
- test_files:
119
- - test/fixtures/_basic.html.erb
120
- - test/fixtures/_card.html.erb
121
- - test/fixtures/_clobberer.html.erb
122
- - test/fixtures/_partial_accessed_in_outer_context.html.erb
123
- - test/fixtures/card_test.html.erb
124
- - test/fixtures/translations/_nice_partials_translated.html.erb
125
- - test/fixtures/translations/_translated.html.erb
126
- - test/fixtures/yields/_object.html.erb
127
- - test/fixtures/yields/_plain.html.erb
128
- - test/fixtures/yields/_plain_nested.html.erb
129
- - test/fixtures/yields/_symbol.html.erb
130
- - test/renderer/translation_test.rb
131
- - test/renderer_test.rb
132
- - test/test_helper.rb
102
+ test_files: []
data/.gitignore DELETED
@@ -1,3 +0,0 @@
1
- Gemfile.lock
2
- /pkg
3
- *~
data/.travis.yml DELETED
@@ -1,19 +0,0 @@
1
- sudo: false
2
- language: ruby
3
-
4
- rvm:
5
- - 3.1
6
- - 3.0
7
- - 2.7
8
- - 2.6
9
- - 2.5
10
- - 2.4
11
- - ruby-head
12
- - jruby-9.2.11.1
13
- - truffleruby-20.2.0
14
-
15
- matrix:
16
- allow_failures:
17
- - rvm: 2.4
18
- - rvm: ruby-head
19
- # fast_finish: true
Binary file
@@ -1 +0,0 @@
1
- <%= partial.yield :message %>
@@ -1,11 +0,0 @@
1
- <div class="card">
2
- <%= partial.yield :image %>
3
- <div class="card-body">
4
- <h5 class="card-title"><%= title %></h5>
5
- <% if partial.content_for? :body %>
6
- <p class="card-text">
7
- <%= partial.content_for :body, tag.with_options(class: "text-bold") %>
8
- </p>
9
- <% end %>
10
- </div>
11
- </div>
@@ -1,3 +0,0 @@
1
- <% p "it's clobbering time" %>
2
- <%# TODO: Remove this file once `p` has been removed post deprecation, but don't change it yet. %>
3
- <%= p.yield :message %>
@@ -1,11 +0,0 @@
1
- <% partial.content_for :original_message, "hello" %>
2
-
3
- <%= render "basic" do |cp| %>
4
- <% cp.content_for :message, partial.content_for(:original_message) %>
5
- <% end %>
6
-
7
- <%= render "basic" do |cp| %>
8
- <% cp.content_for :message, "goodbye" %>
9
- <% end %>
10
-
11
- <span><%= partial.content_for :message %></span>
@@ -1,9 +0,0 @@
1
- <%= render "card", title: "Some Title" do |p| %>
2
- <% p.content_for :body do |tag| %>
3
- <%= tag.p "Lorem Ipsum" %>
4
- <% end %>
5
-
6
- <% p.content_for :image do %>
7
- <img src="https://example.com/image.jpg" />
8
- <% end %>
9
- <% end %>
@@ -1,3 +0,0 @@
1
- <%= render("basic") do |partial| %>
2
- <%= partial.content_for :message, t(".message") %>
3
- <% end %>
@@ -1 +0,0 @@
1
- <%= t ".message" %>
@@ -1 +0,0 @@
1
- <%= yield Hash.new(custom_key: :custom_value) %>
@@ -1 +0,0 @@
1
- <%= yield %>
@@ -1,3 +0,0 @@
1
- <%= render "yields/plain" do %>
2
- <%= yield %>
3
- <% end %>
@@ -1 +0,0 @@
1
- <%= yield :message %>
@@ -1,26 +0,0 @@
1
- require "test_helper"
2
-
3
- module Renderer; end
4
-
5
- class Renderer::TranslationTest < NicePartials::Test
6
- setup do
7
- I18n.backend.store_translations "en", { translations: {
8
- translated: { message: "message" },
9
- nice_partials_translated: { message: "nice_partials" }
10
- } }
11
- end
12
-
13
- teardown { I18n.reload! }
14
-
15
- test "clean translation render" do
16
- render "translations/translated"
17
-
18
- assert_rendered "message"
19
- end
20
-
21
- test "translations insert prefix from originating partial" do
22
- render "translations/nice_partials_translated"
23
-
24
- assert_rendered "nice_partials"
25
- end
26
- end
@@ -1,83 +0,0 @@
1
- require "test_helper"
2
-
3
- class RendererTest < NicePartials::Test
4
- test "render basic nice partial" do
5
- render("basic") { |p| p.content_for :message, "hello from nice partials" }
6
-
7
- assert_rendered "hello from nice partials"
8
- end
9
-
10
- test "render nice partial in card template" do
11
- render(template: "card_test")
12
-
13
- assert_rendered "Some Title"
14
- assert_rendered '<p class="text-bold">Lorem Ipsum</p>'
15
- assert_rendered "https://example.com/image.jpg"
16
- end
17
-
18
- test "accessing partial in outer context won't leak state to inner render" do
19
- render "partial_accessed_in_outer_context"
20
-
21
- assert_rendered "hello"
22
- assert_rendered "goodbye"
23
- assert_rendered "<span></span>"
24
- assert_not_includes rendered, "hellogoodbye"
25
- end
26
-
27
- test "explicit yield without any arguments auto-captures passed block" do
28
- render "yields/plain" do |partial, auto_capture_shouldnt_pass_extra_argument|
29
- assert_kind_of NicePartials::Partial, partial
30
- assert_nil auto_capture_shouldnt_pass_extra_argument
31
- end
32
- end
33
-
34
- test "explicit yield with symbol auto-captures passed block" do
35
- render "yields/symbol" do |partial, auto_capture_shouldnt_pass_extra_argument|
36
- assert_kind_of NicePartials::Partial, partial
37
- assert_nil auto_capture_shouldnt_pass_extra_argument
38
- end
39
- end
40
-
41
- test "explicit yield with object won't auto-capture but make partial available in capture" do
42
- render "yields/object" do |object, partial|
43
- assert_equal Hash.new(custom_key: :custom_value), object
44
- assert_kind_of NicePartials::Partial, partial
45
- end
46
- end
47
-
48
- test "explicit yield without any arguments with nesting" do
49
- render "yields/plain_nested" do
50
- tag.span "Output in outer partial through yield"
51
- end
52
-
53
- assert_rendered "<span>Output in outer partial through yield</span>"
54
- end
55
-
56
- test "output_buffer captures content not written via yield/content_for" do
57
- nice_partial = nil
58
- render "basic" do |p|
59
- nice_partial = p
60
- p.content_for :message, "hello from nice partials"
61
- "Some extra content"
62
- end
63
-
64
- assert_rendered "hello from nice partials"
65
- assert_equal "Some extra content", nice_partial.yield
66
- end
67
-
68
- test "doesn't clobber Kernel.p" do
69
- assert_output "\"it's clobbering time\"\n" do
70
- render("clobberer") { |p| p.content_for :message, "hello from nice partials" }
71
- end
72
-
73
- assert_rendered "hello from nice partials"
74
- end
75
-
76
- test "deprecates top-level access through p method" do
77
- assert_deprecated /p is deprecated and will be removed from nice_partials \d/, NicePartials::DEPRECATOR do
78
- assert_output "\"it's clobbering time\"\n" do
79
- render("clobberer") { |p| p.content_for :message, "hello from nice partials" }
80
- end
81
- end
82
- end
83
- end
data/test/test_helper.rb DELETED
@@ -1,17 +0,0 @@
1
- require "active_support"
2
- require "active_support/testing/autorun"
3
- require "action_controller"
4
- require "action_view"
5
- require "action_view/test_case"
6
-
7
- require "nice_partials"
8
-
9
- class NicePartials::Test < ActionView::TestCase
10
- TestController.view_paths << "test/fixtures"
11
-
12
- private
13
-
14
- def assert_rendered(matcher)
15
- assert_match matcher, rendered
16
- end
17
- end