futurism 0.3.3 → 0.5.2

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: '09ba45b906e8c0f223e8da6793131f6eb96acad018116c32584d033392f1fe3b'
4
- data.tar.gz: 178166e14d83fab48dcb6296d7dc9b412762ca228e201d5d97e7c70c08d1d1e1
3
+ metadata.gz: 313e2de708762f264a6b0b647e9ae7e1eff5f2463e4ba852e95696ffd8706fb3
4
+ data.tar.gz: 73f61a471267578dba1e2460cb0c388d96bdf46a52bcae5a047e9c729fe76095
5
5
  SHA512:
6
- metadata.gz: 29c7a409b86e1e29eac2feadc4e01d2042071e8daa196849bc676d400b2d59f4b4b7548fd4c3c76d45a262cb0f57b80adc0bde56812a2bcbc394eefd56f50c1c
7
- data.tar.gz: f85ea36325a9a4aecb63a0c8a47636db1cf4e7573907e558cb46203bfbcd87b583d52efd78b2c6bffe20040a44e4cbad9cd4bf269741a7d011966d427518ec55
6
+ metadata.gz: f205ad83640359aaaf72414069bd8a287faf5177b8ec320298c39b82db75eedab9799c45cbff003478804f432d033fc6fe65522ca1de7a5932601fe387c7e8a2
7
+ data.tar.gz: 56b67210ed5b229298e07216d5b920b358c43758d825ce6dc906faf4a2289dc20feafb2aa8e25ff846802c8ca6bc8fce6061c20f210b1a37690d5798349cac7d
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Futurism
2
2
  [![Twitter follow](https://img.shields.io/twitter/follow/julian_rubisch?style=social)](https://twitter.com/julian_rubisch)
3
3
  <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
4
- [![All Contributors](https://img.shields.io/badge/all_contributors-10-orange.svg?style=flat-square)](#contributors-)
4
+ [![All Contributors](https://img.shields.io/badge/all_contributors-13-orange.svg?style=flat-square)](#contributors-)
5
5
  <!-- ALL-CONTRIBUTORS-BADGE:END -->
6
6
  Lazy-load Rails partials via CableReady
7
7
 
@@ -10,6 +10,26 @@ Lazy-load Rails partials via CableReady
10
10
  <img src="https://user-images.githubusercontent.com/4352208/88374198-9e6f3500-cd99-11ea-804b-0216ed320eff.jpg" alt="birmingham-museums-trust-GrvC6MI-z4w-unsplash" width="50%" align="center"/>
11
11
  <span>Photo by <a href="https://unsplash.com/@birminghammuseumstrust?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Birmingham Museums Trust</a> on <a href="https://unsplash.com/s/photos/futurism?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></span>
12
12
 
13
+ ## Table of Contents
14
+
15
+ - [Table of Contents](#table-of-contents)
16
+ - [Facts](#facts)
17
+ - [Browser Support](#browser-support)
18
+ - [Usage](#usage)
19
+ - [API](#api)
20
+ - [Resource](#resource)
21
+ - [Explicit Partial](#explicit-partial)
22
+ - [HTML Options](#html-options)
23
+ - [Eager Loading](#eager-loading)
24
+ - [Events](#events)
25
+ - [Installation](#installation)
26
+ - [Manual Installation](#manual-installation)
27
+ - [Authentication](#authentication)
28
+ - [Gotchas](#gotchas)
29
+ - [Contributing](#contributing)
30
+ - [License](#license)
31
+ - [Contributors](#contributors)
32
+
13
33
  ## Facts
14
34
  - only one dependency: CableReady
15
35
  - bundle size (without CableReady) is around [~1.04kB](https://bundlephobia.com/result?p=@minthesize/futurism@0.1.3)
@@ -121,6 +141,19 @@ This will output the following:
121
141
  </tr>
122
142
  ```
123
143
 
144
+ ### Eager Loading
145
+ It may sound surprising to support eager loading in a lazy loading library :joy:, but there's a quite simple use case:
146
+
147
+ Suppose you have some hidden interactive portion of your page, like a tab or dropdown. You don't want its content to block the initial page load, but once that is done, you occasionally don't want to wait for the element to become visible and trigger the `IntersectionObserver`, you want to lazy load its contents right after it's added to the DOM.
148
+
149
+ Futurism makes that dead simple:
150
+
151
+ ```erb
152
+ <%= futurize 'some_tab', eager: true, extends: :tr do %>
153
+ <div class="placeholder"</td>
154
+ <% end %>
155
+ ```
156
+
124
157
  ## Events
125
158
 
126
159
  Once your futurize element has been rendered, the `futurize:appeared` custom event will be called.
@@ -155,7 +188,7 @@ $ bin/yarn add @minthesize/futurism
155
188
  In your `app/javascript/channels/index.js`, add the following
156
189
 
157
190
  ```js
158
- import * as Futurism from '@minthesize/futurism''
191
+ import * as Futurism from '@minthesize/futurism'
159
192
 
160
193
  import consumer from './consumer'
161
194
 
@@ -163,6 +196,39 @@ Futurism.initializeElements()
163
196
  Futurism.createSubscription(consumer)
164
197
  ```
165
198
 
199
+ ## Authentication
200
+ For authentication, you can rely on ActionCable identifiers, for example, if you use Devise:
201
+
202
+ ```ruby
203
+ module ApplicationCable
204
+ class Connection < ActionCable::Connection::Base
205
+ identified_by :current_user
206
+
207
+ def connect
208
+ self.current_user = env["warden"].user || reject_unauthorized_connection
209
+ end
210
+ end
211
+ end
212
+ ```
213
+
214
+ The [Stimulus Reflex Docs](https://docs.stimulusreflex.com/authentication) have an excellent section about all sorts of authentication.
215
+
216
+ ## Gotchas
217
+
218
+ ### ActiveStorage URLs aren't correct in development
219
+
220
+ Out of the box, Rails will prefix generated urls with `http://example.org` rather than `http://localhost`, much like ActionMailer. To amend this, add
221
+
222
+ ```ruby
223
+ # config/environments/development.rb
224
+ config.action_controller.default_url_options = {host: "localhost", port: 3000}
225
+
226
+ # config/environments/production.rb
227
+ config.action_controller.default_url_options = {host: "mysite.com"}
228
+ ```
229
+
230
+ to your environments.
231
+
166
232
  ## Contributing
167
233
 
168
234
  ## License
@@ -182,13 +248,17 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
182
248
  <td align="center"><a href="https://ParamagicDev.github.io/portfolio"><img src="https://avatars2.githubusercontent.com/u/26425882?v=4" width="100px;" alt=""/><br /><sub><b>Konnor Rogers</b></sub></a><br /><a href="https://github.com/julianrubisch/futurism/commits?author=ParamagicDev" title="Code">💻</a></td>
183
249
  <td align="center"><a href="https://www.andrewm.codes"><img src="https://avatars1.githubusercontent.com/u/18423853?v=4" width="100px;" alt=""/><br /><sub><b>Andrew Mason</b></sub></a><br /><a href="#maintenance-andrewmcodes" title="Maintenance">🚧</a></td>
184
250
  <td align="center"><a href="http://gorails.com"><img src="https://avatars1.githubusercontent.com/u/67093?v=4" width="100px;" alt=""/><br /><sub><b>Chris Oliver</b></sub></a><br /><a href="https://github.com/julianrubisch/futurism/commits?author=excid3" title="Code">💻</a> <a href="https://github.com/julianrubisch/futurism/pulls?q=is%3Apr+reviewed-by%3Aexcid3" title="Reviewed Pull Requests">👀</a></td>
185
- <td align="center"><a href="https://github.com/leastbad"><img src="https://avatars2.githubusercontent.com/u/38150464?v=4" width="100px;" alt=""/><br /><sub><b>leastbad</b></sub></a><br /><a href="https://github.com/julianrubisch/futurism/commits?author=leastbad" title="Code">💻</a></td>
251
+ <td align="center"><a href="https://github.com/leastbad"><img src="https://avatars2.githubusercontent.com/u/38150464?v=4" width="100px;" alt=""/><br /><sub><b>leastbad</b></sub></a><br /><a href="https://github.com/julianrubisch/futurism/commits?author=leastbad" title="Code">💻</a> <a href="https://github.com/julianrubisch/futurism/pulls?q=is%3Apr+reviewed-by%3Aleastbad" title="Reviewed Pull Requests">👀</a></td>
186
252
  <td align="center"><a href="http://code.digimonkey.com"><img src="https://avatars0.githubusercontent.com/u/74207?v=4" width="100px;" alt=""/><br /><sub><b>M. E. Patterson</b></sub></a><br /><a href="https://github.com/julianrubisch/futurism/issues?q=author%3Amepatterson" title="Bug reports">🐛</a></td>
187
253
  </tr>
188
254
  <tr>
189
255
  <td align="center"><a href="http://fractaledmind.com"><img src="https://avatars3.githubusercontent.com/u/5077225?v=4" width="100px;" alt=""/><br /><sub><b>Stephen Margheim</b></sub></a><br /><a href="https://github.com/julianrubisch/futurism/commits?author=fractaledmind" title="Code">💻</a></td>
190
256
  <td align="center"><a href="http://hass.codes"><img src="https://avatars2.githubusercontent.com/u/1064205?v=4" width="100px;" alt=""/><br /><sub><b>Hassanin Ahmed</b></sub></a><br /><a href="https://github.com/julianrubisch/futurism/commits?author=sas1ni69" title="Code">💻</a></td>
191
257
  <td align="center"><a href="https://marcoroth.dev"><img src="https://avatars2.githubusercontent.com/u/6411752?v=4" width="100px;" alt=""/><br /><sub><b>Marco Roth</b></sub></a><br /><a href="https://github.com/julianrubisch/futurism/commits?author=marcoroth" title="Code">💻</a></td>
258
+ <td align="center"><a href="https://viedit.com"><img src="https://avatars1.githubusercontent.com/u/49990587?v=4" width="100px;" alt=""/><br /><sub><b>Viedit com</b></sub></a><br /><a href="https://github.com/julianrubisch/futurism/commits?author=vieditcom" title="Documentation">📖</a></td>
259
+ <td align="center"><a href="http://scottbarrow.ca"><img src="https://avatars2.githubusercontent.com/u/5571736?v=4" width="100px;" alt=""/><br /><sub><b>Scott Barrow</b></sub></a><br /><a href="https://github.com/julianrubisch/futurism/commits?author=scottbarrow" title="Code">💻</a></td>
260
+ <td align="center"><a href="http://domchristie.co.uk"><img src="https://avatars0.githubusercontent.com/u/111734?v=4" width="100px;" alt=""/><br /><sub><b>Dom Christie</b></sub></a><br /><a href="https://github.com/julianrubisch/futurism/pulls?q=is%3Apr+reviewed-by%3Adomchristie" title="Reviewed Pull Requests">👀</a></td>
261
+ <td align="center"><a href="http://www.rickychilcott.com"><img src="https://avatars1.githubusercontent.com/u/445759?v=4" width="100px;" alt=""/><br /><sub><b>Ricky Chilcott</b></sub></a><br /><a href="https://github.com/julianrubisch/futurism/pulls?q=is%3Apr+reviewed-by%3Arickychilcott" title="Reviewed Pull Requests">👀</a></td>
192
262
  </tr>
193
263
  </table>
194
264
 
@@ -2,26 +2,46 @@ module Futurism
2
2
  class Channel < ActionCable::Channel::Base
3
3
  include CableReady::Broadcaster
4
4
 
5
+ def stream_name
6
+ ids = connection.identifiers.map { |identifier| send(identifier).try(:id) || send(identifier) }
7
+ [
8
+ params[:channel],
9
+ ids.select(&:present?).join(";")
10
+ ].select(&:present?).join(":")
11
+ end
12
+
5
13
  def subscribed
6
- stream_from "Futurism::Channel"
14
+ stream_from stream_name
7
15
  end
8
16
 
9
17
  def receive(data)
10
- resources = data["signed_params"].map { |signed_params|
11
- [signed_params, Rails.application.message_verifier("futurism").verify(signed_params)]
12
- }
18
+ resources = data.fetch_values("signed_params", "sgids") { |key| [nil] }.transpose
13
19
 
14
20
  new_env = connection.env.merge(ApplicationController.renderer.instance_variable_get(:@env))
15
21
  ApplicationController.renderer.instance_variable_set(:@env, new_env)
16
22
 
17
- resources.each do |signed_params, resource|
18
- cable_ready["Futurism::Channel"].outer_html(
19
- selector: "[data-signed-params='#{signed_params}']",
20
- html: ApplicationController.render(resource)
23
+ resources.each do |signed_params, sgid|
24
+ selector = "[data-signed-params='#{signed_params}']"
25
+ selector << "[data-sgid='#{sgid}']" if sgid.present?
26
+ cable_ready[stream_name].outer_html(
27
+ selector: selector,
28
+ html: ApplicationController.render(resource(signed_params: signed_params, sgid: sgid))
21
29
  )
22
30
  end
23
31
 
24
32
  cable_ready.broadcast
25
33
  end
34
+
35
+ private
36
+
37
+ def resource(signed_params:, sgid:)
38
+ return GlobalID::Locator.locate_signed(sgid) if sgid.present?
39
+
40
+ Rails
41
+ .application
42
+ .message_verifier("futurism")
43
+ .verify(signed_params)
44
+ .deep_transform_values { |value| value.is_a?(String) && value.start_with?("gid://") ? GlobalID::Locator.locate(value) : value }
45
+ end
26
46
  end
27
47
  end
@@ -2,25 +2,46 @@ module Futurism
2
2
  class Channel < ActionCable::Channel::Base
3
3
  include CableReady::Broadcaster
4
4
 
5
+ def stream_name
6
+ ids = connection.identifiers.map { |identifier| send(identifier).try(:id) || send(identifier) }
7
+ [
8
+ params[:channel],
9
+ ids.select(&:present?).join(";")
10
+ ].select(&:present?).join(":")
11
+ end
12
+
5
13
  def subscribed
6
- stream_from "Futurism::Channel"
14
+ stream_from stream_name
7
15
  end
8
16
 
9
17
  def receive(data)
10
- resources = data["signed_params"].map { |signed_params|
11
- [signed_params, Rails.application.message_verifier("futurism").verify(signed_params)]
12
- }
18
+ resources = data.fetch_values("signed_params", "sgids") { |key| [nil] }.transpose
13
19
 
14
- ApplicationController.renderer.instance_variable_set(:@env, connection.env)
20
+ new_env = connection.env.merge(ApplicationController.renderer.instance_variable_get(:@env))
21
+ ApplicationController.renderer.instance_variable_set(:@env, new_env)
15
22
 
16
- resources.each do |signed_params, resource|
17
- cable_ready["Futurism::Channel"].outer_html(
18
- selector: "[data-signed-params='#{signed_params}']",
19
- html: ApplicationController.render(resource)
23
+ resources.each do |signed_params, sgid|
24
+ selector = "[data-signed-params='#{signed_params}']"
25
+ selector << "[data-sgid='#{sgid}']" if sgid.present?
26
+ cable_ready[stream_name].outer_html(
27
+ selector: selector,
28
+ html: ApplicationController.render(resource(signed_params: signed_params, sgid: sgid))
20
29
  )
21
30
  end
22
31
 
23
32
  cable_ready.broadcast
24
33
  end
34
+
35
+ private
36
+
37
+ def resource(signed_params:, sgid:)
38
+ return GlobalID::Locator.locate_signed(sgid) if sgid.present?
39
+
40
+ Rails
41
+ .application
42
+ .message_verifier("futurism")
43
+ .verify(signed_params)
44
+ .deep_transform_values { |value| value.is_a?(String) && value.start_with?("gid://") ? GlobalID::Locator.locate(value) : value }
45
+ end
25
46
  end
26
47
  end
@@ -6,7 +6,8 @@ module Futurism
6
6
  if records_or_string.is_a?(ActiveRecord::Base) || records_or_string.is_a?(ActiveRecord::Relation)
7
7
  futurize_active_record(records_or_string, extends: extends, placeholder: placeholder, **options)
8
8
  elsif records_or_string.is_a?(String)
9
- futurize_with_options(extends: extends, partial: records_or_string, locals: options, placeholder: placeholder)
9
+ html_options = options.delete(:html_options)
10
+ futurize_with_options(extends: extends, placeholder: placeholder, partial: records_or_string, locals: options, html_options: html_options)
10
11
  else
11
12
  futurize_with_options(extends: extends, placeholder: placeholder, **options)
12
13
  end
@@ -15,37 +16,70 @@ module Futurism
15
16
  def futurize_with_options(extends:, placeholder:, **options)
16
17
  collection = options.delete(:collection)
17
18
  if collection.nil?
18
- render_element(extends: extends, placeholder: placeholder, options: options)
19
+ Element.new(extends: extends, placeholder: placeholder, options: options).render
19
20
  else
20
21
  collection_class_name = collection.klass.name
21
22
  as = options.delete(:as) || collection_class_name.downcase
22
23
  collection.map { |record|
23
- render_element(extends: extends, placeholder: placeholder, options: options.deep_merge(locals: {as.to_sym => record}))
24
+ Element.new(extends: extends, placeholder: placeholder, options: options.deep_merge(locals: {as.to_sym => record})).render
24
25
  }.join.html_safe
25
26
  end
26
27
  end
27
28
 
28
29
  def futurize_active_record(records, extends:, placeholder:, **options)
29
30
  Array(records).map { |record|
30
- render_element(extends: extends, placeholder: placeholder, options: options.merge(model: record))
31
+ Element.new(extends: extends, options: options.merge(model: record), placeholder: placeholder).render
31
32
  }.join.html_safe
32
33
  end
33
34
 
34
- def render_element(extends:, options:, placeholder:)
35
- html_options = options.delete(:html_options) || {}
36
- model_or_options = options.delete(:model) || options
37
- case extends
38
- when :li
39
- content_tag :li, placeholder, {data: {signed_params: futurism_signed_params(model_or_options)}, is: "futurism-li"}.merge(html_options)
40
- when :tr
41
- content_tag :tr, placeholder, {data: {signed_params: futurism_signed_params(model_or_options)}, is: "futurism-table-row"}.merge(html_options)
42
- else
43
- content_tag :"futurism-element", placeholder, {data: {signed_params: futurism_signed_params(model_or_options)}}.merge(html_options)
35
+ # wraps functionality for rendering a futurism element
36
+ class Element
37
+ include ActionView::Helpers
38
+
39
+ attr_reader :extends, :placeholder, :html_options, :data_attributes, :model, :options, :eager
40
+
41
+ def initialize(extends:, placeholder:, options:)
42
+ @extends = extends
43
+ @placeholder = placeholder
44
+ @eager = options.delete(:eager)
45
+ @html_options = options.delete(:html_options) || {}
46
+ @data_attributes = html_options.fetch(:data, {}).except(:sgid, :signed_params)
47
+ @model = options.delete(:model)
48
+ @options = data_attributes.any? ? options.merge(data: data_attributes) : options
44
49
  end
45
- end
46
50
 
47
- def futurism_signed_params(params)
48
- Rails.application.message_verifier("futurism").generate(params)
51
+ def dataset
52
+ data_attributes.merge({
53
+ signed_params: signed_params,
54
+ sgid: model && model.to_sgid.to_s,
55
+ eager: eager.presence
56
+ })
57
+ end
58
+
59
+ def render
60
+ case extends
61
+ when :li
62
+ content_tag :li, placeholder, html_options.deep_merge({data: dataset, is: "futurism-li"})
63
+ when :tr
64
+ content_tag :tr, placeholder, html_options.deep_merge({data: dataset, is: "futurism-table-row"})
65
+ else
66
+ content_tag :"futurism-element", placeholder, html_options.deep_merge({data: dataset})
67
+ end
68
+ end
69
+
70
+ def transformed_options
71
+ require_relative "shims/deep_transform_values" unless options.respond_to? :deep_transform_values
72
+
73
+ options.deep_transform_values do |value|
74
+ value.is_a?(ActiveRecord::Base) && !value.new_record? ? value.to_global_id.to_s : value
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ def signed_params
81
+ Rails.application.message_verifier("futurism").generate(transformed_options)
82
+ end
49
83
  end
50
84
  end
51
85
  end
@@ -1,13 +1,83 @@
1
- module FuturismHelper
2
- def futurize(records, extends: :tr, &block)
3
- placeholder = capture(&block)
4
- Array(records).map { |record|
5
- case extends
6
- when :tr
7
- content_tag :tr, placeholder, data: { sgid: record.to_sgid.to_s }, is: "futurism-table-row"
1
+ module Futurism
2
+ module Helpers
3
+ def futurize(records_or_string = nil, extends:, **options, &block)
4
+ placeholder = capture(&block)
5
+
6
+ if records_or_string.is_a?(ActiveRecord::Base) || records_or_string.is_a?(ActiveRecord::Relation)
7
+ futurize_active_record(records_or_string, extends: extends, placeholder: placeholder, **options)
8
+ elsif records_or_string.is_a?(String)
9
+ html_options = options.delete(:html_options)
10
+ futurize_with_options(extends: extends, placeholder: placeholder, partial: records_or_string, locals: options, html_options: html_options)
8
11
  else
9
- content_tag :"futurism-element", placeholder, data: { sgid: record.to_sgid.to_s }
12
+ futurize_with_options(extends: extends, placeholder: placeholder, **options)
10
13
  end
11
- }.join.html_safe
14
+ end
15
+
16
+ def futurize_with_options(extends:, placeholder:, **options)
17
+ collection = options.delete(:collection)
18
+ if collection.nil?
19
+ Element.new(extends: extends, placeholder: placeholder, options: options).render
20
+ else
21
+ collection_class_name = collection.klass.name
22
+ as = options.delete(:as) || collection_class_name.downcase
23
+ collection.map { |record|
24
+ Element.new(extends: extends, placeholder: placeholder, options: options.deep_merge(locals: {as.to_sym => record})).render
25
+ }.join.html_safe
26
+ end
27
+ end
28
+
29
+ def futurize_active_record(records, extends:, placeholder:, **options)
30
+ Array(records).map { |record|
31
+ Element.new(extends: extends, options: options.merge(model: record), placeholder: placeholder).render
32
+ }.join.html_safe
33
+ end
34
+
35
+ # wraps functionality for rendering a futurism element
36
+ class Element
37
+ include ActionView::Helpers
38
+
39
+ attr_reader :extends, :placeholder, :html_options, :data_attributes, :model, :options
40
+
41
+ def initialize(extends:, placeholder:, options:)
42
+ @extends = extends
43
+ @placeholder = placeholder
44
+ @html_options = options.delete(:html_options) || {}
45
+ @data_attributes = html_options.fetch(:data, {}).except(:sgid, :signed_params)
46
+ @model = options.delete(:model)
47
+ @options = data_attributes.any? ? options.merge(data: data_attributes) : options
48
+ end
49
+
50
+ def dataset
51
+ data_attributes.merge({
52
+ signed_params: signed_params,
53
+ sgid: model && model.to_sgid.to_s
54
+ })
55
+ end
56
+
57
+ def render
58
+ case extends
59
+ when :li
60
+ content_tag :li, placeholder, html_options.deep_merge({data: dataset, is: "futurism-li"})
61
+ when :tr
62
+ content_tag :tr, placeholder, html_options.deep_merge({data: dataset, is: "futurism-table-row"})
63
+ else
64
+ content_tag :"futurism-element", placeholder, html_options.deep_merge({data: dataset})
65
+ end
66
+ end
67
+
68
+ def transformed_options
69
+ require_relative "shims/deep_transform_values" unless options.respond_to? :deep_transform_values
70
+
71
+ options.deep_transform_values do |value|
72
+ value.is_a?(ActiveRecord::Base) && !value.new_record? ? value.to_global_id.to_s : value
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ def signed_params
79
+ Rails.application.message_verifier("futurism").generate(transformed_options)
80
+ end
81
+ end
12
82
  end
13
83
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Hash
4
+ # Returns a new hash with all values converted by the block operation.
5
+ # This includes the values from the root hash and from all
6
+ # nested hashes and arrays.
7
+ #
8
+ # hash = { person: { name: 'Rob', age: '28' } }
9
+ #
10
+ # hash.deep_transform_values{ |value| value.to_s.upcase }
11
+ # # => {person: {name: "ROB", age: "28"}}
12
+ def deep_transform_values(&block)
13
+ _deep_transform_values_in_object(self, &block)
14
+ end
15
+
16
+ # Destructively converts all values by using the block operation.
17
+ # This includes the values from the root hash and from all
18
+ # nested hashes and arrays.
19
+ def deep_transform_values!(&block)
20
+ _deep_transform_values_in_object!(self, &block)
21
+ end
22
+
23
+ private
24
+
25
+ # Support methods for deep transforming nested hashes and arrays.
26
+ def _deep_transform_values_in_object(object, &block)
27
+ case object
28
+ when Hash
29
+ object.transform_values { |value| _deep_transform_values_in_object(value, &block) }
30
+ when Array
31
+ object.map { |e| _deep_transform_values_in_object(e, &block) }
32
+ else
33
+ yield(object)
34
+ end
35
+ end
36
+
37
+ def _deep_transform_values_in_object!(object, &block)
38
+ case object
39
+ when Hash
40
+ object.transform_values! { |value| _deep_transform_values_in_object!(value, &block) }
41
+ when Array
42
+ object.map! { |e| _deep_transform_values_in_object!(e, &block) }
43
+ else
44
+ yield(object)
45
+ end
46
+ end
47
+ end
@@ -1,3 +1,3 @@
1
1
  module Futurism
2
- VERSION = "0.3.3"
2
+ VERSION = "0.5.2"
3
3
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: futurism
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julian Rubisch
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-30 00:00:00.000000000 Z
11
+ date: 2020-10-06 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: appraisal
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -128,14 +142,14 @@ dependencies:
128
142
  requirements:
129
143
  - - ">="
130
144
  - !ruby/object:Gem::Version
131
- version: '6'
145
+ version: '5.2'
132
146
  type: :runtime
133
147
  prerelease: false
134
148
  version_requirements: !ruby/object:Gem::Requirement
135
149
  requirements:
136
150
  - - ">="
137
151
  - !ruby/object:Gem::Version
138
- version: '6'
152
+ version: '5.2'
139
153
  - !ruby/object:Gem::Dependency
140
154
  name: cable_ready
141
155
  requirement: !ruby/object:Gem::Requirement
@@ -170,6 +184,7 @@ files:
170
184
  - lib/futurism/engine.rb
171
185
  - lib/futurism/helpers.rb
172
186
  - lib/futurism/helpers.rb~
187
+ - lib/futurism/shims/deep_transform_values.rb
173
188
  - lib/futurism/version.rb
174
189
  - lib/tasks/futurism_tasks.rake
175
190
  - lib/tasks/futurism_tasks.rake~