stimulus_reflex 3.4.1 → 3.5.0.pre3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of stimulus_reflex might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +664 -495
- data/Gemfile.lock +99 -95
- data/LATEST +1 -0
- data/README.md +17 -16
- data/app/channels/stimulus_reflex/channel.rb +44 -75
- data/lib/generators/USAGE +1 -1
- data/lib/generators/stimulus_reflex/{config_generator.rb → initializer_generator.rb} +3 -3
- data/lib/generators/stimulus_reflex/stimulus_reflex_generator.rb +5 -4
- data/lib/generators/stimulus_reflex/templates/app/reflexes/%file_name%_reflex.rb.tt +3 -2
- data/lib/generators/stimulus_reflex/templates/app/reflexes/application_reflex.rb.tt +11 -4
- data/lib/generators/stimulus_reflex/templates/config/initializers/stimulus_reflex.rb +21 -1
- data/lib/stimulus_reflex/broadcasters/broadcaster.rb +22 -18
- data/lib/stimulus_reflex/broadcasters/nothing_broadcaster.rb +6 -1
- data/lib/stimulus_reflex/broadcasters/page_broadcaster.rb +3 -5
- data/lib/stimulus_reflex/broadcasters/selector_broadcaster.rb +22 -16
- data/lib/stimulus_reflex/broadcasters/update.rb +23 -0
- data/lib/stimulus_reflex/cable_ready_channels.rb +10 -2
- data/lib/stimulus_reflex/callbacks.rb +55 -5
- data/lib/stimulus_reflex/concern_enhancer.rb +37 -0
- data/lib/stimulus_reflex/configuration.rb +4 -1
- data/lib/stimulus_reflex/dataset.rb +34 -0
- data/lib/stimulus_reflex/element.rb +20 -13
- data/lib/stimulus_reflex/policies/reflex_invocation_policy.rb +28 -0
- data/lib/stimulus_reflex/reflex.rb +41 -21
- data/lib/stimulus_reflex/reflex_data.rb +79 -0
- data/lib/stimulus_reflex/reflex_factory.rb +31 -0
- data/lib/stimulus_reflex/request_parameters.rb +19 -0
- data/lib/stimulus_reflex/utils/attribute_builder.rb +17 -0
- data/lib/stimulus_reflex/{logger.rb → utils/logger.rb} +6 -4
- data/lib/stimulus_reflex/utils/sanity_checker.rb +210 -0
- data/lib/stimulus_reflex/version.rb +1 -1
- data/lib/stimulus_reflex.rb +10 -2
- data/lib/tasks/stimulus_reflex/install.rake +54 -15
- data/test/broadcasters/broadcaster_test.rb +0 -1
- data/test/broadcasters/broadcaster_test_case.rb +25 -1
- data/test/broadcasters/nothing_broadcaster_test.rb +14 -20
- data/test/broadcasters/page_broadcaster_test.rb +31 -29
- data/test/broadcasters/selector_broadcaster_test.rb +165 -55
- data/test/callbacks_test.rb +652 -0
- data/test/concern_enhancer_test.rb +54 -0
- data/test/element_test.rb +254 -0
- data/test/generators/stimulus_reflex_generator_test.rb +8 -0
- data/test/reflex_test.rb +12 -1
- data/test/test_helper.rb +25 -1
- data/test/tmp/app/reflexes/application_reflex.rb +10 -3
- data/test/tmp/app/reflexes/{user_reflex.rb → demo_reflex.rb} +4 -12
- metadata +65 -36
- data/lib/stimulus_reflex/sanity_checker.rb +0 -154
- data/package.json +0 -57
- data/stimulus_reflex.gemspec +0 -42
- data/tags +0 -156
- data/yarn.lock +0 -4687
@@ -0,0 +1,79 @@
|
|
1
|
+
class StimulusReflex::ReflexData
|
2
|
+
attr_reader :data
|
3
|
+
|
4
|
+
def initialize(data)
|
5
|
+
@data = data
|
6
|
+
end
|
7
|
+
|
8
|
+
def reflex_name
|
9
|
+
reflex_name = target.split("#").first
|
10
|
+
reflex_name = reflex_name.camelize
|
11
|
+
reflex_name.end_with?("Reflex") ? reflex_name : "#{reflex_name}Reflex"
|
12
|
+
end
|
13
|
+
|
14
|
+
def selectors
|
15
|
+
selectors = (data["selectors"] || []).select(&:present?)
|
16
|
+
selectors = data["selectors"] = ["body"] if selectors.blank?
|
17
|
+
selectors
|
18
|
+
end
|
19
|
+
|
20
|
+
def target
|
21
|
+
data["target"].to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_name
|
25
|
+
target.split("#").second
|
26
|
+
end
|
27
|
+
|
28
|
+
def arguments
|
29
|
+
(data["args"] || []).map { |arg| object_with_indifferent_access arg } || []
|
30
|
+
end
|
31
|
+
|
32
|
+
def url
|
33
|
+
data["url"].to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
def element
|
37
|
+
StimulusReflex::Element.new(data)
|
38
|
+
end
|
39
|
+
|
40
|
+
def permanent_attribute_name
|
41
|
+
data["permanentAttributeName"]
|
42
|
+
end
|
43
|
+
|
44
|
+
def form_data
|
45
|
+
Rack::Utils.parse_nested_query(data["formData"])
|
46
|
+
end
|
47
|
+
|
48
|
+
def form_params
|
49
|
+
form_data.deep_merge(data["params"] || {})
|
50
|
+
end
|
51
|
+
|
52
|
+
def reflex_id
|
53
|
+
data["reflexId"]
|
54
|
+
end
|
55
|
+
|
56
|
+
def tab_id
|
57
|
+
data["tabId"]
|
58
|
+
end
|
59
|
+
|
60
|
+
def xpath_controller
|
61
|
+
data["xpathController"]
|
62
|
+
end
|
63
|
+
|
64
|
+
def xpath_element
|
65
|
+
data["xpathElement"]
|
66
|
+
end
|
67
|
+
|
68
|
+
def reflex_controller
|
69
|
+
data["reflexController"]
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def object_with_indifferent_access(object)
|
75
|
+
return object.with_indifferent_access if object.respond_to?(:with_indifferent_access)
|
76
|
+
object.map! { |obj| object_with_indifferent_access obj } if object.is_a?(Array)
|
77
|
+
object
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class StimulusReflex::ReflexFactory
|
2
|
+
class << self
|
3
|
+
attr_reader :reflex_data
|
4
|
+
|
5
|
+
def create_reflex_from_data(channel, reflex_data)
|
6
|
+
@reflex_data = reflex_data
|
7
|
+
reflex_class.new(channel,
|
8
|
+
url: reflex_data.url,
|
9
|
+
element: reflex_data.element,
|
10
|
+
selectors: reflex_data.selectors,
|
11
|
+
method_name: reflex_data.method_name,
|
12
|
+
params: reflex_data.form_params,
|
13
|
+
client_attributes: {
|
14
|
+
reflex_id: reflex_data.reflex_id,
|
15
|
+
tab_id: reflex_data.tab_id,
|
16
|
+
xpath_controller: reflex_data.xpath_controller,
|
17
|
+
xpath_element: reflex_data.xpath_element,
|
18
|
+
reflex_controller: reflex_data.reflex_controller,
|
19
|
+
permanent_attribute_name: reflex_data.permanent_attribute_name
|
20
|
+
})
|
21
|
+
end
|
22
|
+
|
23
|
+
def reflex_class
|
24
|
+
reflex_data.reflex_name.constantize.tap { |klass| raise ArgumentError.new("#{reflex_name} is not a StimulusReflex::Reflex") unless is_reflex?(klass) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def is_reflex?(klass)
|
28
|
+
klass.ancestors.include? StimulusReflex::Reflex
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module StimulusReflex
|
2
|
+
class RequestParameters
|
3
|
+
def initialize(params:, req:, url:)
|
4
|
+
@params = params
|
5
|
+
@req = req
|
6
|
+
@url = url
|
7
|
+
end
|
8
|
+
|
9
|
+
def apply!
|
10
|
+
path_params = Rails.application.routes.recognize_path_with_request(@req, @url, @req.env[:extras] || {})
|
11
|
+
path_params[:controller] = path_params[:controller].force_encoding("UTF-8")
|
12
|
+
path_params[:action] = path_params[:action].force_encoding("UTF-8")
|
13
|
+
|
14
|
+
@req.env.merge(ActionDispatch::Http::Parameters::PARAMETERS_KEY => path_params)
|
15
|
+
@req.env["action_dispatch.request.parameters"] = @req.parameters.merge(@params)
|
16
|
+
@req.tap { |r| r.session.send :load! }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -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,22 +2,24 @@
|
|
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
|
16
|
+
def log_all_operations
|
13
17
|
return unless config_logging.instance_of?(Proc)
|
14
18
|
|
15
|
-
puts
|
16
19
|
reflex.broadcaster.operations.each do
|
17
|
-
|
20
|
+
logger.info instance_eval(&config_logging) + "\e[0m"
|
18
21
|
@current_operation += 1
|
19
22
|
end
|
20
|
-
puts
|
21
23
|
end
|
22
24
|
|
23
25
|
private
|
@@ -0,0 +1,210 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class StimulusReflex::SanityChecker
|
4
|
+
LATEST_VERSION_FORMAT = /^(\d+\.\d+\.\d+)$/
|
5
|
+
NODE_VERSION_FORMAT = /(\d+\.\d+\.\d+.*):/
|
6
|
+
JSON_VERSION_FORMAT = /(\d+\.\d+\.\d+.*)"/
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def check!
|
10
|
+
return if ENV["SKIP_SANITY_CHECK"]
|
11
|
+
return if StimulusReflex.config.on_failed_sanity_checks == :ignore
|
12
|
+
return if called_by_installer?
|
13
|
+
return if called_by_generate_config?
|
14
|
+
return if called_by_rake?
|
15
|
+
|
16
|
+
instance = new
|
17
|
+
instance.check_caching_enabled
|
18
|
+
instance.check_package_versions_match
|
19
|
+
# instance.check_default_url_config
|
20
|
+
instance.check_new_version_available
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def called_by_installer?
|
26
|
+
Rake.application.top_level_tasks.include? "stimulus_reflex:install"
|
27
|
+
rescue
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
31
|
+
def called_by_generate_config?
|
32
|
+
ARGV.include? "stimulus_reflex:initializer"
|
33
|
+
end
|
34
|
+
|
35
|
+
def called_by_rake?
|
36
|
+
File.basename($PROGRAM_NAME) == "rake"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def check_caching_enabled
|
41
|
+
if caching_not_enabled?
|
42
|
+
warn_and_exit <<~WARN
|
43
|
+
👉 StimulusReflex requires caching to be enabled. Caching allows the session to be modified during ActionCable requests.
|
44
|
+
|
45
|
+
To enable caching in development, run:
|
46
|
+
|
47
|
+
rails dev:cache
|
48
|
+
WARN
|
49
|
+
end
|
50
|
+
|
51
|
+
if using_null_store?
|
52
|
+
warn_and_exit <<~WARN
|
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.
|
56
|
+
WARN
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def check_default_url_config
|
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
|
+
|
66
|
+
You can set your URL options in config/environments/#{Rails.env}.rb
|
67
|
+
|
68
|
+
config.action_controller.default_url_options = {host: "localhost", port: 3000}
|
69
|
+
#{"config.action_mailer.default_url_options = {host: \"localhost\", port: 3000}\n" if defined?(ActionMailer)}
|
70
|
+
Please update every environment with the appropriate URL. Typically, no port is necessary in production.
|
71
|
+
|
72
|
+
WARN
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def check_package_versions_match
|
77
|
+
if npm_version.nil?
|
78
|
+
warn_and_exit <<~WARN
|
79
|
+
👉 Can't locate the stimulus_reflex npm package.
|
80
|
+
|
81
|
+
yarn add stimulus_reflex@#{gem_version}
|
82
|
+
|
83
|
+
Either add it to your package.json as a dependency or use "yarn link stimulus_reflex" if you are doing development.
|
84
|
+
WARN
|
85
|
+
end
|
86
|
+
|
87
|
+
if package_version_mismatch?
|
88
|
+
warn_and_exit <<~WARN
|
89
|
+
👉 The stimulus_reflex npm package version (#{npm_version}) does not match the Rubygem version (#{gem_version}).
|
90
|
+
|
91
|
+
To update the stimulus_reflex npm package:
|
92
|
+
|
93
|
+
yarn upgrade stimulus_reflex@#{gem_version}
|
94
|
+
WARN
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def check_new_version_available
|
99
|
+
return if StimulusReflex.config.on_new_version_available == :ignore
|
100
|
+
return if Rails.env.development? == false
|
101
|
+
return if using_preview_release?
|
102
|
+
begin
|
103
|
+
latest_version = URI.open("https://raw.githubusercontent.com/stimulusreflex/stimulus_reflex/master/LATEST", open_timeout: 1, read_timeout: 1).read.strip
|
104
|
+
if latest_version != StimulusReflex::VERSION
|
105
|
+
puts <<~WARN
|
106
|
+
|
107
|
+
👉 There is a new version of StimulusReflex available!
|
108
|
+
Current: #{StimulusReflex::VERSION} Latest: #{latest_version}
|
109
|
+
|
110
|
+
If you upgrade, it is very important that you update BOTH Gemfile and package.json
|
111
|
+
Then, run `bundle install && yarn install` to update to #{latest_version}.
|
112
|
+
|
113
|
+
WARN
|
114
|
+
exit if StimulusReflex.config.on_new_version_available == :exit
|
115
|
+
end
|
116
|
+
rescue
|
117
|
+
puts "👉 StimulusReflex #{StimulusReflex::VERSION} update check skipped: connection timeout"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def caching_not_enabled?
|
122
|
+
Rails.application.config.action_controller.perform_caching == false
|
123
|
+
end
|
124
|
+
|
125
|
+
def using_null_store?
|
126
|
+
Rails.application.config.cache_store == :null_store
|
127
|
+
end
|
128
|
+
|
129
|
+
def default_url_config_set?
|
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
|
135
|
+
end
|
136
|
+
|
137
|
+
def package_version_mismatch?
|
138
|
+
npm_version != gem_version
|
139
|
+
end
|
140
|
+
|
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
|
145
|
+
end
|
146
|
+
|
147
|
+
def gem_version
|
148
|
+
@_gem_version ||= StimulusReflex::VERSION.gsub(".pre", "-pre")
|
149
|
+
end
|
150
|
+
|
151
|
+
def npm_version
|
152
|
+
@_npm_version ||= find_npm_version
|
153
|
+
end
|
154
|
+
|
155
|
+
def find_npm_version
|
156
|
+
if (match = search_file(package_json_path, regex: /version/))
|
157
|
+
match[JSON_VERSION_FORMAT, 1]
|
158
|
+
elsif (match = search_file(yarn_lock_path, regex: /^stimulus_reflex/))
|
159
|
+
match[NODE_VERSION_FORMAT, 1]
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def search_file(path, regex:)
|
164
|
+
return if File.exist?(path) == false
|
165
|
+
File.foreach(path).grep(regex).first
|
166
|
+
end
|
167
|
+
|
168
|
+
def package_json_path
|
169
|
+
Rails.root.join("node_modules", "stimulus_reflex", "package.json")
|
170
|
+
end
|
171
|
+
|
172
|
+
def yarn_lock_path
|
173
|
+
Rails.root.join("yarn.lock")
|
174
|
+
end
|
175
|
+
|
176
|
+
def initializer_missing?
|
177
|
+
File.exist?(Rails.root.join("config", "initializers", "stimulus_reflex.rb")) == false
|
178
|
+
end
|
179
|
+
|
180
|
+
def warn_and_exit(text)
|
181
|
+
puts
|
182
|
+
puts "Heads up! 🔥"
|
183
|
+
puts
|
184
|
+
puts text
|
185
|
+
puts
|
186
|
+
if StimulusReflex.config.on_failed_sanity_checks == :exit
|
187
|
+
puts <<~INFO
|
188
|
+
To ignore any warnings and start the application anyway, you can set the SKIP_SANITY_CHECK environment variable:
|
189
|
+
|
190
|
+
SKIP_SANITY_CHECK=true rails
|
191
|
+
|
192
|
+
To do this permanently, add the following directive to the StimulusReflex initializer:
|
193
|
+
|
194
|
+
StimulusReflex.configure do |config|
|
195
|
+
config.on_failed_sanity_checks = :warn
|
196
|
+
end
|
197
|
+
|
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
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
data/lib/stimulus_reflex.rb
CHANGED
@@ -1,26 +1,34 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "uri"
|
4
|
+
require "open-uri"
|
4
5
|
require "rack"
|
5
6
|
require "rails/engine"
|
6
7
|
require "active_support/all"
|
7
8
|
require "action_dispatch"
|
8
9
|
require "action_cable"
|
10
|
+
require "action_view"
|
9
11
|
require "nokogiri"
|
10
12
|
require "cable_ready"
|
11
13
|
require "stimulus_reflex/version"
|
12
14
|
require "stimulus_reflex/cable_ready_channels"
|
15
|
+
require "stimulus_reflex/concern_enhancer"
|
13
16
|
require "stimulus_reflex/configuration"
|
14
17
|
require "stimulus_reflex/callbacks"
|
18
|
+
require "stimulus_reflex/request_parameters"
|
15
19
|
require "stimulus_reflex/reflex"
|
20
|
+
require "stimulus_reflex/reflex_data"
|
21
|
+
require "stimulus_reflex/reflex_factory"
|
16
22
|
require "stimulus_reflex/element"
|
17
|
-
require "stimulus_reflex/sanity_checker"
|
18
23
|
require "stimulus_reflex/broadcasters/broadcaster"
|
19
24
|
require "stimulus_reflex/broadcasters/nothing_broadcaster"
|
20
25
|
require "stimulus_reflex/broadcasters/page_broadcaster"
|
21
26
|
require "stimulus_reflex/broadcasters/selector_broadcaster"
|
27
|
+
require "stimulus_reflex/broadcasters/update"
|
28
|
+
require "stimulus_reflex/policies/reflex_invocation_policy"
|
22
29
|
require "stimulus_reflex/utils/colorize"
|
23
|
-
require "stimulus_reflex/logger"
|
30
|
+
require "stimulus_reflex/utils/logger"
|
31
|
+
require "stimulus_reflex/utils/sanity_checker"
|
24
32
|
|
25
33
|
module StimulusReflex
|
26
34
|
class Engine < Rails::Engine
|
@@ -4,7 +4,7 @@ require "fileutils"
|
|
4
4
|
require "stimulus_reflex/version"
|
5
5
|
|
6
6
|
namespace :stimulus_reflex do
|
7
|
-
desc "Install StimulusReflex in this application"
|
7
|
+
desc "✨ Install StimulusReflex in this application"
|
8
8
|
task install: :environment do
|
9
9
|
system "rails dev:cache" unless Rails.root.join("tmp", "caching-dev.txt").exist?
|
10
10
|
gem_version = StimulusReflex::VERSION.gsub(".pre", "-pre")
|
@@ -25,8 +25,8 @@ namespace :stimulus_reflex do
|
|
25
25
|
.map { |path| Rails.root.join(path) }
|
26
26
|
.first
|
27
27
|
|
28
|
-
puts "Updating #{filepath}"
|
29
|
-
lines = File.
|
28
|
+
puts "✨ Updating #{filepath}"
|
29
|
+
lines = File.readlines(filepath)
|
30
30
|
|
31
31
|
unless lines.find { |line| line.start_with?("import StimulusReflex") }
|
32
32
|
matches = lines.select { |line| line =~ /\A(require|import)/ }
|
@@ -44,34 +44,73 @@ namespace :stimulus_reflex do
|
|
44
44
|
end
|
45
45
|
|
46
46
|
initialize_line = lines.find { |line| line.start_with?("StimulusReflex.initialize") }
|
47
|
-
lines << "
|
47
|
+
lines << "application.consumer = consumer\n"
|
48
|
+
lines << "StimulusReflex.initialize(application, { controller, isolate: true })\n" unless initialize_line
|
48
49
|
lines << "StimulusReflex.debug = process.env.RAILS_ENV === 'development'\n" unless initialize_line
|
49
|
-
File.
|
50
|
+
File.write(filepath, lines.join)
|
50
51
|
|
52
|
+
puts
|
53
|
+
puts "✨ Updating config/environments/development.rb"
|
51
54
|
filepath = Rails.root.join("config/environments/development.rb")
|
52
|
-
lines = File.
|
55
|
+
lines = File.readlines(filepath)
|
53
56
|
unless lines.find { |line| line.include?("config.session_store") }
|
54
|
-
lines.
|
55
|
-
|
57
|
+
matches = lines.select { |line| line =~ /\A(Rails.application.configure do)/ }
|
58
|
+
lines.insert lines.index(matches.last).to_i + 1, " config.session_store :cache_store\n\n"
|
59
|
+
puts
|
60
|
+
puts "✨ Using :cache_store for session storage. We recommend switching to Redis for cache and session storage."
|
61
|
+
puts
|
62
|
+
puts "https://docs.stimulusreflex.com/appendices/deployment#use-redis-as-your-cache-store"
|
63
|
+
File.write(filepath, lines.join)
|
64
|
+
end
|
65
|
+
|
66
|
+
if defined?(ActionMailer)
|
67
|
+
lines = File.readlines(filepath)
|
68
|
+
unless lines.find { |line| line.include?("config.action_mailer.default_url_options") }
|
69
|
+
matches = lines.select { |line| line =~ /\A(Rails.application.configure do)/ }
|
70
|
+
lines.insert lines.index(matches.last).to_i + 1, " config.action_mailer.default_url_options = {host: \"localhost\", port: 3000}\n\n"
|
71
|
+
File.write(filepath, lines.join)
|
72
|
+
end
|
56
73
|
end
|
57
74
|
|
75
|
+
lines = File.readlines(filepath)
|
76
|
+
unless lines.find { |line| line.include?("config.action_controller.default_url_options") }
|
77
|
+
matches = lines.select { |line| line =~ /\A(Rails.application.configure do)/ }
|
78
|
+
lines.insert lines.index(matches.last).to_i + 1, " config.action_controller.default_url_options = {host: \"localhost\", port: 3000}\n"
|
79
|
+
File.write(filepath, lines.join)
|
80
|
+
end
|
81
|
+
|
82
|
+
puts
|
83
|
+
puts "✨ Updating config/cable.yml to use Redis in development"
|
58
84
|
filepath = Rails.root.join("config/cable.yml")
|
59
|
-
lines = File.
|
85
|
+
lines = File.readlines(filepath)
|
60
86
|
if lines[1].include?("adapter: async")
|
61
87
|
lines.delete_at 1
|
62
88
|
lines.insert 1, " adapter: redis\n"
|
63
89
|
lines.insert 2, " url: <%= ENV.fetch(\"REDIS_URL\") { \"redis://localhost:6379/1\" } %>\n"
|
64
|
-
lines.insert 3, " channel_prefix: " + File.basename(Rails.root.to_s).underscore + "_development\n"
|
65
|
-
File.
|
90
|
+
lines.insert 3, " channel_prefix: " + File.basename(Rails.root.to_s).tr("\\", "").tr("-. ", "_").underscore + "_development\n"
|
91
|
+
File.write(filepath, lines.join)
|
66
92
|
end
|
67
93
|
|
94
|
+
puts
|
95
|
+
puts "✨ Generating default StimulusReflex and CableReady configuration files"
|
96
|
+
puts
|
97
|
+
system "bundle exec rails generate stimulus_reflex:initializer"
|
98
|
+
system "bundle exec rails generate cable_ready:initializer"
|
99
|
+
system "bundle exec rails generate cable_ready:helpers"
|
100
|
+
|
101
|
+
puts
|
102
|
+
puts "✨ Generating ApplicationReflex class and Stimulus controllers, plus an example Reflex class and controller"
|
103
|
+
puts
|
68
104
|
system "bundle exec rails generate stimulus_reflex example"
|
69
|
-
puts "Generating default StimulusReflex configuration file into your application config/initializers directory"
|
70
|
-
system "bundle exec rails generate stimulus_reflex:config"
|
71
105
|
|
72
106
|
puts
|
73
|
-
puts "StimulusReflex and CableReady have been successfully installed!"
|
74
|
-
puts
|
107
|
+
puts "🎉 StimulusReflex and CableReady have been successfully installed! 🎉"
|
108
|
+
puts
|
109
|
+
puts "https://docs.stimulusreflex.com/hello-world/quickstart"
|
110
|
+
puts
|
111
|
+
puts "😊 The fastest way to get support is to say hello on Discord:"
|
112
|
+
puts
|
113
|
+
puts "https://discord.gg/stimulus-reflex"
|
75
114
|
puts
|
76
115
|
end
|
77
116
|
end
|
@@ -7,6 +7,5 @@ class StimulusReflex::BroadcasterTest < StimulusReflex::BroadcasterTestCase
|
|
7
7
|
broadcaster = StimulusReflex::Broadcaster.new(@reflex)
|
8
8
|
|
9
9
|
assert_raises(NotImplementedError) { broadcaster.broadcast }
|
10
|
-
assert_raises(NotImplementedError) { broadcaster.broadcast_message(subject: "Test") }
|
11
10
|
end
|
12
11
|
end
|
@@ -5,11 +5,35 @@ require_relative "../test_helper"
|
|
5
5
|
class StimulusReflex::BroadcasterTestCase < ActionCable::Channel::TestCase
|
6
6
|
tests StimulusReflex::Channel
|
7
7
|
|
8
|
+
def assert_broadcast_on(stream, data, &block)
|
9
|
+
serialized_msg = ActiveSupport::JSON.decode(ActiveSupport::JSON.encode(data))
|
10
|
+
|
11
|
+
new_messages = broadcasts(stream)
|
12
|
+
if block
|
13
|
+
old_messages = new_messages
|
14
|
+
clear_messages(stream)
|
15
|
+
|
16
|
+
yield
|
17
|
+
new_messages = broadcasts(stream)
|
18
|
+
clear_messages(stream)
|
19
|
+
|
20
|
+
(old_messages + new_messages).each { |m| pubsub_adapter.broadcast(stream, m) }
|
21
|
+
end
|
22
|
+
|
23
|
+
message = new_messages.find { |msg| ActiveSupport::JSON.decode(msg) == serialized_msg }
|
24
|
+
|
25
|
+
unless message
|
26
|
+
puts "\n\n#{ActiveSupport::JSON.decode(new_messages.first)}\n#{data}\n\n"
|
27
|
+
end
|
28
|
+
|
29
|
+
assert message, "No messages sent with #{data} to #{stream}"
|
30
|
+
end
|
31
|
+
|
8
32
|
setup do
|
9
33
|
stub_connection(session_id: SecureRandom.uuid)
|
10
34
|
def connection.env
|
11
35
|
@env ||= {}
|
12
36
|
end
|
13
|
-
@reflex = StimulusReflex::Reflex.new(subscribe, url: "https://test.stimulusreflex.com")
|
37
|
+
@reflex = StimulusReflex::Reflex.new(subscribe, url: "https://test.stimulusreflex.com", client_attributes: {reflex_id: "666"})
|
14
38
|
end
|
15
39
|
end
|
@@ -3,33 +3,27 @@
|
|
3
3
|
require_relative "broadcaster_test_case"
|
4
4
|
|
5
5
|
class StimulusReflex::NothingBroadcasterTest < StimulusReflex::BroadcasterTestCase
|
6
|
-
test "broadcasts a
|
6
|
+
test "broadcasts a nothing morph when called" do
|
7
7
|
broadcaster = StimulusReflex::NothingBroadcaster.new(@reflex)
|
8
8
|
|
9
9
|
expected = {
|
10
10
|
"cableReady" => true,
|
11
|
-
"operations" =>
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
}
|
24
|
-
}
|
25
|
-
}
|
26
|
-
}
|
27
|
-
]
|
28
|
-
}
|
11
|
+
"operations" => [
|
12
|
+
{
|
13
|
+
"name" => "stimulus-reflex:morph-nothing",
|
14
|
+
"payload" => {},
|
15
|
+
"stimulusReflex" => {
|
16
|
+
"some" => "data",
|
17
|
+
"morph" => "nothing"
|
18
|
+
},
|
19
|
+
"reflexId" => "666",
|
20
|
+
"operation" => "dispatchEvent"
|
21
|
+
}
|
22
|
+
]
|
29
23
|
}
|
30
24
|
|
31
25
|
assert_broadcast_on @reflex.stream_name, expected do
|
32
|
-
broadcaster.broadcast nil, some: :data
|
26
|
+
broadcaster.broadcast nil, {some: :data}
|
33
27
|
end
|
34
28
|
end
|
35
29
|
end
|