stimulus_reflex 3.4.1 → 3.5.0.pre3
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 +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
|