futurism 0.5.4 → 0.8.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: 4e79c03c8d157585784ab3e4f48d2660100acad4e317aa378cdfa94a0c5a3fb9
4
- data.tar.gz: 5036367ba790b660ef6230e6155192cfedd65973fa65e00fd7b53f071f8a6ae8
3
+ metadata.gz: 75dd023300659792f3dd9e114727b0003204ed6b2e9e990413fcc1ca82971fba
4
+ data.tar.gz: b73280cb140625612fc5e7188e301f98e5be0eb19e7359c7786fae8b4a8f4b8c
5
5
  SHA512:
6
- metadata.gz: cf2acd22c20fd40897b6caed2ad897eec3cc98f7ea1fbd9ab31ea19cf276cfa2f94f04ef87a16fe8c68ec03dab1e4e5832a1f4026fe269c58b8114dd1aecb54a
7
- data.tar.gz: bda0591fb9174ebd6499839be5bfdb8512d8c7c110b9af837f6d8425eb6e9180384234fd493df1945fe51c021c2a0ab0e8ee5537238babd00617ca9bf4a16d8b
6
+ metadata.gz: c9285da73bb00137f7aea08b2171d370b032681abd79b8d37e652b1aef546159a2d568ecc695ecaeb0a7f3a8f4a74abb0a6a310dca9969021923d4590c0fd03b
7
+ data.tar.gz: ae425d91dcae19d847105b5633a0f0b434166d5cb45f9aed14bfccb2a07cc9661594c2a814d072b541b30d7b401c6273919e6c199ffcdb38c146d6fc8f8a6a74
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-13-orange.svg?style=flat-square)](#contributors-)
4
+ [![All Contributors](https://img.shields.io/badge/all_contributors-15-orange.svg?style=flat-square)](#contributors-)
5
5
  <!-- ALL-CONTRIBUTORS-BADGE:END -->
6
6
  Lazy-load Rails partials via CableReady
7
7
 
@@ -33,7 +33,7 @@ Lazy-load Rails partials via CableReady
33
33
 
34
34
  ## Facts
35
35
  - only one dependency: CableReady
36
- - bundle size (without CableReady) is around [~1.04kB](https://bundlephobia.com/result?p=@minthesize/futurism@0.1.3)
36
+ - bundle size (without CableReady) is around [~2.46kB](https://bundlephobia.com/result?p=@minthesize/futurism@0.7.2)
37
37
 
38
38
  ### Browser Support
39
39
 
@@ -124,6 +124,22 @@ Collection rendering is also possible:
124
124
  <% end %>
125
125
  ```
126
126
 
127
+ #### Specifying Controller to Render
128
+
129
+ You can also pass in the controller that will be used to render the partial.
130
+
131
+ ```erb
132
+ <%= futurize partial: "items/card", collection: @cards, controller: MyController, extends: :div do %>
133
+ <div class="spinner"></div>
134
+ <% end %>
135
+ ```
136
+
137
+ By default (i.e. not passing in a value), futurize will use `ApplicationController`, but you may override by setting the Futurism default controller in an initializer, for example `config/initializers/futurism.rb`.
138
+
139
+ ```ruby
140
+ Futurism.default_controller = "MyController" # to avoid the controller from trying to autoload at boot, provide as a string
141
+ ```
142
+
127
143
  ### HTML Options
128
144
 
129
145
  You can pass a hash of attribute/value pairs which will be mixed into the HTML markup for the placeholder element. This is important for layouts that require elements to have dimensionality. For example, many scripts calculate size based on element height and width. This option ensures that your elements have integrity, even if they are gone before you see them.
@@ -241,6 +257,39 @@ to your environments.
241
257
 
242
258
  ## Contributing
243
259
 
260
+ ### Get local environment setup
261
+
262
+ Below are a set of instructions that may help you get a local development environment working
263
+
264
+ ```shell
265
+ # Get the gem/npm package source locally
266
+ git clone futurism
267
+ cd futurism/javascript
268
+ yarn install # install all of the npm package's dependencies
269
+ yarn link # set the local machine's futurism npm package's lookup to this local path
270
+
271
+ # Setup a sample project, use the information below directly or use your own project
272
+ git clone https://github.com/leastbad/stimulus_reflex_harness.git
273
+ cd stimulus_reflex_harness
274
+ git checkout futurism
275
+ # Edit Gemfile to point point to local gem (e.g. `gem "futurism", path: "../futurism"`)
276
+ # yarn link @minthesize/futurism
277
+
278
+
279
+ # Do your work, Submit PR, Profit!
280
+
281
+
282
+ # To stop using your local version of futurism
283
+ # change your Gemfile back to the published (e.g. `gem "futurism"`)
284
+ cd path/to/futurism/javascript
285
+ # Stop using the local npm package
286
+ yarn unlink
287
+
288
+ # Instruct your project to reinstall the published version of the npm package
289
+ cd path/to/project
290
+ yarn install --force
291
+ ```
292
+
244
293
  ## License
245
294
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
246
295
 
@@ -253,27 +302,31 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
253
302
  <!-- markdownlint-disable -->
254
303
  <table>
255
304
  <tr>
256
- <td align="center"><a href="http://www.julianrubisch.at"><img src="https://avatars0.githubusercontent.com/u/4352208?v=4" width="100px;" alt=""/><br /><sub><b>Julian Rubisch</b></sub></a><br /><a href="https://github.com/julianrubisch/futurism/commits?author=julianrubisch" title="Code">💻</a></td>
257
- <td align="center"><a href="https://github.com/darkrubyist"><img src="https://avatars2.githubusercontent.com/u/11207292?v=4" width="100px;" alt=""/><br /><sub><b>darkrubyist</b></sub></a><br /><a href="https://github.com/julianrubisch/futurism/commits?author=darkrubyist" title="Code">💻</a> <a href="https://github.com/julianrubisch/futurism/commits?author=darkrubyist" title="Documentation">📖</a></td>
258
- <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>
259
- <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>
260
- <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>
261
- <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>
262
- <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>
305
+ <td align="center"><a href="http://www.julianrubisch.at"><img src="https://avatars0.githubusercontent.com/u/4352208?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Julian Rubisch</b></sub></a><br /><a href="https://github.com/julianrubisch/futurism/commits?author=julianrubisch" title="Code">💻</a></td>
306
+ <td align="center"><a href="https://github.com/darkrubyist"><img src="https://avatars2.githubusercontent.com/u/11207292?v=4?s=100" width="100px;" alt=""/><br /><sub><b>darkrubyist</b></sub></a><br /><a href="https://github.com/julianrubisch/futurism/commits?author=darkrubyist" title="Code">💻</a> <a href="https://github.com/julianrubisch/futurism/commits?author=darkrubyist" title="Documentation">📖</a></td>
307
+ <td align="center"><a href="https://ParamagicDev.github.io/portfolio"><img src="https://avatars2.githubusercontent.com/u/26425882?v=4?s=100" 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>
308
+ <td align="center"><a href="https://www.andrewm.codes"><img src="https://avatars1.githubusercontent.com/u/18423853?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andrew Mason</b></sub></a><br /><a href="#maintenance-andrewmcodes" title="Maintenance">🚧</a></td>
309
+ <td align="center"><a href="http://gorails.com"><img src="https://avatars1.githubusercontent.com/u/67093?v=4?s=100" 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>
310
+ <td align="center"><a href="https://github.com/leastbad"><img src="https://avatars2.githubusercontent.com/u/38150464?v=4?s=100" 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>
311
+ <td align="center"><a href="http://code.digimonkey.com"><img src="https://avatars0.githubusercontent.com/u/74207?v=4?s=100" 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>
263
312
  </tr>
264
313
  <tr>
265
- <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>
266
- <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>
267
- <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>
268
- <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>
269
- <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>
270
- <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>
271
- <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>
314
+ <td align="center"><a href="http://fractaledmind.com"><img src="https://avatars3.githubusercontent.com/u/5077225?v=4?s=100" 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>
315
+ <td align="center"><a href="http://hass.codes"><img src="https://avatars2.githubusercontent.com/u/1064205?v=4?s=100" 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>
316
+ <td align="center"><a href="https://marcoroth.dev"><img src="https://avatars2.githubusercontent.com/u/6411752?v=4?s=100" 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>
317
+ <td align="center"><a href="https://viedit.com"><img src="https://avatars1.githubusercontent.com/u/49990587?v=4?s=100" 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>
318
+ <td align="center"><a href="http://scottbarrow.ca"><img src="https://avatars2.githubusercontent.com/u/5571736?v=4?s=100" 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>
319
+ <td align="center"><a href="http://domchristie.co.uk"><img src="https://avatars0.githubusercontent.com/u/111734?v=4?s=100" 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>
320
+ <td align="center"><a href="http://www.rickychilcott.com"><img src="https://avatars1.githubusercontent.com/u/445759?v=4?s=100" 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>
321
+ </tr>
322
+ <tr>
323
+ <td align="center"><a href="https://github.com/mansakondo"><img src="https://avatars.githubusercontent.com/u/47113995?v=4?s=100" width="100px;" alt=""/><br /><sub><b>mansakondo</b></sub></a><br /><a href="https://github.com/julianrubisch/futurism/commits?author=mansakondo" title="Code">💻</a></td>
272
324
  </tr>
273
325
  </table>
274
326
 
275
- <!-- markdownlint-enable -->
327
+ <!-- markdownlint-restore -->
276
328
  <!-- prettier-ignore-end -->
329
+
277
330
  <!-- ALL-CONTRIBUTORS-LIST:END -->
278
331
 
279
332
  This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
data/lib/futurism.rb CHANGED
@@ -2,6 +2,10 @@ require "rails"
2
2
  require "action_cable"
3
3
  require "cable_ready"
4
4
  require "futurism/engine"
5
+ require "futurism/message_verifier"
6
+ require "futurism/resolver/resources"
7
+ require "futurism/resolver/controller"
8
+ require "futurism/resolver/controller/renderer"
5
9
  require "futurism/channel"
6
10
  require "futurism/helpers"
7
11
 
@@ -10,7 +14,12 @@ module Futurism
10
14
 
11
15
  autoload :Helpers, "futurism/helpers"
12
16
 
13
- mattr_accessor :skip_in_test
17
+ mattr_accessor :skip_in_test, default: false
18
+
19
+ mattr_writer :default_controller
20
+ def self.default_controller
21
+ (@@default_controller || "::ApplicationController").to_s.constantize
22
+ end
14
23
 
15
24
  ActiveSupport.on_load(:action_view) {
16
25
  include Futurism::Helpers
data/lib/futurism.rb~ CHANGED
@@ -2,6 +2,9 @@ require "rails"
2
2
  require "action_cable"
3
3
  require "cable_ready"
4
4
  require "futurism/engine"
5
+ require "futurism/message_verifier"
6
+ require "futurism/resolver/controller"
7
+ require "futurism/resolver/controller/renderer"
5
8
  require "futurism/channel"
6
9
  require "futurism/helpers"
7
10
 
@@ -10,6 +13,13 @@ module Futurism
10
13
 
11
14
  autoload :Helpers, "futurism/helpers"
12
15
 
16
+ mattr_accessor :skip_in_test, default: false
17
+
18
+ mattr_writer :default_controller
19
+ def self.default_controller
20
+ (@@default_controller || "::ApplicationController").to_s.constantize
21
+ end
22
+
13
23
  ActiveSupport.on_load(:action_view) {
14
24
  include Futurism::Helpers
15
25
  }
@@ -15,33 +15,17 @@ module Futurism
15
15
  end
16
16
 
17
17
  def receive(data)
18
- resources = data.fetch_values("signed_params", "sgids") { |key| [nil] }.transpose
18
+ resources = data.fetch_values("signed_params", "sgids", "signed_controllers", "urls") { |_key| Array.new(data["signed_params"].length, nil) }.transpose
19
19
 
20
- new_env = connection.env.merge(ApplicationController.renderer.instance_variable_get(:@env))
21
- ApplicationController.renderer.instance_variable_set(:@env, new_env)
22
-
23
- resources.each do |signed_params, sgid|
24
- selector = "[data-signed-params='#{signed_params}']"
25
- selector << "[data-sgid='#{sgid}']" if sgid.present?
20
+ resolver = Resolver::Resources.new(resource_definitions: resources, connection: connection, params: @params)
21
+ resolver.resolve do |selector, html|
26
22
  cable_ready[stream_name].outer_html(
27
23
  selector: selector,
28
- html: ApplicationController.render(resource(signed_params: signed_params, sgid: sgid))
24
+ html: html
29
25
  )
30
26
  end
31
27
 
32
28
  cable_ready.broadcast
33
29
  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
46
30
  end
47
31
  end
@@ -1,6 +1,7 @@
1
1
  module Futurism
2
2
  class Channel < ActionCable::Channel::Base
3
3
  include CableReady::Broadcaster
4
+ include Futurism::MessageVerifier
4
5
 
5
6
  def stream_name
6
7
  ids = connection.identifiers.map { |identifier| send(identifier).try(:id) || send(identifier) }
@@ -15,17 +16,28 @@ module Futurism
15
16
  end
16
17
 
17
18
  def receive(data)
18
- resources = data.fetch_values("signed_params", "sgids") { |key| [nil] }.transpose
19
+ resources = data.fetch_values("signed_params", "sgids", "signed_controllers", "urls") { |_key| Array.new(data["signed_params"].length, nil) }.transpose
19
20
 
20
- new_env = connection.env.merge(ApplicationController.renderer.instance_variable_get(:@env))
21
- ApplicationController.renderer.instance_variable_set(:@env, new_env)
21
+ resources_with_sgids, resources_without_sgids = resources.partition { |signed_params, sgid, *| sgid.present? }
22
22
 
23
- resources.each do |signed_params, sgid|
23
+ GlobalID::Locator.locate_many_signed resources_with_sgids.map(&:second)
24
+
25
+ resources_without_sgids.each do |signed_params, sgid, signed_controller, url|
24
26
  selector = "[data-signed-params='#{signed_params}']"
25
27
  selector << "[data-sgid='#{sgid}']" if sgid.present?
28
+
29
+ controller = Resolver::Controller.from(signed_string: signed_controller)
30
+ renderer = Resolver::Controller::Renderer.for(controller: controller,
31
+ connection: connection,
32
+ url: url,
33
+ params: @params)
34
+
35
+ resource = lookup_resource(signed_params: signed_params, sgid: sgid)
36
+ html = renderer.render(resource)
37
+
26
38
  cable_ready[stream_name].outer_html(
27
39
  selector: selector,
28
- html: ApplicationController.render(resource(signed_params: signed_params, sgid: sgid))
40
+ html: html
29
41
  )
30
42
  end
31
43
 
@@ -34,12 +46,10 @@ module Futurism
34
46
 
35
47
  private
36
48
 
37
- def resource(signed_params:, sgid:)
49
+ def lookup_resource(signed_params:, sgid:)
38
50
  return GlobalID::Locator.locate_signed(sgid) if sgid.present?
39
51
 
40
- Rails
41
- .application
42
- .message_verifier("futurism")
52
+ message_verifier
43
53
  .verify(signed_params)
44
54
  .deep_transform_values { |value| value.is_a?(String) && value.start_with?("gid://") ? GlobalID::Locator.locate(value) : value }
45
55
  end
@@ -3,9 +3,9 @@ module Futurism
3
3
  def futurize(records_or_string = nil, extends:, **options, &block)
4
4
  if Rails.env.test? && Futurism.skip_in_test
5
5
  if records_or_string.nil?
6
- return render **options
6
+ return render(**options)
7
7
  else
8
- return render records_or_string, **options
8
+ return render(records_or_string, **options)
9
9
  end
10
10
  end
11
11
 
@@ -26,10 +26,10 @@ module Futurism
26
26
  if collection.nil?
27
27
  Element.new(extends: extends, placeholder: placeholder, options: options).render
28
28
  else
29
- collection_class_name = collection.klass.name
29
+ collection_class_name = collection.try(:klass).try(:name) || collection.first.class.to_s
30
30
  as = options.delete(:as) || collection_class_name.downcase
31
- collection.map { |record|
32
- Element.new(extends: extends, placeholder: placeholder, options: options.deep_merge(locals: {as.to_sym => record})).render
31
+ collection.each_with_index.map { |record, index|
32
+ Element.new(extends: extends, placeholder: placeholder, options: options.deep_merge(locals: {as.to_sym => record, "#{as}_counter".to_sym => index})).render
33
33
  }.join.html_safe
34
34
  end
35
35
  end
@@ -43,13 +43,15 @@ module Futurism
43
43
  # wraps functionality for rendering a futurism element
44
44
  class Element
45
45
  include ActionView::Helpers
46
+ include Futurism::MessageVerifier
46
47
 
47
- attr_reader :extends, :placeholder, :html_options, :data_attributes, :model, :options, :eager
48
+ attr_reader :extends, :placeholder, :html_options, :data_attributes, :model, :options, :eager, :controller
48
49
 
49
50
  def initialize(extends:, placeholder:, options:)
50
51
  @extends = extends
51
52
  @placeholder = placeholder
52
53
  @eager = options.delete(:eager)
54
+ @controller = options.delete(:controller)
53
55
  @html_options = options.delete(:html_options) || {}
54
56
  @data_attributes = html_options.fetch(:data, {}).except(:sgid, :signed_params)
55
57
  @model = options.delete(:model)
@@ -60,7 +62,8 @@ module Futurism
60
62
  data_attributes.merge({
61
63
  signed_params: signed_params,
62
64
  sgid: model && model.to_sgid.to_s,
63
- eager: eager.presence
65
+ eager: eager.presence,
66
+ signed_controller: signed_controller
64
67
  })
65
68
  end
66
69
 
@@ -86,7 +89,13 @@ module Futurism
86
89
  private
87
90
 
88
91
  def signed_params
89
- Rails.application.message_verifier("futurism").generate(transformed_options)
92
+ message_verifier.generate(transformed_options)
93
+ end
94
+
95
+ def signed_controller
96
+ return unless controller.present?
97
+
98
+ message_verifier.generate(controller.to_s)
90
99
  end
91
100
  end
92
101
  end
@@ -3,11 +3,10 @@ module Futurism
3
3
  def futurize(records_or_string = nil, extends:, **options, &block)
4
4
  if Rails.env.test? && Futurism.skip_in_test
5
5
  if records_or_string.nil?
6
- render options
6
+ return render(**options)
7
7
  else
8
- render records_or_string, options
8
+ return render(records_or_string, **options)
9
9
  end
10
- return
11
10
  end
12
11
 
13
12
  placeholder = capture(&block)
@@ -44,13 +43,15 @@ module Futurism
44
43
  # wraps functionality for rendering a futurism element
45
44
  class Element
46
45
  include ActionView::Helpers
46
+ include Futurism::MessageVerifier
47
47
 
48
- attr_reader :extends, :placeholder, :html_options, :data_attributes, :model, :options, :eager
48
+ attr_reader :extends, :placeholder, :html_options, :data_attributes, :model, :options, :eager, :controller
49
49
 
50
50
  def initialize(extends:, placeholder:, options:)
51
51
  @extends = extends
52
52
  @placeholder = placeholder
53
53
  @eager = options.delete(:eager)
54
+ @controller = options.delete(:controller)
54
55
  @html_options = options.delete(:html_options) || {}
55
56
  @data_attributes = html_options.fetch(:data, {}).except(:sgid, :signed_params)
56
57
  @model = options.delete(:model)
@@ -61,7 +62,8 @@ module Futurism
61
62
  data_attributes.merge({
62
63
  signed_params: signed_params,
63
64
  sgid: model && model.to_sgid.to_s,
64
- eager: eager.presence
65
+ eager: eager.presence,
66
+ signed_controller: signed_controller
65
67
  })
66
68
  end
67
69
 
@@ -87,7 +89,13 @@ module Futurism
87
89
  private
88
90
 
89
91
  def signed_params
90
- Rails.application.message_verifier("futurism").generate(transformed_options)
92
+ message_verifier.generate(transformed_options)
93
+ end
94
+
95
+ def signed_controller
96
+ return unless controller.present?
97
+
98
+ message_verifier.generate(controller.to_s)
91
99
  end
92
100
  end
93
101
  end
@@ -0,0 +1,11 @@
1
+ module Futurism
2
+ module MessageVerifier
3
+ def self.message_verifier
4
+ @message_verifier ||= Rails.application.message_verifier("futurism")
5
+ end
6
+
7
+ def message_verifier
8
+ @message_verifier ||= Rails.application.message_verifier("futurism")
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ module Futurism
2
+ module Resolver
3
+ class Controller
4
+ def self.from(signed_string:)
5
+ if signed_string.present?
6
+ Futurism::MessageVerifier
7
+ .message_verifier
8
+ .verify(signed_string)
9
+ .to_s
10
+ .safe_constantize
11
+ else
12
+ Futurism.default_controller
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module Futurism
2
+ module Resolver
3
+ class Controller
4
+ def self.from(signed_string:)
5
+ if signed_string.present?
6
+ Futurism::MessageVerifier
7
+ .message_verifier
8
+ .verify(signed_string)
9
+ .to_s
10
+ .safe_constantize
11
+ else
12
+ Futurism.default_controller
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,57 @@
1
+ module Futurism
2
+ module Resolver
3
+ class Controller
4
+ class Renderer
5
+ def self.for(controller:, connection:, url:, params:)
6
+ new(controller: controller, connection: connection, url: url, params: params).renderer
7
+ end
8
+
9
+ def initialize(controller:, connection:, url:, params:)
10
+ @controller = controller
11
+ @connection = connection
12
+ @url = url || ""
13
+ @params = params || {}
14
+
15
+ setup_env!
16
+ end
17
+
18
+ def renderer
19
+ @renderer ||= controller.renderer
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :controller, :connection, :url, :params
25
+ attr_writer :renderer
26
+
27
+ def setup_env!
28
+ if url.present?
29
+ uri = URI.parse(url)
30
+ path = ActionDispatch::Journey::Router::Utils.normalize_path(uri.path)
31
+ query_hash = Rack::Utils.parse_nested_query(uri.query)
32
+
33
+ path_params = Rails.application.routes.recognize_path(path)
34
+
35
+ self.renderer =
36
+ renderer.new(
37
+ "rack.request.query_hash" => query_hash,
38
+ "rack.request.query_string" => uri.query,
39
+ "ORIGINAL_SCRIPT_NAME" => "",
40
+ "ORIGINAL_FULLPATH" => path,
41
+ Rack::SCRIPT_NAME => "",
42
+ Rack::PATH_INFO => path,
43
+ Rack::REQUEST_PATH => path,
44
+ Rack::QUERY_STRING => uri.query,
45
+ ActionDispatch::Http::Parameters::PARAMETERS_KEY => params.symbolize_keys.merge(path_params).merge(query_hash)
46
+ )
47
+ end
48
+
49
+ # Copy connection env to renderer to fix some RACK related issues from gems like
50
+ # Warden or Devise
51
+ new_env = connection.env.merge(renderer.instance_variable_get(:@env))
52
+ renderer.instance_variable_set(:@env, new_env)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,57 @@
1
+ module Futurism
2
+ module Resolver
3
+ class Controller
4
+ class Renderer
5
+ def self.for(controller:, connection:, url:, params:)
6
+ new(controller: controller, connection: connection, url: url, params: params).renderer
7
+ end
8
+
9
+ def initialize(controller:, connection:, url:, params:)
10
+ @controller = controller
11
+ @connection = connection
12
+ @url = url || ""
13
+ @params = params || {}
14
+
15
+ setup_env!
16
+ end
17
+
18
+ def renderer
19
+ @renderer ||= controller.renderer
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :controller, :connection, :url, :params
25
+ attr_writer :renderer
26
+
27
+ def setup_env!
28
+ if url.present?
29
+ uri = URI.parse(url)
30
+ path = ActionDispatch::Journey::Router::Utils.normalize_path(uri.path)
31
+ query_hash = Rack::Utils.parse_nested_query(uri.query)
32
+
33
+ path_params = Rails.application.routes.recognize_path(path)
34
+
35
+ self.renderer =
36
+ renderer.new(
37
+ "rack.request.query_hash" => query_hash,
38
+ "rack.request.query_string" => uri.query,
39
+ "ORIGINAL_SCRIPT_NAME" => "",
40
+ "ORIGINAL_FULLPATH" => path,
41
+ Rack::SCRIPT_NAME => "",
42
+ Rack::PATH_INFO => path,
43
+ Rack::REQUEST_PATH => path,
44
+ Rack::QUERY_STRING => uri.query,
45
+ ActionDispatch::Http::Parameters::PARAMETERS_KEY => path_params.reverse_merge(path_params)
46
+ )
47
+ end
48
+
49
+ # Copy connection env to renderer to fix some RACK related issues from gems like
50
+ # Warden or Devise
51
+ new_env = connection.env.merge(renderer.instance_variable_get(:@env))
52
+ renderer.instance_variable_set(:@env, new_env)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,68 @@
1
+ module Futurism
2
+ module Resolver
3
+ class Resources
4
+ include Futurism::MessageVerifier
5
+
6
+ # resource definitions are an array of [signed_params, sgid, signed_controller, url]
7
+ def initialize(resource_definitions:, connection:, params:)
8
+ @connection = connection
9
+ @params = params
10
+ @resources_with_sgids, @resources_without_sgids = resource_definitions
11
+ .partition { |signed_params, sgid, *| sgid.present? }
12
+ .map { |partition| partition.map { |definition| ResourceDefinition.new(definition) } }
13
+ end
14
+
15
+ def resolve
16
+ resolved_models.zip(@resources_with_sgids).each do |model, resource_definition|
17
+ html = renderer_for(resource_definition: resource_definition).render(model)
18
+
19
+ yield(resource_definition.selector, html)
20
+ end
21
+
22
+ @resources_without_sgids.each do |resource_definition|
23
+ resource = lookup_resource(resource_definition)
24
+ html = renderer_for(resource_definition: resource_definition).render(resource)
25
+
26
+ yield(resource_definition.selector, html)
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ class ResourceDefinition
33
+ attr_reader :signed_params, :sgid, :signed_controller, :url
34
+
35
+ def initialize(resource_definition)
36
+ @signed_params, @sgid, @signed_controller, @url = resource_definition
37
+ end
38
+
39
+ def selector
40
+ selector = "[data-signed-params='#{@signed_params}']"
41
+ selector << "[data-sgid='#{@sgid}']" if @sgid.present?
42
+ selector
43
+ end
44
+
45
+ def controller
46
+ Resolver::Controller.from(signed_string: @signed_controller)
47
+ end
48
+ end
49
+
50
+ def renderer_for(resource_definition:)
51
+ Resolver::Controller::Renderer.for(controller: resource_definition.controller,
52
+ connection: @connection,
53
+ url: resource_definition.url,
54
+ params: @params)
55
+ end
56
+
57
+ def resolved_models
58
+ GlobalID::Locator.locate_many_signed @resources_with_sgids.map(&:sgid)
59
+ end
60
+
61
+ def lookup_resource(resource_definition)
62
+ message_verifier
63
+ .verify(resource_definition.signed_params)
64
+ .deep_transform_values { |value| value.is_a?(String) && value.start_with?("gid://") ? GlobalID::Locator.locate(value) : value }
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,73 @@
1
+ module Futurism
2
+ module Resolver
3
+ class Resources
4
+ include Futurism::MessageVerifier
5
+
6
+ # resource definitions are an array of [signed_params, sgid, signed_controller, url]
7
+ def initialize(resource_definitions:, connection:, params:)
8
+ @connection = connection
9
+ @params = params
10
+ @resources_with_sgids, @resources_without_sgids = resource_definitions
11
+ .partition { |signed_params, sgid, *| sgid.present? }
12
+ .map { |definition| ResourceDefinition.new(definition) }
13
+ end
14
+
15
+ def resolve
16
+ resolved_models.zip(@resources_with_sgids).each do |model, resource_definition|
17
+ signed_params, sgid, signed_controller, url = resource_definition
18
+
19
+ selector = selector_for(signed_params: signed_params, sgid: sgid)
20
+
21
+ controller = Resolver::Controller.from(signed_string: signed_controller)
22
+ renderer = Resolver::Controller::Renderer.for(controller: controller,
23
+ connection: @connection,
24
+ url: url,
25
+ params: @params)
26
+
27
+ html = renderer.render(model)
28
+
29
+ yield(selector, html)
30
+ end
31
+
32
+ @resources_without_sgids.each do |signed_params, sgid, signed_controller, url|
33
+ selector = selector_for(signed_params: signed_params, sgid: sgid)
34
+
35
+ controller = Resolver::Controller.from(signed_string: signed_controller)
36
+ renderer = Resolver::Controller::Renderer.for(controller: controller,
37
+ connection: @connection,
38
+ url: url,
39
+ params: @params)
40
+
41
+ resource = lookup_resource(signed_params: signed_params)
42
+ html = renderer.render(resource)
43
+
44
+ yield(selector, html)
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ class ResourceDefinition
51
+ def initialize(resource_definition)
52
+ @signed_params, @sgid, @signed_controller, @url = resource_definition
53
+ end
54
+ end
55
+
56
+ def resolved_models
57
+ GlobalID::Locator.locate_many_signed @resources_with_sgids.map(&:second)
58
+ end
59
+
60
+ def lookup_resource(signed_params:)
61
+ message_verifier
62
+ .verify(signed_params)
63
+ .deep_transform_values { |value| value.is_a?(String) && value.start_with?("gid://") ? GlobalID::Locator.locate(value) : value }
64
+ end
65
+
66
+ def selector_for(signed_params:, sgid:)
67
+ selector = "[data-signed-params='#{signed_params}']"
68
+ selector << "[data-sgid='#{sgid}']" if sgid.present?
69
+ selector
70
+ end
71
+ end
72
+ end
73
+ end
@@ -1,3 +1,3 @@
1
1
  module Futurism
2
- VERSION = "0.5.4"
2
+ VERSION = "0.8.0"
3
3
  end
@@ -0,0 +1,3 @@
1
+ module Futurism
2
+ VERSION = "0.7.2"
3
+ end
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: futurism
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.8.0
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-10-09 00:00:00.000000000 Z
11
+ date: 2021-04-23 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'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: bundler
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -108,20 +94,6 @@ dependencies:
108
94
  - - ">="
109
95
  - !ruby/object:Gem::Version
110
96
  version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: spy
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
97
  - !ruby/object:Gem::Dependency
126
98
  name: rack
127
99
  requirement: !ruby/object:Gem::Requirement
@@ -175,7 +147,6 @@ files:
175
147
  - MIT-LICENSE
176
148
  - README.md
177
149
  - Rakefile
178
- - app/assets/config/futurism_manifest.js
179
150
  - config/routes.rb
180
151
  - lib/futurism.rb
181
152
  - lib/futurism.rb~
@@ -184,8 +155,16 @@ files:
184
155
  - lib/futurism/engine.rb
185
156
  - lib/futurism/helpers.rb
186
157
  - lib/futurism/helpers.rb~
158
+ - lib/futurism/message_verifier.rb
159
+ - lib/futurism/resolver/controller.rb
160
+ - lib/futurism/resolver/controller.rb~
161
+ - lib/futurism/resolver/controller/renderer.rb
162
+ - lib/futurism/resolver/controller/renderer.rb~
163
+ - lib/futurism/resolver/resources.rb
164
+ - lib/futurism/resolver/resources.rb~
187
165
  - lib/futurism/shims/deep_transform_values.rb
188
166
  - lib/futurism/version.rb
167
+ - lib/futurism/version.rb~
189
168
  - lib/tasks/futurism_tasks.rake
190
169
  - lib/tasks/futurism_tasks.rake~
191
170
  homepage: https://github.com/julianrubisch/futurism
File without changes