stimulus_reflex 3.5.0.pre1 → 3.5.0.pre5

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.

Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +75 -8
  3. data/Gemfile.lock +86 -78
  4. data/README.md +8 -7
  5. data/app/channels/stimulus_reflex/channel.rb +13 -17
  6. data/lib/generators/stimulus_reflex/stimulus_reflex_generator.rb +5 -4
  7. data/lib/generators/stimulus_reflex/templates/app/reflexes/application_reflex.rb.tt +11 -4
  8. data/lib/generators/stimulus_reflex/templates/config/initializers/stimulus_reflex.rb +15 -0
  9. data/lib/stimulus_reflex/broadcasters/broadcaster.rb +18 -17
  10. data/lib/stimulus_reflex/broadcasters/nothing_broadcaster.rb +6 -1
  11. data/lib/stimulus_reflex/broadcasters/page_broadcaster.rb +1 -3
  12. data/lib/stimulus_reflex/broadcasters/selector_broadcaster.rb +19 -20
  13. data/lib/stimulus_reflex/broadcasters/update.rb +23 -0
  14. data/lib/stimulus_reflex/configuration.rb +3 -1
  15. data/lib/stimulus_reflex/dataset.rb +34 -0
  16. data/lib/stimulus_reflex/element.rb +16 -33
  17. data/lib/stimulus_reflex/reflex.rb +7 -2
  18. data/lib/stimulus_reflex/utils/attribute_builder.rb +17 -0
  19. data/lib/stimulus_reflex/utils/logger.rb +6 -2
  20. data/lib/stimulus_reflex/utils/sanity_checker.rb +75 -67
  21. data/lib/stimulus_reflex/version.rb +1 -1
  22. data/lib/stimulus_reflex.rb +1 -0
  23. data/lib/tasks/stimulus_reflex/install.rake +49 -12
  24. data/test/broadcasters/broadcaster_test.rb +0 -1
  25. data/test/broadcasters/broadcaster_test_case.rb +24 -0
  26. data/test/broadcasters/nothing_broadcaster_test.rb +14 -22
  27. data/test/broadcasters/page_broadcaster_test.rb +30 -32
  28. data/test/broadcasters/selector_broadcaster_test.rb +82 -88
  29. data/test/element_test.rb +73 -0
  30. data/test/generators/stimulus_reflex_generator_test.rb +8 -0
  31. data/test/reflex_test.rb +11 -0
  32. data/test/test_helper.rb +21 -1
  33. data/test/tmp/app/reflexes/application_reflex.rb +10 -3
  34. metadata +25 -4
@@ -26,33 +26,34 @@ module StimulusReflex
26
26
  false
27
27
  end
28
28
 
29
- def broadcast_message(subject:, data: {}, error: nil)
29
+ def halted(data: {})
30
30
  operations << ["document", :dispatch_event]
31
31
  cable_ready.dispatch_event(
32
- name: "stimulus-reflex:server-message",
33
- detail: {
34
- reflexId: data.delete("reflexId"),
35
- payload: payload,
36
- stimulus_reflex: data.merge(
37
- morph: to_sym,
38
- server_message: {subject: subject, body: error&.to_s}
39
- )
40
- }
41
- )
42
- cable_ready.broadcast
43
- end
44
-
45
- # abstract method to be implemented by subclasses
32
+ name: "stimulus-reflex:morph-halted",
33
+ payload: payload,
34
+ stimulus_reflex: data.merge(morph: to_sym)
35
+ ).broadcast
36
+ end
37
+
38
+ def error(data: {}, body: nil)
39
+ operations << ["document", :dispatch_event]
40
+ cable_ready.dispatch_event(
41
+ name: "stimulus-reflex:morph-error",
42
+ payload: payload,
43
+ stimulus_reflex: data.merge(morph: to_sym),
44
+ body: body&.to_s
45
+ ).broadcast
46
+ end
47
+
48
+ # abstract methods to be implemented by subclasses
46
49
  def broadcast(*args)
47
50
  raise NotImplementedError
48
51
  end
49
52
 
50
- # abstract method to be implemented by subclasses
51
53
  def to_sym
52
54
  raise NotImplementedError
53
55
  end
54
56
 
55
- # abstract method to be implemented by subclasses
56
57
  def to_s
57
58
  raise NotImplementedError
58
59
  end
@@ -3,7 +3,12 @@
3
3
  module StimulusReflex
4
4
  class NothingBroadcaster < Broadcaster
5
5
  def broadcast(_, data)
6
- broadcast_message subject: "nothing", data: data
6
+ operations << ["document", :dispatch_event]
7
+ cable_ready.dispatch_event(
8
+ name: "stimulus-reflex:morph-nothing",
9
+ payload: payload,
10
+ stimulus_reflex: data.merge(morph: to_sym)
11
+ ).broadcast
7
12
  end
8
13
 
9
14
  def nothing?
@@ -19,9 +19,7 @@ module StimulusReflex
19
19
  payload: payload,
20
20
  children_only: true,
21
21
  permanent_attribute_name: permanent_attribute_name,
22
- stimulus_reflex: data.merge({
23
- morph: to_sym
24
- })
22
+ stimulus_reflex: data.merge(morph: to_sym)
25
23
  )
26
24
  end
27
25
  cable_ready.broadcast
@@ -2,40 +2,30 @@
2
2
 
3
3
  module StimulusReflex
4
4
  class SelectorBroadcaster < Broadcaster
5
- include CableReady::Identifiable
6
-
7
5
  def broadcast(_, data = {})
8
6
  morphs.each do |morph|
9
7
  selectors, html = morph
10
- updates = selectors.is_a?(Hash) ? selectors : {selectors => html}
11
- updates.each do |key, value|
12
- html = reflex.render(key) if key.is_a?(ActiveRecord::Base) && value.nil?
13
- html = reflex.render_collection(key) if key.is_a?(ActiveRecord::Relation) && value.nil?
14
- html ||= value
15
- fragment = Nokogiri::HTML.fragment(html.to_s)
16
- selector = key.is_a?(ActiveRecord::Base) || key.is_a?(ActiveRecord::Relation) ? dom_id(key) : key.to_s
17
- match = fragment.at_css(selector)
8
+ updates = create_update_collection(selectors, html)
9
+ updates.each do |update|
10
+ fragment = Nokogiri::HTML.fragment(update.html.to_s)
11
+ match = fragment.at_css(update.selector)
18
12
  if match.present?
19
- operations << [selector, :morph]
13
+ operations << [update.selector, :morph]
20
14
  cable_ready.morph(
21
- selector: selector,
15
+ selector: update.selector,
22
16
  html: match.inner_html(save_with: Broadcaster::DEFAULT_HTML_WITHOUT_FORMAT),
23
17
  payload: payload,
24
18
  children_only: true,
25
19
  permanent_attribute_name: permanent_attribute_name,
26
- stimulus_reflex: data.merge({
27
- morph: to_sym
28
- })
20
+ stimulus_reflex: data.merge(morph: to_sym)
29
21
  )
30
22
  else
31
- operations << [selector, :inner_html]
23
+ operations << [update.selector, :inner_html]
32
24
  cable_ready.inner_html(
33
- selector: selector,
25
+ selector: update.selector,
34
26
  html: fragment.to_html,
35
27
  payload: payload,
36
- stimulus_reflex: data.merge({
37
- morph: to_sym
38
- })
28
+ stimulus_reflex: data.merge(morph: to_sym)
39
29
  )
40
30
  end
41
31
  end
@@ -64,5 +54,14 @@ module StimulusReflex
64
54
  def to_s
65
55
  "Selector"
66
56
  end
57
+
58
+ private
59
+
60
+ def create_update_collection(selectors, html)
61
+ updates = selectors.is_a?(Hash) ? selectors : {selectors => html}
62
+ updates.map do |key, value|
63
+ StimulusReflex::Broadcasters::Update.new(key, value, reflex)
64
+ end
65
+ end
67
66
  end
68
67
  end
@@ -0,0 +1,23 @@
1
+ module StimulusReflex
2
+ module Broadcasters
3
+ class Update
4
+ include CableReady::Identifiable
5
+
6
+ def initialize(key, value, reflex)
7
+ @key = key
8
+ @value = value
9
+ @reflex = reflex
10
+ end
11
+
12
+ def selector
13
+ @selector ||= identifiable?(@key) ? dom_id(@key) : @key.to_s
14
+ end
15
+
16
+ def html
17
+ html = @reflex.render(@key) if @key.is_a?(ActiveRecord::Base) && @value.nil?
18
+ html = @reflex.render_collection(@key) if @key.is_a?(ActiveRecord::Relation) && @value.nil?
19
+ html || @value
20
+ end
21
+ end
22
+ end
23
+ end
@@ -14,15 +14,17 @@ module StimulusReflex
14
14
  end
15
15
 
16
16
  class Configuration
17
- attr_accessor :on_failed_sanity_checks, :on_new_version_available, :parent_channel, :logging, :middleware
17
+ attr_accessor :on_failed_sanity_checks, :on_new_version_available, :on_missing_default_urls, :parent_channel, :logging, :logger, :middleware
18
18
 
19
19
  DEFAULT_LOGGING = proc { "[#{session_id}] #{operation_counter.magenta} #{reflex_info.green} -> #{selector.cyan} via #{mode} Morph (#{operation.yellow})" }
20
20
 
21
21
  def initialize
22
22
  @on_failed_sanity_checks = :exit
23
23
  @on_new_version_available = :ignore
24
+ @on_missing_default_urls = :warn
24
25
  @parent_channel = "ApplicationCable::Channel"
25
26
  @logging = DEFAULT_LOGGING
27
+ @logger = Rails.logger
26
28
  @middleware = ActionDispatch::MiddlewareStack.new
27
29
  end
28
30
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "stimulus_reflex/utils/attribute_builder"
4
+
5
+ class StimulusReflex::Dataset < OpenStruct
6
+ include StimulusReflex::AttributeBuilder
7
+
8
+ attr_accessor :attrs, :data_attrs
9
+
10
+ def initialize(data = {})
11
+ datasets = data["dataset"] || {}
12
+ regular_dataset = datasets["dataset"] || {}
13
+ @attrs = build_data_attrs(regular_dataset, datasets["datasetAll"] || {})
14
+ @data_attrs = @attrs.transform_keys { |key| key.delete_prefix "data-" }
15
+
16
+ super build_underscored(@data_attrs)
17
+ end
18
+
19
+ def signed
20
+ @signed ||= ->(accessor) { GlobalID::Locator.locate_signed(self[accessor]) }
21
+ end
22
+
23
+ def unsigned
24
+ @unsigned ||= ->(accessor) { GlobalID::Locator.locate(self[accessor]) }
25
+ end
26
+
27
+ def boolean
28
+ @boolean ||= ->(accessor) { ActiveModel::Type::Boolean.new.cast(self[accessor]) || self[accessor].blank? }
29
+ end
30
+
31
+ def numeric
32
+ @numeric ||= ->(accessor) { Float(self[accessor]) }
33
+ end
34
+ end
@@ -1,49 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "stimulus_reflex/dataset"
4
+ require "stimulus_reflex/utils/attribute_builder"
5
+
3
6
  class StimulusReflex::Element < OpenStruct
4
- attr_reader :attrs, :data_attrs
7
+ include StimulusReflex::AttributeBuilder
8
+
9
+ attr_reader :attrs, :dataset
10
+
11
+ alias_method :data_attributes, :dataset
12
+
13
+ delegate :signed, :unsigned, :numeric, :boolean, :data_attrs, to: :dataset
5
14
 
6
15
  def initialize(data = {})
7
16
  @attrs = HashWithIndifferentAccess.new(data["attrs"] || {})
8
- datasets = data["dataset"] || {}
9
- regular_dataset = datasets["dataset"] || {}
10
- @data_attrs = build_data_attrs(regular_dataset, datasets["datasetAll"] || {})
11
- all_attributes = @attrs.merge(@data_attrs)
12
- super build_underscored(all_attributes)
13
- @data_attrs.transform_keys! { |key| key.delete_prefix "data-" }
14
- end
17
+ @dataset = StimulusReflex::Dataset.new(data)
15
18
 
16
- def signed
17
- @signed ||= ->(accessor) { GlobalID::Locator.locate_signed(dataset[accessor]) }
18
- end
19
-
20
- def unsigned
21
- @unsigned ||= ->(accessor) { GlobalID::Locator.locate(dataset[accessor]) }
19
+ all_attributes = @attrs.merge(@dataset.attrs)
20
+ super build_underscored(all_attributes)
22
21
  end
23
22
 
24
23
  def attributes
25
24
  @attributes ||= OpenStruct.new(build_underscored(attrs))
26
25
  end
27
26
 
28
- def dataset
29
- @dataset ||= OpenStruct.new(build_underscored(data_attrs))
30
- end
31
-
32
- alias_method :data_attributes, :dataset
33
-
34
- private
35
-
36
- def build_data_attrs(dataset, dataset_all)
37
- dataset_all.transform_keys! { |key| "data-#{key.delete_prefix("data-").pluralize}" }
38
-
39
- dataset.each { |key, value| dataset_all[key]&.prepend(value) }
40
-
41
- data_attrs = dataset.merge(dataset_all)
42
-
43
- HashWithIndifferentAccess.new(data_attrs || {})
44
- end
27
+ def to_dom_id
28
+ raise NoIDError.new "The element `morph` is called on must have a valid DOM ID" if id.blank?
45
29
 
46
- def build_underscored(attrs)
47
- attrs.merge(attrs.transform_keys(&:underscore))
30
+ "##{id}"
48
31
  end
49
32
  end
@@ -8,14 +8,14 @@ class StimulusReflex::Reflex
8
8
  include ActionView::Helpers::TagHelper
9
9
  include CableReady::Identifiable
10
10
 
11
- attr_accessor :payload
11
+ attr_accessor :payload, :headers
12
12
  attr_reader :cable_ready, :channel, :url, :element, :selectors, :method_name, :broadcaster, :client_attributes, :logger
13
13
 
14
14
  alias_method :action_name, :method_name # for compatibility with controller libraries like Pundit that expect an action name
15
15
 
16
16
  delegate :connection, :stream_name, to: :channel
17
17
  delegate :controller_class, :flash, :session, to: :request
18
- delegate :broadcast, :broadcast_message, to: :broadcaster
18
+ delegate :broadcast, :halted, :error, to: :broadcaster
19
19
  delegate :reflex_id, :tab_id, :reflex_controller, :xpath_controller, :xpath_element, :permanent_attribute_name, to: :client_attributes
20
20
 
21
21
  def initialize(channel, url: nil, element: nil, selectors: [], method_name: nil, params: {}, client_attributes: {})
@@ -41,6 +41,7 @@ class StimulusReflex::Reflex
41
41
  @client_attributes = ClientAttributes.new(client_attributes)
42
42
  @cable_ready = StimulusReflex::CableReadyChannels.new(stream_name, reflex_id)
43
43
  @payload = {}
44
+ @headers = {}
44
45
  self.params
45
46
  end
46
47
 
@@ -97,6 +98,7 @@ class StimulusReflex::Reflex
97
98
 
98
99
  def controller
99
100
  @controller ||= controller_class.new.tap do |c|
101
+ request.headers.merge!(headers)
100
102
  c.instance_variable_set :@stimulus_reflex, true
101
103
  c.set_request! request
102
104
  c.set_response! controller_class.make_response!(request)
@@ -111,6 +113,9 @@ class StimulusReflex::Reflex
111
113
  end
112
114
 
113
115
  def render(*args)
116
+ options = args.extract_options!
117
+ (options[:locals] ||= {}).reverse_merge!(params: params)
118
+ args << options.reverse_merge(layout: false)
114
119
  controller_class.renderer.new(connection.env.merge("SCRIPT_NAME" => "")).render(*args)
115
120
  end
116
121
 
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StimulusReflex::AttributeBuilder
4
+ def build_data_attrs(dataset, dataset_all)
5
+ dataset_all.transform_keys! { |key| "data-#{key.delete_prefix("data-").pluralize}" }
6
+
7
+ dataset.each { |key, value| dataset_all[key]&.prepend(value) }
8
+
9
+ data_attrs = dataset.merge(dataset_all)
10
+
11
+ HashWithIndifferentAccess.new(data_attrs || {})
12
+ end
13
+
14
+ def build_underscored(attrs)
15
+ attrs.merge(attrs.transform_keys(&:underscore))
16
+ end
17
+ end
@@ -2,18 +2,22 @@
2
2
 
3
3
  module StimulusReflex
4
4
  class Logger
5
+ attr_reader :logger
5
6
  attr_accessor :reflex, :current_operation
6
7
 
8
+ delegate :debug, :info, :warn, :error, :fatal, :unknown, to: :logger
9
+
7
10
  def initialize(reflex)
8
11
  @reflex = reflex
9
12
  @current_operation = 1
13
+ @logger = StimulusReflex.config.logger
10
14
  end
11
15
 
12
- def print
16
+ def log_all_operations
13
17
  return unless config_logging.instance_of?(Proc)
14
18
 
15
19
  reflex.broadcaster.operations.each do
16
- puts instance_eval(&config_logging) + "\e[0m"
20
+ logger.info instance_eval(&config_logging) + "\e[0m"
17
21
  @current_operation += 1
18
22
  end
19
23
  end
@@ -7,14 +7,16 @@ class StimulusReflex::SanityChecker
7
7
 
8
8
  class << self
9
9
  def check!
10
+ return if ENV["SKIP_SANITY_CHECK"]
10
11
  return if StimulusReflex.config.on_failed_sanity_checks == :ignore
11
12
  return if called_by_installer?
12
13
  return if called_by_generate_config?
14
+ return if called_by_rake?
13
15
 
14
16
  instance = new
15
17
  instance.check_caching_enabled
16
- instance.check_javascript_package_version
17
- instance.check_default_url_config
18
+ instance.check_package_versions_match
19
+ # instance.check_default_url_config
18
20
  instance.check_new_version_available
19
21
  end
20
22
 
@@ -29,65 +31,80 @@ class StimulusReflex::SanityChecker
29
31
  def called_by_generate_config?
30
32
  ARGV.include? "stimulus_reflex:initializer"
31
33
  end
34
+
35
+ def called_by_rake?
36
+ File.basename($PROGRAM_NAME) == "rake"
37
+ end
32
38
  end
33
39
 
34
40
  def check_caching_enabled
35
- unless caching_enabled?
41
+ if caching_not_enabled?
36
42
  warn_and_exit <<~WARN
37
- StimulusReflex requires caching to be enabled. Caching allows the session to be modified during ActionCable requests.
43
+ 👉 StimulusReflex requires caching to be enabled. Caching allows the session to be modified during ActionCable requests.
44
+
38
45
  To enable caching in development, run:
46
+
39
47
  rails dev:cache
40
48
  WARN
41
49
  end
42
50
 
43
- unless not_null_store?
51
+ if using_null_store?
44
52
  warn_and_exit <<~WARN
45
- StimulusReflex requires caching to be enabled. Caching allows the session to be modified during ActionCable requests.
46
- But your config.cache_store is set to :null_store, so it won't work.
53
+ 👉 StimulusReflex requires caching to be enabled.
54
+
55
+ Caching allows the session to be modified during ActionCable requests. Your config.cache_store is set to :null_store, so it won't work.
47
56
  WARN
48
57
  end
49
58
  end
50
59
 
51
60
  def check_default_url_config
52
- unless default_url_config_set?
53
- warn_and_exit <<~WARN
54
- StimulusReflex strongly suggests that you set default_url_options in your environment files.
55
- Otherwise, ActionController and ActionMailer will default to example.com when rendering route helpers.
61
+ return if StimulusReflex.config.on_missing_default_urls == :ignore
62
+ if default_url_config_set? == false
63
+ puts <<~WARN
64
+ 👉 StimulusReflex strongly suggests that you set default_url_options in your environment files. Otherwise, ActionController #{"and ActionMailer " if defined?(ActionMailer)}will default to example.com when rendering route helpers.
65
+
56
66
  You can set your URL options in config/environments/#{Rails.env}.rb
67
+
57
68
  config.action_controller.default_url_options = {host: "localhost", port: 3000}
58
- config.action_mailer.default_url_options = {host: "localhost", port: 3000}
69
+ #{"config.action_mailer.default_url_options = {host: \"localhost\", port: 3000}\n" if defined?(ActionMailer)}
59
70
  Please update every environment with the appropriate URL. Typically, no port is necessary in production.
71
+
60
72
  WARN
61
73
  end
62
74
  end
63
75
 
64
- def check_javascript_package_version
65
- if javascript_package_version.nil?
76
+ def check_package_versions_match
77
+ if npm_version.nil?
66
78
  warn_and_exit <<~WARN
67
- Can't locate the stimulus_reflex npm package.
79
+ 👉 Can't locate the stimulus_reflex npm package.
80
+
81
+ yarn add stimulus_reflex@#{gem_version}
82
+
68
83
  Either add it to your package.json as a dependency or use "yarn link stimulus_reflex" if you are doing development.
69
84
  WARN
70
85
  end
71
86
 
72
- unless javascript_version_matches?
87
+ if package_version_mismatch?
73
88
  warn_and_exit <<~WARN
74
- The stimulus_reflex npm package version (#{javascript_package_version}) does not match the Rubygem version (#{gem_version}).
89
+ 👉 The stimulus_reflex npm package version (#{npm_version}) does not match the Rubygem version (#{gem_version}).
90
+
75
91
  To update the stimulus_reflex npm package:
92
+
76
93
  yarn upgrade stimulus_reflex@#{gem_version}
77
94
  WARN
78
95
  end
79
96
  end
80
97
 
81
98
  def check_new_version_available
82
- return unless Rails.env.development?
83
99
  return if StimulusReflex.config.on_new_version_available == :ignore
84
- return unless using_stable_release
100
+ return if Rails.env.development? == false
101
+ return if using_preview_release?
85
102
  begin
86
103
  latest_version = URI.open("https://raw.githubusercontent.com/stimulusreflex/stimulus_reflex/master/LATEST", open_timeout: 1, read_timeout: 1).read.strip
87
104
  if latest_version != StimulusReflex::VERSION
88
105
  puts <<~WARN
89
106
 
90
- There is a new version of StimulusReflex available!
107
+ 👉 There is a new version of StimulusReflex available!
91
108
  Current: #{StimulusReflex::VERSION} Latest: #{latest_version}
92
109
 
93
110
  If you upgrade, it is very important that you update BOTH Gemfile and package.json
@@ -97,43 +114,45 @@ class StimulusReflex::SanityChecker
97
114
  exit if StimulusReflex.config.on_new_version_available == :exit
98
115
  end
99
116
  rescue
100
- puts "StimulusReflex #{StimulusReflex::VERSION} update check skipped: connection timeout"
117
+ puts "👉 StimulusReflex #{StimulusReflex::VERSION} update check skipped: connection timeout"
101
118
  end
102
119
  end
103
120
 
104
- private
105
-
106
- def caching_enabled?
107
- Rails.application.config.action_controller.perform_caching
121
+ def caching_not_enabled?
122
+ Rails.application.config.action_controller.perform_caching == false
108
123
  end
109
124
 
110
- def not_null_store?
111
- Rails.application.config.cache_store != :null_store
125
+ def using_null_store?
126
+ Rails.application.config.cache_store == :null_store
112
127
  end
113
128
 
114
129
  def default_url_config_set?
115
- Rails.application.config.action_controller.default_url_options
130
+ if defined?(ActionMailer)
131
+ Rails.application.config.action_controller.default_url_options.blank? && Rails.application.config.action_mailer.default_url_options.blank?
132
+ else
133
+ Rails.application.config.action_controller.default_url_options.blank?
134
+ end
116
135
  end
117
136
 
118
- def javascript_version_matches?
119
- javascript_package_version == gem_version
137
+ def package_version_mismatch?
138
+ npm_version != gem_version
120
139
  end
121
140
 
122
- def using_stable_release
123
- stable = StimulusReflex::VERSION.match?(LATEST_VERSION_FORMAT)
124
- puts "StimulusReflex #{StimulusReflex::VERSION} update check skipped: pre-release build" unless stable
125
- stable
141
+ def using_preview_release?
142
+ preview = StimulusReflex::VERSION.match?(LATEST_VERSION_FORMAT) == false
143
+ puts "👉 StimulusReflex #{StimulusReflex::VERSION} update check skipped: pre-release build" if preview
144
+ preview
126
145
  end
127
146
 
128
147
  def gem_version
129
148
  @_gem_version ||= StimulusReflex::VERSION.gsub(".pre", "-pre")
130
149
  end
131
150
 
132
- def javascript_package_version
133
- @_js_version ||= find_javascript_package_version
151
+ def npm_version
152
+ @_npm_version ||= find_npm_version
134
153
  end
135
154
 
136
- def find_javascript_package_version
155
+ def find_npm_version
137
156
  if (match = search_file(package_json_path, regex: /version/))
138
157
  match[JSON_VERSION_FORMAT, 1]
139
158
  elsif (match = search_file(yarn_lock_path, regex: /^stimulus_reflex/))
@@ -142,7 +161,7 @@ class StimulusReflex::SanityChecker
142
161
  end
143
162
 
144
163
  def search_file(path, regex:)
145
- return unless File.exist?(path)
164
+ return if File.exist?(path) == false
146
165
  File.foreach(path).grep(regex).first
147
166
  end
148
167
 
@@ -154,49 +173,38 @@ class StimulusReflex::SanityChecker
154
173
  Rails.root.join("yarn.lock")
155
174
  end
156
175
 
157
- def initializer_path
158
- @_initializer_path ||= Rails.root.join("config", "initializers", "stimulus_reflex.rb")
176
+ def initializer_missing?
177
+ File.exist?(Rails.root.join("config", "initializers", "stimulus_reflex.rb")) == false
159
178
  end
160
179
 
161
180
  def warn_and_exit(text)
162
- puts "WARNING:"
181
+ puts
182
+ puts "Heads up! 🔥"
183
+ puts
163
184
  puts text
164
- exit_with_info if StimulusReflex.config.on_failed_sanity_checks == :exit
165
- end
166
-
167
- def exit_with_info
168
185
  puts
169
-
170
- if File.exist?(initializer_path)
171
- puts <<~INFO
172
- If you know what you are doing and you want to start the application anyway,
173
- you can add the following directive to the StimulusReflex initializer,
174
- which is located at #{initializer_path}
175
-
176
- StimulusReflex.configure do |config|
177
- config.on_failed_sanity_checks = :warn
178
- end
179
-
180
- INFO
181
- else
186
+ if StimulusReflex.config.on_failed_sanity_checks == :exit
182
187
  puts <<~INFO
183
- If you know what you are doing and you want to start the application anyway,
184
- you can create a StimulusReflex initializer with the command:
185
-
186
- bundle exec rails generate stimulus_reflex:config
188
+ To ignore any warnings and start the application anyway, you can set the SKIP_SANITY_CHECK environment variable:
187
189
 
188
- Then open your initializer at
190
+ SKIP_SANITY_CHECK=true rails
189
191
 
190
- #{initializer_path}
191
-
192
- and then add the following directive:
192
+ To do this permanently, add the following directive to the StimulusReflex initializer:
193
193
 
194
194
  StimulusReflex.configure do |config|
195
195
  config.on_failed_sanity_checks = :warn
196
196
  end
197
197
 
198
198
  INFO
199
+ if initializer_missing?
200
+ puts <<~INFO
201
+ You can create a StimulusReflex initializer with the command:
202
+
203
+ bundle exec rails generate stimulus_reflex:initializer
204
+
205
+ INFO
206
+ end
207
+ exit false if Rails.env.test? == false
199
208
  end
200
- exit false
201
209
  end
202
210
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StimulusReflex
4
- VERSION = "3.5.0.pre1"
4
+ VERSION = "3.5.0.pre5"
5
5
  end
@@ -24,6 +24,7 @@ require "stimulus_reflex/broadcasters/broadcaster"
24
24
  require "stimulus_reflex/broadcasters/nothing_broadcaster"
25
25
  require "stimulus_reflex/broadcasters/page_broadcaster"
26
26
  require "stimulus_reflex/broadcasters/selector_broadcaster"
27
+ require "stimulus_reflex/broadcasters/update"
27
28
  require "stimulus_reflex/policies/reflex_invocation_policy"
28
29
  require "stimulus_reflex/utils/colorize"
29
30
  require "stimulus_reflex/utils/logger"