stimulus_reflex 3.4.0.pre3 → 3.4.0.pre4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of stimulus_reflex might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 344e0b60c7f18f467821263a5758cc37843cfae000430754ed89d34214363ff3
4
- data.tar.gz: a49f8d18df8d0e2f4d664a70690fd562fd7d4fcc9db3f22d7821f96f67dee03d
3
+ metadata.gz: 1d3b9110da6cd9d446b19c1bd8ac2978b1d8b0c5ca88d1a1cf9fb849400a1757
4
+ data.tar.gz: 5512ece82357de04c62f9c4fcff9bba59bf6dec9f9234effeb06772084e96d38
5
5
  SHA512:
6
- metadata.gz: cd85f6455c20f2cad48a8e4c7bda0fe6e46e50fa6bb39d2c67c128a899edd96d815798b913b928ae08c75fb8f55421483249f6acec34e26428a7114fa7e3eb67
7
- data.tar.gz: 3fbb2e6be0b867db5c05997aa0727642e0298d0c13ad14e31c3f811ca4e6b4188db5154ea0c7ada5aeca8a3fb456c6998e35d0f4616e3fa03c636fc710b33056
6
+ metadata.gz: 928a0b20cc704cb30a1a9c7ccfe7672cc44c2e8cce2f9387b87ddc531981b2521e926992271233fb18e7787121bcda84e4f90c64823d32f5c2824ad302ba24e4
7
+ data.tar.gz: da166747c83c5dfee363e6a9475826cb32d3ba850f997481539cfdd475e390614e7726083bdf7e18762f410d4b74ff8b031922a66647498937d065479e939002
@@ -2,7 +2,34 @@
2
2
 
3
3
  ## [Unreleased](https://github.com/hopsoft/stimulus_reflex/tree/HEAD)
4
4
 
5
- [Full Changelog](https://github.com/hopsoft/stimulus_reflex/compare/v3.4.0.pre2...HEAD)
5
+ [Full Changelog](https://github.com/hopsoft/stimulus_reflex/compare/v3.4.0.pre3...HEAD)
6
+
7
+ **Fixed bugs:**
8
+
9
+ - Fix fatal error in `stimulus\_reflex:install` task with Rails 5.2 [\#371](https://github.com/hopsoft/stimulus_reflex/pull/371) ([Matt-Yorkley](https://github.com/Matt-Yorkley))
10
+ - fix nothing morphs and error messages [\#368](https://github.com/hopsoft/stimulus_reflex/pull/368) ([leastbad](https://github.com/leastbad))
11
+
12
+ **Closed issues:**
13
+
14
+ - `stimulus\_reflex:install` fails to complete in Rails 5.2 [\#367](https://github.com/hopsoft/stimulus_reflex/issues/367)
15
+ - Form data still not captured [\#366](https://github.com/hopsoft/stimulus_reflex/issues/366)
16
+ - Console exception when reflex does not update a page that didn't trigger the reflex [\#363](https://github.com/hopsoft/stimulus_reflex/issues/363)
17
+ - Improve server-side logging options [\#264](https://github.com/hopsoft/stimulus_reflex/issues/264)
18
+
19
+ **Merged pull requests:**
20
+
21
+ - use puts instead of ActionCable.logger to sidestep silenced AC logs [\#373](https://github.com/hopsoft/stimulus_reflex/pull/373) ([leastbad](https://github.com/leastbad))
22
+ - Improve logged post\_install.js message [\#372](https://github.com/hopsoft/stimulus_reflex/pull/372) ([forsbergplustwo](https://github.com/forsbergplustwo))
23
+ - Pass additional reflex-related data to reflex from data [\#370](https://github.com/hopsoft/stimulus_reflex/pull/370) ([joshleblanc](https://github.com/joshleblanc))
24
+ - fix: rip out microbundle [\#369](https://github.com/hopsoft/stimulus_reflex/pull/369) ([ParamagicDev](https://github.com/ParamagicDev))
25
+ - Add tests for broadcasters [\#364](https://github.com/hopsoft/stimulus_reflex/pull/364) ([julianrubisch](https://github.com/julianrubisch))
26
+ - Do not run sanity check on `rails generate stimulus\_reflex:config` [\#362](https://github.com/hopsoft/stimulus_reflex/pull/362) ([RolandStuder](https://github.com/RolandStuder))
27
+ - fix: revert CR and @rails/actioncable to dependencies [\#361](https://github.com/hopsoft/stimulus_reflex/pull/361) ([ParamagicDev](https://github.com/ParamagicDev))
28
+ - xpath fix [\#360](https://github.com/hopsoft/stimulus_reflex/pull/360) ([leastbad](https://github.com/leastbad))
29
+
30
+ ## [v3.4.0.pre3](https://github.com/hopsoft/stimulus_reflex/tree/v3.4.0.pre3) (2020-11-11)
31
+
32
+ [Full Changelog](https://github.com/hopsoft/stimulus_reflex/compare/v3.4.0.pre2...v3.4.0.pre3)
6
33
 
7
34
  **Merged pull requests:**
8
35
 
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- stimulus_reflex (3.4.0.pre3)
4
+ stimulus_reflex (3.4.0.pre4)
5
+ cable_ready (>= 4.3.0)
5
6
  nokogiri
6
7
  rack
7
8
  rails (>= 5.2)
@@ -72,7 +73,7 @@ GEM
72
73
  coderay (1.1.3)
73
74
  concurrent-ruby (1.1.7)
74
75
  crass (1.0.6)
75
- erubi (1.9.0)
76
+ erubi (1.10.0)
76
77
  globalid (0.4.2)
77
78
  activesupport (>= 4.2.0)
78
79
  i18n (1.8.5)
@@ -131,7 +132,7 @@ GEM
131
132
  thor (>= 0.20.3, < 2.0)
132
133
  rainbow (3.0.0)
133
134
  rake (13.0.1)
134
- redis (4.2.2)
135
+ redis (4.2.4)
135
136
  regexp_parser (1.8.2)
136
137
  rexml (3.2.4)
137
138
  rubocop (1.2.0)
@@ -176,7 +177,6 @@ PLATFORMS
176
177
 
177
178
  DEPENDENCIES
178
179
  bundler (~> 2.0)
179
- cable_ready (>= 4.3.0)
180
180
  pry
181
181
  pry-nav
182
182
  rake
@@ -37,9 +37,14 @@ class StimulusReflex::Channel < StimulusReflex.configuration.parent_channel.cons
37
37
  element: element,
38
38
  selectors: selectors,
39
39
  method_name: method_name,
40
- permanent_attribute_name: permanent_attribute_name,
41
40
  params: params,
42
- reflex_id: data["reflexId"])
41
+ client_attributes: {
42
+ reflex_id: data["reflexId"],
43
+ xpath: data["xpath"],
44
+ c_xpath: data["cXpath"],
45
+ reflex_controller: data["reflexController"],
46
+ permanent_attribute_name: permanent_attribute_name
47
+ })
43
48
  delegate_call_to_reflex reflex, method_name, arguments
44
49
  rescue => invoke_error
45
50
  message = exception_message_with_backtrace(invoke_error)
@@ -48,7 +53,7 @@ class StimulusReflex::Channel < StimulusReflex.configuration.parent_channel.cons
48
53
  reflex.rescue_with_handler(invoke_error)
49
54
  reflex.broadcast_message subject: "error", body: body, data: data, error: invoke_error
50
55
  else
51
- logger.error "\e[31m#{body}\e[0m"
56
+ puts "\e[31m#{body}\e[0m"
52
57
  end
53
58
  return
54
59
  end
@@ -63,10 +68,14 @@ class StimulusReflex::Channel < StimulusReflex.configuration.parent_channel.cons
63
68
  message = exception_message_with_backtrace(render_error)
64
69
  body = "Reflex failed to re-render: #{message} [#{url}]"
65
70
  reflex.broadcast_message subject: "error", body: body, data: data, error: render_error
71
+ puts "\e[31m#{body}\e[0m"
66
72
  end
67
73
  end
68
74
  ensure
69
- commit_session reflex if reflex
75
+ if reflex
76
+ commit_session(reflex)
77
+ reflex.logger.print
78
+ end
70
79
  end
71
80
  end
72
81
 
@@ -101,7 +110,7 @@ class StimulusReflex::Channel < StimulusReflex.configuration.parent_channel.cons
101
110
  store.commit_session reflex.request, reflex.controller.response
102
111
  rescue => e
103
112
  message = "Failed to commit session! #{exception_message_with_backtrace(e)}"
104
- logger.error "\e[31m#{message}\e[0m"
113
+ puts "\e[31m#{message}\e[0m"
105
114
  end
106
115
 
107
116
  def exception_message_with_backtrace(exception)
@@ -3,8 +3,18 @@
3
3
  StimulusReflex.configure do |config|
4
4
  # Enable/disable exiting / warning when the sanity checks fail options:
5
5
  # `:exit` or `:warn` or `:ignore`
6
+
6
7
  # config.on_failed_sanity_checks = :exit
7
8
 
8
9
  # Override the parent class that the StimulusReflex ActionCable channel inherits from
10
+
9
11
  # config.parent_channel = "ApplicationCable::Channel"
12
+
13
+ # Customize server-side Reflex logging format, with optional colorization:
14
+ # Available tokens: session_id, session_id_full, reflex_info, operation, reflex_id, reflex_id_full, mode, selector, operation_counter, connection_id, connection_id_full, timestamp
15
+ # Available colors: green, yellow, blue, magenta, cyan, white
16
+ # You can also use attributes from your ActionCable Connection's identifiers that resolve to valid ActiveRecord models
17
+ # eg. if your connection is `identified_by :current_user` and your User model has an email attribute, you can access r.email (it will display `-` if the user isn't logged in)
18
+
19
+ # config.logging = proc { "[#{session_id}] #{operation_counter.magenta} #{reflex_info.green} -> #{selector.cyan} via #{mode} Morph (#{operation.yellow})" }
10
20
  end
@@ -17,6 +17,8 @@ require "stimulus_reflex/broadcasters/broadcaster"
17
17
  require "stimulus_reflex/broadcasters/nothing_broadcaster"
18
18
  require "stimulus_reflex/broadcasters/page_broadcaster"
19
19
  require "stimulus_reflex/broadcasters/selector_broadcaster"
20
+ require "stimulus_reflex/utils/colorize"
21
+ require "stimulus_reflex/logger"
20
22
 
21
23
  module StimulusReflex
22
24
  class Engine < Rails::Engine
@@ -4,12 +4,13 @@ module StimulusReflex
4
4
  class Broadcaster
5
5
  include CableReady::Broadcaster
6
6
 
7
- attr_reader :reflex, :logger
7
+ attr_reader :reflex, :logger, :operations
8
8
  delegate :permanent_attribute_name, :stream_name, to: :reflex
9
9
 
10
10
  def initialize(reflex)
11
11
  @reflex = reflex
12
- @logger = Rails.logger
12
+ @logger = Rails.logger if defined?(Rails.logger)
13
+ @operations = []
13
14
  end
14
15
 
15
16
  def nothing?
@@ -26,6 +27,7 @@ module StimulusReflex
26
27
 
27
28
  def broadcast_message(subject:, body: nil, data: {}, error: nil)
28
29
  logger.error "\e[31m#{body}\e[0m" if subject == "error"
30
+ @operations << ["document", :dispatch_event]
29
31
  cable_ready[stream_name].dispatch_event(
30
32
  name: "stimulus-reflex:server-message",
31
33
  detail: {
@@ -48,5 +50,10 @@ module StimulusReflex
48
50
  def to_sym
49
51
  raise NotImplementedError
50
52
  end
53
+
54
+ # abstract method to be implemented by subclasses
55
+ def to_s
56
+ raise NotImplementedError
57
+ end
51
58
  end
52
59
  end
@@ -13,5 +13,9 @@ module StimulusReflex
13
13
  def to_sym
14
14
  :nothing
15
15
  end
16
+
17
+ def to_s
18
+ "Nothing"
19
+ end
16
20
  end
17
21
  end
@@ -8,9 +8,10 @@ module StimulusReflex
8
8
 
9
9
  return unless page_html.present?
10
10
 
11
- document = Nokogiri::HTML(page_html)
11
+ document = Nokogiri::HTML.parse(page_html)
12
12
  selectors = selectors.select { |s| document.css(s).present? }
13
13
  selectors.each do |selector|
14
+ @operations << [selector, :morph]
14
15
  html = document.css(selector).inner_html
15
16
  cable_ready[stream_name].morph(
16
17
  selector: selector,
@@ -32,5 +33,9 @@ module StimulusReflex
32
33
  def page?
33
34
  true
34
35
  end
36
+
37
+ def to_s
38
+ "Page"
39
+ end
35
40
  end
36
41
  end
@@ -11,6 +11,7 @@ module StimulusReflex
11
11
  fragment = Nokogiri::HTML.fragment(html)
12
12
  match = fragment.at_css(selector)
13
13
  if match.present?
14
+ @operations << [selector, :morph]
14
15
  cable_ready[stream_name].morph(
15
16
  selector: selector,
16
17
  html: match.inner_html,
@@ -21,6 +22,7 @@ module StimulusReflex
21
22
  })
22
23
  )
23
24
  else
25
+ @operations << [selector, :inner_html]
24
26
  cable_ready[stream_name].inner_html(
25
27
  selector: selector,
26
28
  html: fragment.to_html,
@@ -40,6 +42,10 @@ module StimulusReflex
40
42
  @morphs ||= []
41
43
  end
42
44
 
45
+ def append_morph(selectors, html)
46
+ morphs << [selectors, html]
47
+ end
48
+
43
49
  def to_sym
44
50
  :selector
45
51
  end
@@ -47,5 +53,9 @@ module StimulusReflex
47
53
  def selector?
48
54
  true
49
55
  end
56
+
57
+ def to_s
58
+ "Selector"
59
+ end
50
60
  end
51
61
  end
@@ -14,11 +14,14 @@ module StimulusReflex
14
14
  end
15
15
 
16
16
  class Configuration
17
- attr_accessor :on_failed_sanity_checks, :parent_channel
17
+ attr_accessor :on_failed_sanity_checks, :parent_channel, :logging
18
+
19
+ DEFAULT_LOGGING = proc { "[#{session_id}] #{operation_counter.magenta} #{reflex_info.green} -> #{selector.cyan} via #{mode} Morph (#{operation.yellow})" }
18
20
 
19
21
  def initialize
20
22
  @on_failed_sanity_checks = :exit
21
23
  @parent_channel = "ApplicationCable::Channel"
24
+ @logging = DEFAULT_LOGGING
22
25
  end
23
26
  end
24
27
  end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StimulusReflex
4
+ class Logger
5
+ attr_accessor :reflex, :current_operation
6
+
7
+ def initialize(reflex)
8
+ @reflex = reflex
9
+ @current_operation = 1
10
+ end
11
+
12
+ def print
13
+ return unless config_logging.instance_of?(Proc)
14
+
15
+ puts
16
+ reflex.broadcaster.operations.each do
17
+ puts instance_eval(&config_logging) + "\e[0m"
18
+ @current_operation += 1
19
+ end
20
+ puts
21
+ end
22
+
23
+ private
24
+
25
+ def config_logging
26
+ return @config_logging if @config_logging
27
+
28
+ StimulusReflex.config.logging.binding.eval("using StimulusReflex::Utils::Colorize")
29
+ @config_logging = StimulusReflex.config.logging
30
+ end
31
+
32
+ def session_id_full
33
+ session = reflex.request&.session
34
+ session.nil? ? "-" : session.id
35
+ end
36
+
37
+ def session_id
38
+ session_id_full.to_s[0..7]
39
+ end
40
+
41
+ def reflex_info
42
+ reflex.class.to_s + "#" + reflex.method_name
43
+ end
44
+
45
+ def reflex_id_full
46
+ reflex.reflex_id
47
+ end
48
+
49
+ def reflex_id
50
+ reflex_id_full[0..7]
51
+ end
52
+
53
+ def mode
54
+ reflex.broadcaster.to_s
55
+ end
56
+
57
+ def selector
58
+ reflex.broadcaster.operations[current_operation - 1][0]
59
+ end
60
+
61
+ def operation
62
+ reflex.broadcaster.operations[current_operation - 1][1].to_s
63
+ end
64
+
65
+ def operation_counter
66
+ current_operation.to_s + "/" + reflex.broadcaster.operations.size.to_s
67
+ end
68
+
69
+ def connection_id_full
70
+ identifier = reflex.connection&.connection_identifier
71
+ identifier.empty? ? "-" : identifier
72
+ end
73
+
74
+ def connection_id
75
+ connection_id_full[0..7]
76
+ end
77
+
78
+ def timestamp
79
+ Time.now.strftime("%Y-%m-%d %H:%M:%S")
80
+ end
81
+
82
+ def method_missing method
83
+ return send(method.to_sym) if private_instance_methods.include?(method.to_sym)
84
+
85
+ reflex.connection.identifiers.each do |identifier|
86
+ ident = reflex.connection.send(identifier)
87
+ return ident.send(method) if ident.respond_to?(:attributes) && ident.attributes.key?(method.to_s)
88
+ end
89
+ "-"
90
+ end
91
+
92
+ def respond_to_missing? method
93
+ return true if private_instance_methods.include?(method.to_sym)
94
+
95
+ reflex.connection.identifiers.each do |identifier|
96
+ ident = reflex.connection.send(identifier)
97
+ return true if ident.respond_to?(:attributes) && ident.attributes.key?(method.to_s)
98
+ end
99
+ false
100
+ end
101
+
102
+ def private_instance_methods
103
+ StimulusReflex::Logger.private_instance_methods(false)
104
+ end
105
+ end
106
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ ClientAttributes = Struct.new(:reflex_id, :reflex_controller, :xpath, :c_xpath, :permanent_attribute_name, keyword_init: true)
4
+
3
5
  class StimulusReflex::Reflex
4
6
  include ActiveSupport::Rescuable
5
7
  include ActiveSupport::Callbacks
@@ -43,24 +45,25 @@ class StimulusReflex::Reflex
43
45
  end
44
46
  end
45
47
 
46
- attr_reader :channel, :url, :element, :selectors, :method_name, :broadcaster, :permanent_attribute_name, :reflex_id
48
+ attr_reader :channel, :url, :element, :selectors, :method_name, :broadcaster, :client_attributes, :logger
47
49
 
48
50
  alias_method :action_name, :method_name # for compatibility with controller libraries like Pundit that expect an action name
49
51
 
50
52
  delegate :connection, :stream_name, to: :channel
51
53
  delegate :flash, :session, to: :request
52
54
  delegate :broadcast, :broadcast_message, to: :broadcaster
55
+ delegate :reflex_id, :reflex_controller, :xpath, :c_xpath, :permanent_attribute_name, to: :client_attributes
53
56
 
54
- def initialize(channel, url: nil, element: nil, selectors: [], method_name: nil, permanent_attribute_name: nil, params: {}, reflex_id: nil)
57
+ def initialize(channel, url: nil, element: nil, selectors: [], method_name: nil, params: {}, client_attributes: {})
55
58
  @channel = channel
56
59
  @url = url
57
60
  @element = element
58
61
  @selectors = selectors
59
62
  @method_name = method_name
60
63
  @params = params
61
- @permanent_attribute_name = permanent_attribute_name
62
64
  @broadcaster = StimulusReflex::PageBroadcaster.new(self)
63
- @reflex_id = reflex_id
65
+ @logger = StimulusReflex::Logger.new(self)
66
+ @client_attributes = ClientAttributes.new(client_attributes)
64
67
  self.params
65
68
  end
66
69
 
@@ -105,7 +108,7 @@ class StimulusReflex::Reflex
105
108
  else
106
109
  raise StandardError.new("Cannot call :selector morph after :nothing morph") if broadcaster.nothing?
107
110
  @broadcaster = StimulusReflex::SelectorBroadcaster.new(self) unless broadcaster.selector?
108
- broadcaster.morphs << [selectors, html]
111
+ broadcaster.append_morph(selectors, html)
109
112
  end
110
113
  end
111
114
 
@@ -3,12 +3,21 @@
3
3
  class StimulusReflex::SanityChecker
4
4
  JSON_VERSION_FORMAT = /(\d+\.\d+\.\d+.*)"/
5
5
 
6
- def self.check!
7
- return if StimulusReflex.config.on_failed_sanity_checks == :ignore
6
+ class << self
7
+ def check!
8
+ return if StimulusReflex.config.on_failed_sanity_checks == :ignore
9
+ return if called_by_generate_config?
10
+
11
+ instance = new
12
+ instance.check_caching_enabled
13
+ instance.check_javascript_package_version
14
+ end
15
+
16
+ private
8
17
 
9
- instance = new
10
- instance.check_caching_enabled
11
- instance.check_javascript_package_version
18
+ def called_by_generate_config?
19
+ ARGV.include? "stimulus_reflex:config"
20
+ end
12
21
  end
13
22
 
14
23
  def check_caching_enabled