futurism 0.3.0 → 0.4.1

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: e4522cbff1a5893e2a977bf7a32236b1ad9425983ed38521f188c5696dbbfec1
4
- data.tar.gz: 37cb1278ae994766170290f172aca2f4db3b8e2a801edcb77c1ce4632352d56a
3
+ metadata.gz: dc887b3a3173cce8feec82e572327f820cdb39793b5ee5fd5977b6e32c1edb78
4
+ data.tar.gz: e0f429c1861f30754e91c3dcce1121bf95894f558792f15f7f72958006b01dea
5
5
  SHA512:
6
- metadata.gz: 83742f96cb378d99ddc8d51bb95b8734fcdec0d9e22d0f3ac2b17122977dedf518942ed38664d715ec2b6890017269a301c31ebe3489d1e10d2176412970c13e
7
- data.tar.gz: 42a03c5aa611bd415ecfc33b76b9242ce2c4d1e2c06cab8bf50ee06e6e7fe67fb14bad078f4c36bf9b0cd2e242eeefdd3f79581a5f50d47e2c89f5c184f12e40
6
+ metadata.gz: 603a65c0d08974feeaceb867e076ab69daf99e51a139fd8f9c2634d7e3b885a7f662ae1c2c32e0e2c31ec6e2dd1b55ec2df8ad385441abfe25d66a7088d30a21
7
+ data.tar.gz: 11d930242efc8ff82a7b495197b4c5fceb9a0a7cc4e89fc48d9464e05e85e7eb307b7a25dac85628e2a5f7e66e1427e960150f544b325552142fc1ececb5e7db
data/README.md CHANGED
@@ -1,12 +1,34 @@
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-6-orange.svg?style=flat-square)](#contributors-)
4
+ [![All Contributors](https://img.shields.io/badge/all_contributors-12-orange.svg?style=flat-square)](#contributors-)
5
5
  <!-- ALL-CONTRIBUTORS-BADGE:END -->
6
6
  Lazy-load Rails partials via CableReady
7
7
 
8
8
  :rotating_light: *Futurism is still in pre-1.0 state. As much as I hope to keep the API backwards-compatible, I cannot guarantee it* :rotating_light:
9
9
 
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
+ <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
+
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
+ - [Events](#events)
24
+ - [Installation](#installation)
25
+ - [Manual Installation](#manual-installation)
26
+ - [Authentication](#authentication)
27
+ - [Gotchas](#gotchas)
28
+ - [Contributing](#contributing)
29
+ - [License](#license)
30
+ - [Contributors](#contributors)
31
+
10
32
  ## Facts
11
33
  - only one dependency: CableReady
12
34
  - bundle size (without CableReady) is around [~1.04kB](https://bundlephobia.com/result?p=@minthesize/futurism@0.1.3)
@@ -100,6 +122,28 @@ Collection rendering is also possible:
100
122
  <% end %>
101
123
  ```
102
124
 
125
+ ### HTML Options
126
+
127
+ 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.
128
+
129
+ ```erb
130
+ <%= futurize @posts, extends: :tr, html_options: {style: "width: 50px; height: 50px;"} do %>
131
+ <td class="placeholder"></td>
132
+ <% end %>
133
+ ```
134
+
135
+ This will output the following:
136
+
137
+ ```html
138
+ <tr style="width: 50px; height: 50px;">
139
+ <td class="placeholder"></td>
140
+ </tr>
141
+ ```
142
+
143
+ ## Events
144
+
145
+ Once your futurize element has been rendered, the `futurize:appeared` custom event will be called.
146
+
103
147
  ## Installation
104
148
  Add this line to your application's Gemfile:
105
149
 
@@ -130,7 +174,7 @@ $ bin/yarn add @minthesize/futurism
130
174
  In your `app/javascript/channels/index.js`, add the following
131
175
 
132
176
  ```js
133
- import * as Futurism
177
+ import * as Futurism from '@minthesize/futurism'
134
178
 
135
179
  import consumer from './consumer'
136
180
 
@@ -138,6 +182,39 @@ Futurism.initializeElements()
138
182
  Futurism.createSubscription(consumer)
139
183
  ```
140
184
 
185
+ ## Authentication
186
+ For authentication, you can rely on ActionCable identifiers, for example, if you use Devise:
187
+
188
+ ```ruby
189
+ module ApplicationCable
190
+ class Connection < ActionCable::Connection::Base
191
+ identified_by :current_user
192
+
193
+ def connect
194
+ self.current_user = env["warden"].user || reject_unauthorized_connection
195
+ end
196
+ end
197
+ end
198
+ ```
199
+
200
+ The [Stimulus Reflex Docs](https://docs.stimulusreflex.com/authentication) have an excellent section about all sorts of authentication.
201
+
202
+ ## Gotchas
203
+
204
+ ### ActiveStorage URLs aren't correct in development
205
+
206
+ Out of the box, Rails will prefix generated urls with `http://example.org` rather than `http://localhost`, much like ActionMailer. To amend this, add
207
+
208
+ ```ruby
209
+ # config/environments/development.rb
210
+ config.action_controller.default_url_options = {host: "localhost", port: 3000}
211
+
212
+ # config/environments/production.rb
213
+ config.action_controller.default_url_options = {host: "mysite.com"}
214
+ ```
215
+
216
+ to your environments.
217
+
141
218
  ## Contributing
142
219
 
143
220
  ## License
@@ -157,7 +234,15 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
157
234
  <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>
158
235
  <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>
159
236
  <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>
160
- <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>
237
+ <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>
238
+ <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>
239
+ </tr>
240
+ <tr>
241
+ <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>
242
+ <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>
243
+ <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>
244
+ <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>
245
+ <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>
161
246
  </tr>
162
247
  </table>
163
248
 
@@ -2,25 +2,42 @@ 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.application.message_verifier("futurism").verify(signed_params)
41
+ end
25
42
  end
26
43
  end
@@ -1,22 +1,35 @@
1
- class FuturismChannel < ApplicationCable::Channel
2
- include CableReady::Broadcaster
1
+ module Futurism
2
+ class Channel < ActionCable::Channel::Base
3
+ include CableReady::Broadcaster
3
4
 
4
- def subscribed
5
- stream_from "FuturismChannel"
6
- end
5
+ def subscribed
6
+ stream_from "Futurism::Channel"
7
+ end
8
+
9
+ def receive(data)
10
+ resources = data.fetch_values("signed_params", "sgids") { |key| [nil] }.transpose
11
+
12
+ new_env = connection.env.merge(ApplicationController.renderer.instance_variable_get(:@env))
13
+ ApplicationController.renderer.instance_variable_set(:@env, new_env)
7
14
 
8
- def receive(data)
9
- resources = data["sgids"].map { |sgid|
10
- [sgid, GlobalID::Locator.locate_signed(sgid)]
11
- }
15
+ resources.each do |signed_params, sgid|
16
+ selector = "[data-signed-params='#{signed_params}']"
17
+ selector << "[data-sgid='#{sgid}']" if sgid.present?
18
+ cable_ready["Futurism::Channel"].outer_html(
19
+ selector: selector,
20
+ html: ApplicationController.render(resource(signed_params: signed_params, sgid: sgid))
21
+ )
22
+ end
12
23
 
13
- resources.each do |sgid, resource|
14
- cable_ready["FuturismChannel"].outer_html(
15
- selector: "[data-sgid='#{sgid}']",
16
- html: ApplicationController.render(resource)
17
- )
24
+ cable_ready.broadcast
18
25
  end
19
26
 
20
- cable_ready.broadcast
27
+ private
28
+
29
+ def resource(signed_params:, sgid:)
30
+ return GlobalID::Locator.locate_signed(sgid) if sgid.present?
31
+
32
+ Rails.application.message_verifier("futurism").verify(signed_params)
33
+ end
21
34
  end
22
35
  end
@@ -4,9 +4,10 @@ module Futurism
4
4
  placeholder = capture(&block)
5
5
 
6
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)
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,32 +16,60 @@ 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
- collection_class_name = collection.first.class.name
21
+ collection_class_name = collection.klass.name
22
+ as = options.delete(:as) || collection_class_name.downcase
21
23
  collection.map { |record|
22
- render_element(extends: extends, placeholder: placeholder, options: options.merge(locals: {collection_class_name.downcase.to_sym => record}))
24
+ Element.new(extends: extends, placeholder: placeholder, options: options.deep_merge(locals: {as.to_sym => record})).render
23
25
  }.join.html_safe
24
26
  end
25
27
  end
26
28
 
27
- def futurize_active_record(records, extends:, placeholder:)
29
+ def futurize_active_record(records, extends:, placeholder:, **options)
28
30
  Array(records).map { |record|
29
- render_element(extends: extends, placeholder: placeholder, options: record)
31
+ Element.new(extends: extends, options: options.merge(model: record), placeholder: placeholder).render
30
32
  }.join.html_safe
31
33
  end
32
34
 
33
- def render_element(extends:, options:, placeholder:)
34
- case extends
35
- when :tr
36
- content_tag :tr, placeholder, data: {signed_params: futurism_signed_params(options)}, is: "futurism-table-row"
37
- else
38
- content_tag :"futurism-element", placeholder, data: {signed_params: futurism_signed_params(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
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
39
66
  end
40
- end
41
67
 
42
- def futurism_signed_params(params)
43
- Rails.application.message_verifier("futurism").generate(params)
68
+ private
69
+
70
+ def signed_params
71
+ Rails.application.message_verifier("futurism").generate(options)
72
+ end
44
73
  end
45
74
  end
46
75
  end
@@ -1,13 +1,73 @@
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
+ futurize_with_options(extends: extends, placeholder: placeholder, partial: records_or_string, **options)
8
10
  else
9
- content_tag :"futurism-element", placeholder, data: { sgid: record.to_sgid.to_s }
11
+ futurize_with_options(extends: extends, placeholder: placeholder, **options)
10
12
  end
11
- }.join.html_safe
13
+ end
14
+
15
+ def futurize_with_options(extends:, placeholder:, **options)
16
+ collection = options.delete(:collection)
17
+ if collection.nil?
18
+ Element.new(extends: extends, placeholder: placeholder, options: options).render
19
+ else
20
+ collection_class_name = collection.klass.name
21
+ as = options.delete(:as) || collection_class_name.downcase
22
+ collection.map { |record|
23
+ Element.new(extends: extends, placeholder: placeholder, options: options.deep_merge(locals: {as.to_sym => record})).render
24
+ }.join.html_safe
25
+ end
26
+ end
27
+
28
+ def futurize_active_record(records, extends:, placeholder:, **options)
29
+ Array(records).map { |record|
30
+ Element.new(extends: extends, options: options.merge(model: record), placeholder: placeholder).render
31
+ }.join.html_safe
32
+ end
33
+
34
+ # wraps functionality for rendering a futurism element
35
+ class Element
36
+ include ActionView::Helpers
37
+
38
+ attr_reader :extends, :placeholder, :html_options, :model, :options
39
+
40
+ def initialize(extends:, placeholder:, options:)
41
+ @extends = extends
42
+ @placeholder = placeholder
43
+ @html_options = options.delete(:html_options) || {}
44
+ @model = options.delete(:model)
45
+ @options = options
46
+ end
47
+
48
+ def dataset
49
+ {
50
+ signed_params: signed_params,
51
+ sgid: model && model.to_sgid.to_s
52
+ }
53
+ end
54
+
55
+ def render
56
+ case extends
57
+ when :li
58
+ content_tag :li, placeholder, {data: dataset, is: "futurism-li"}.merge(html_options)
59
+ when :tr
60
+ content_tag :tr, placeholder, {data: dataset, is: "futurism-table-row"}.merge(html_options)
61
+ else
62
+ content_tag :"futurism-element", placeholder, {data: dataset}.merge(html_options)
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def signed_params
69
+ Rails.application.message_verifier("futurism").generate(options)
70
+ end
71
+ end
12
72
  end
13
73
  end
@@ -1,3 +1,3 @@
1
1
  module Futurism
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: futurism
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.1
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-22 00:00:00.000000000 Z
11
+ date: 2020-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler