cable_ready 5.0.0.pre9 → 5.0.0.pre10

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.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -1
  3. data/Gemfile.lock +119 -100
  4. data/README.md +2 -5
  5. data/app/assets/javascripts/cable_ready.js +457 -151
  6. data/app/assets/javascripts/cable_ready.min.js +1 -1
  7. data/app/assets/javascripts/cable_ready.min.js.map +1 -1
  8. data/app/assets/javascripts/cable_ready.umd.js +441 -165
  9. data/app/assets/javascripts/cable_ready.umd.min.js +1 -1
  10. data/app/assets/javascripts/cable_ready.umd.min.js.map +1 -1
  11. data/app/channels/cable_ready/stream.rb +7 -5
  12. data/app/helpers/cable_ready/view_helper.rb +58 -0
  13. data/app/jobs/cable_ready_broadcast_job.rb +9 -8
  14. data/app/models/concerns/cable_ready/updatable/collection_updatable_callbacks.rb +2 -0
  15. data/app/models/concerns/cable_ready/updatable/collections_registry.rb +2 -0
  16. data/app/models/concerns/cable_ready/updatable/model_updatable_callbacks.rb +5 -2
  17. data/app/models/concerns/cable_ready/updatable.rb +67 -19
  18. data/app/models/concerns/extend_has_many.rb +2 -0
  19. data/cable_ready.gemspec +4 -6
  20. data/lib/cable_ready/broadcaster.rb +2 -0
  21. data/lib/cable_ready/cable_car.rb +2 -0
  22. data/lib/cable_ready/channel.rb +12 -4
  23. data/lib/cable_ready/channels.rb +3 -1
  24. data/lib/cable_ready/config.rb +16 -2
  25. data/lib/cable_ready/engine.rb +19 -9
  26. data/lib/cable_ready/identifiable.rb +23 -5
  27. data/lib/cable_ready/importmap.rb +2 -0
  28. data/lib/cable_ready/installer.rb +224 -0
  29. data/lib/cable_ready/operation_builder.rb +1 -1
  30. data/lib/cable_ready/sanity_checker.rb +1 -31
  31. data/lib/cable_ready/version.rb +1 -1
  32. data/lib/cable_ready.rb +3 -8
  33. data/lib/cable_ready_helper.rb +13 -0
  34. data/lib/generators/cable_ready/channel_generator.rb +51 -12
  35. data/lib/generators/cable_ready/templates/config/initializers/cable_ready.rb +10 -6
  36. data/lib/install/action_cable.rb +144 -0
  37. data/lib/install/broadcaster.rb +109 -0
  38. data/lib/install/bundle.rb +54 -0
  39. data/lib/install/compression.rb +51 -0
  40. data/lib/install/config.rb +39 -0
  41. data/lib/install/development.rb +34 -0
  42. data/lib/install/esbuild.rb +101 -0
  43. data/lib/install/importmap.rb +96 -0
  44. data/lib/install/initializers.rb +15 -0
  45. data/lib/install/mrujs.rb +121 -0
  46. data/lib/install/npm_packages.rb +13 -0
  47. data/lib/install/shakapacker.rb +61 -0
  48. data/lib/install/spring.rb +54 -0
  49. data/lib/install/updatable.rb +34 -0
  50. data/lib/install/vite.rb +62 -0
  51. data/lib/install/webpacker.rb +81 -0
  52. data/lib/install/yarn.rb +56 -0
  53. data/lib/tasks/cable_ready/cable_ready.rake +249 -0
  54. data/package.json +28 -18
  55. data/{rollup.config.js → rollup.config.mjs} +9 -8
  56. data/web-test-runner.config.mjs +12 -0
  57. data/yarn.lock +2210 -404
  58. metadata +37 -161
  59. data/LATEST +0 -1
  60. data/app/helpers/cable_ready_helper.rb +0 -26
  61. data/lib/generators/cable_ready/helpers_generator.rb +0 -43
  62. data/lib/generators/cable_ready/initializer_generator.rb +0 -14
  63. data/test/dummy/app/channels/application_cable/channel.rb +0 -4
  64. data/test/dummy/app/channels/application_cable/connection.rb +0 -4
  65. data/test/dummy/app/controllers/application_controller.rb +0 -2
  66. data/test/dummy/app/helpers/application_helper.rb +0 -2
  67. data/test/dummy/app/jobs/application_job.rb +0 -7
  68. data/test/dummy/app/mailers/application_mailer.rb +0 -4
  69. data/test/dummy/app/models/application_record.rb +0 -3
  70. data/test/dummy/app/models/dugong.rb +0 -4
  71. data/test/dummy/app/models/global_idable_entity.rb +0 -16
  72. data/test/dummy/app/models/post.rb +0 -4
  73. data/test/dummy/app/models/section.rb +0 -6
  74. data/test/dummy/app/models/team.rb +0 -6
  75. data/test/dummy/app/models/topic.rb +0 -4
  76. data/test/dummy/app/models/user.rb +0 -7
  77. data/test/dummy/config/application.rb +0 -22
  78. data/test/dummy/config/boot.rb +0 -5
  79. data/test/dummy/config/environment.rb +0 -5
  80. data/test/dummy/config/environments/development.rb +0 -76
  81. data/test/dummy/config/environments/production.rb +0 -120
  82. data/test/dummy/config/environments/test.rb +0 -59
  83. data/test/dummy/config/initializers/application_controller_renderer.rb +0 -8
  84. data/test/dummy/config/initializers/assets.rb +0 -12
  85. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -8
  86. data/test/dummy/config/initializers/cable_ready.rb +0 -18
  87. data/test/dummy/config/initializers/content_security_policy.rb +0 -28
  88. data/test/dummy/config/initializers/cookies_serializer.rb +0 -5
  89. data/test/dummy/config/initializers/filter_parameter_logging.rb +0 -6
  90. data/test/dummy/config/initializers/inflections.rb +0 -16
  91. data/test/dummy/config/initializers/mime_types.rb +0 -4
  92. data/test/dummy/config/initializers/permissions_policy.rb +0 -11
  93. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  94. data/test/dummy/config/puma.rb +0 -43
  95. data/test/dummy/config/routes.rb +0 -3
  96. data/test/dummy/db/migrate/20210902154139_create_users.rb +0 -9
  97. data/test/dummy/db/migrate/20210902154153_create_posts.rb +0 -10
  98. data/test/dummy/db/migrate/20210904081930_create_topics.rb +0 -9
  99. data/test/dummy/db/migrate/20210904093607_create_sections.rb +0 -9
  100. data/test/dummy/db/migrate/20210913191735_create_teams.rb +0 -8
  101. data/test/dummy/db/migrate/20210913191759_add_team_reference_to_users.rb +0 -5
  102. data/test/dummy/db/migrate/20220329222959_create_dugongs.rb +0 -8
  103. data/test/dummy/db/migrate/20220329230221_create_active_storage_tables.active_storage.rb +0 -36
  104. data/test/dummy/db/schema.rb +0 -84
  105. data/test/dummy/test/models/dugong_test.rb +0 -7
  106. data/test/dummy/test/models/post_test.rb +0 -7
  107. data/test/dummy/test/models/section_test.rb +0 -7
  108. data/test/dummy/test/models/team_test.rb +0 -7
  109. data/test/dummy/test/models/topic_test.rb +0 -7
  110. data/test/dummy/test/models/user_test.rb +0 -7
  111. data/test/lib/cable_ready/cable_car_test.rb +0 -50
  112. data/test/lib/cable_ready/compoundable_test.rb +0 -26
  113. data/test/lib/cable_ready/helper_test.rb +0 -25
  114. data/test/lib/cable_ready/identifiable_test.rb +0 -69
  115. data/test/lib/cable_ready/operation_builder_test.rb +0 -189
  116. data/test/lib/cable_ready/updatable_test.rb +0 -135
  117. data/test/lib/generators/cable_ready/channel_generator_test.rb +0 -157
  118. data/test/support/generator_test_helpers.rb +0 -28
  119. data/test/test_helper.rb +0 -18
@@ -1,18 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/concern"
4
+
3
5
  module CableReady
4
6
  module Updatable
5
7
  extend ::ActiveSupport::Concern
6
8
 
7
9
  included do |base|
8
- if base < ActiveRecord::Base
10
+ if defined?(ActiveRecord) && base < ActiveRecord::Base
9
11
  include ExtendHasMany
10
12
 
11
13
  after_commit CollectionUpdatableCallbacks.new(:create), on: :create
12
14
  after_commit CollectionUpdatableCallbacks.new(:update), on: :update
13
15
  after_commit CollectionUpdatableCallbacks.new(:destroy), on: :destroy
14
16
 
15
- def self.enable_updates(*options)
17
+ def self.enable_updates(...)
18
+ warn "DEPRECATED: please use `enable_cable_ready_updates` instead. The `enable_updates` class method will be removed from a future version of CableReady 5"
19
+
20
+ enable_cable_ready_updates(...)
21
+ end
22
+
23
+ def self.skip_updates(...)
24
+ warn "DEPRECATED: please use `skip_cable_ready_updates` instead. The `skip_updates` class method will be removed from a future version of CableReady 5"
25
+
26
+ skip_cable_ready_updates(...)
27
+ end
28
+
29
+ def self.enable_cable_ready_updates(*options)
16
30
  options = options.extract_options!
17
31
  options = {
18
32
  on: [:create, :update, :destroy],
@@ -26,7 +40,7 @@ module CableReady
26
40
  after_commit(ModelUpdatableCallbacks.new(:destroy, enabled_operations), {on: :destroy, if: options[:if]})
27
41
  end
28
42
 
29
- def self.skip_updates
43
+ def self.skip_cable_ready_updates
30
44
  skip_updates_classes.push(self)
31
45
  yield
32
46
  ensure
@@ -39,15 +53,47 @@ module CableReady
39
53
 
40
54
  module ClassMethods
41
55
  def has_many(name, scope = nil, **options, &extension)
42
- option = options.delete(:enable_updates)
56
+ option = if options.has_key?(:enable_updates)
57
+ warn "DEPRECATED: please use `enable_cable_ready_updates` instead. The `enable_updates` option will be removed from a future version of CableReady 5"
58
+ options.delete(:enable_updates)
59
+ else
60
+ options.delete(:enable_cable_ready_updates)
61
+ end
62
+
63
+ descendants = options.delete(:descendants)
64
+
65
+ broadcast = option.present?
66
+ result = super
67
+ enrich_association_with_updates(name, option, descendants) if broadcast
68
+ result
69
+ end
70
+
71
+ def has_one(name, scope = nil, **options, &extension)
72
+ option = if options.has_key?(:enable_updates)
73
+ warn "DEPRECATED: please use `enable_cable_ready_updates` instead. The `enable_updates` option will be removed from a future version of CableReady 5"
74
+ options.delete(:enable_updates)
75
+ else
76
+ options.delete(:enable_cable_ready_updates)
77
+ end
78
+
79
+ descendants = options.delete(:descendants)
80
+
43
81
  broadcast = option.present?
44
82
  result = super
45
- enrich_association_with_updates(name, option) if broadcast
83
+ enrich_association_with_updates(name, option, descendants) if broadcast
46
84
  result
47
85
  end
48
86
 
49
87
  def has_many_attached(name, **options)
50
- option = options.delete(:enable_updates)
88
+ raise("ActiveStorage must be enabled to use has_many_attached") unless defined?(ActiveStorage)
89
+
90
+ option = if options.has_key?(:enable_updates)
91
+ warn "DEPRECATED: please use `enable_cable_ready_updates` instead. The `enable_updates` option will be removed from a future version of CableReady 5"
92
+ options.delete(:enable_updates)
93
+ else
94
+ options.delete(:enable_cable_ready_updates)
95
+ end
96
+
51
97
  broadcast = option.present?
52
98
  result = super
53
99
  enrich_attachments_with_updates(name, option) if broadcast
@@ -63,7 +109,7 @@ module CableReady
63
109
  broadcast_updates(identifier, model.respond_to?(:previous_changes) ? {changed: model.previous_changes.keys} : {})
64
110
  end
65
111
 
66
- def enrich_association_with_updates(name, option)
112
+ def enrich_association_with_updates(name, option, descendants = nil)
67
113
  reflection = reflect_on_association(name)
68
114
 
69
115
  inverse_of = reflection.inverse_of&.name&.to_s
@@ -76,16 +122,17 @@ module CableReady
76
122
 
77
123
  options = build_options(option)
78
124
 
79
- reflection.klass.send(:include, CableReady::Updatable) unless reflection.klass.respond_to?(:cable_ready_collections)
80
-
81
- reflection.klass.cable_ready_collections.register({
82
- klass: self,
83
- foreign_key: reflection.foreign_key,
84
- name: name,
85
- inverse_association: inverse_of,
86
- through_association: through_association,
87
- options: options
88
- })
125
+ [reflection.klass, *descendants&.map(&:to_s)&.map(&:constantize)].each do |klass|
126
+ klass.send(:include, CableReady::Updatable) unless klass.respond_to?(:cable_ready_collections)
127
+ klass.cable_ready_collections.register({
128
+ klass: self,
129
+ foreign_key: reflection.foreign_key,
130
+ name: name,
131
+ inverse_association: inverse_of,
132
+ through_association: through_association,
133
+ options: options
134
+ })
135
+ end
89
136
  end
90
137
 
91
138
  def enrich_attachments_with_updates(name, option)
@@ -111,7 +158,7 @@ module CableReady
111
158
 
112
159
  case option
113
160
  when TrueClass
114
- # proceed!
161
+ # proceed!
115
162
  when FalseClass
116
163
  options[:on] = []
117
164
  when Array
@@ -124,7 +171,7 @@ module CableReady
124
171
  when Proc
125
172
  options[:if] = option
126
173
  else
127
- raise ArgumentError, "Invalid enable_updates option #{option}"
174
+ raise ArgumentError, "Invalid enable_cable_ready_updates option #{option}"
128
175
  end
129
176
 
130
177
  options
@@ -132,6 +179,7 @@ module CableReady
132
179
 
133
180
  def broadcast_updates(model_class, options)
134
181
  return if skip_updates_classes.any? { |klass| klass >= self }
182
+ raise("ActionCable must be enabled to use Updatable") unless defined?(ActionCable)
135
183
  ActionCable.server.broadcast(model_class, options)
136
184
  end
137
185
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/concern"
4
+
3
5
  module ExtendHasMany
4
6
  extend ::ActiveSupport::Concern
5
7
 
data/cable_ready.gemspec CHANGED
@@ -12,31 +12,29 @@ Gem::Specification.new do |gem|
12
12
  gem.summary = "Out-of-Band Server Triggered DOM Operations"
13
13
 
14
14
  gem.files = Dir[
15
- "lib/**/*.rb",
15
+ "lib/**/*.{rb,rake}",
16
16
  "app/**/*.rb",
17
17
  "app/assets/javascripts/*",
18
18
  "bin/*",
19
19
  "[A-Z]*"
20
20
  ]
21
21
 
22
- gem.test_files = Dir["test/**/*.rb"]
22
+ gem.required_ruby_version = ">= 2.7.0"
23
23
 
24
24
  rails_version = ">= 5.2"
25
- gem.add_dependency "actioncable", rails_version
25
+
26
26
  gem.add_dependency "actionpack", rails_version
27
27
  gem.add_dependency "actionview", rails_version
28
- gem.add_dependency "activerecord", rails_version
29
28
  gem.add_dependency "activesupport", rails_version
30
29
  gem.add_dependency "railties", rails_version
31
-
32
30
  gem.add_dependency "thread-local", ">= 1.1.0"
33
31
 
34
32
  gem.add_development_dependency "magic_frozen_string_literal"
35
33
  gem.add_development_dependency "mocha"
36
34
  gem.add_development_dependency "pry"
37
35
  gem.add_development_dependency "pry-nav"
38
- gem.add_development_dependency "rails", rails_version
39
36
  gem.add_development_dependency "rake"
40
37
  gem.add_development_dependency "sqlite3"
38
+ gem.add_development_dependency "standard", "1.19.1"
41
39
  gem.add_development_dependency "standardrb"
42
40
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/concern"
4
+
3
5
  module CableReady
4
6
  module Broadcaster
5
7
  include Identifiable
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "thread/local"
4
+
3
5
  module CableReady
4
6
  class CableCar < OperationBuilder
5
7
  extend Thread::Local
@@ -5,6 +5,7 @@ module CableReady
5
5
  attr_reader :identifier
6
6
 
7
7
  def broadcast(clear: true)
8
+ raise("Action Cable must be enabled to use broadcast") unless defined?(ActionCable)
8
9
  clients_received = ActionCable.server.broadcast identifier, {
9
10
  "cableReady" => true,
10
11
  "operations" => operations_payload,
@@ -15,6 +16,7 @@ module CableReady
15
16
  end
16
17
 
17
18
  def broadcast_to(model, clear: true)
19
+ raise("Action Cable must be enabled to use broadcast_to") unless defined?(ActionCable)
18
20
  clients_received = identifier.broadcast_to model, {
19
21
  "cableReady" => true,
20
22
  "operations" => operations_payload,
@@ -24,13 +26,19 @@ module CableReady
24
26
  clients_received
25
27
  end
26
28
 
27
- def broadcast_later(clear: true)
28
- CableReadyBroadcastJob.perform_later(identifier: identifier, operations: operations_payload)
29
+ def broadcast_later(clear: true, queue: nil)
30
+ raise("Action Cable must be enabled to use broadcast_later") unless defined?(ActionCable)
31
+ CableReadyBroadcastJob
32
+ .set(queue: queue ? queue.to_sym : CableReady.config.broadcast_job_queue)
33
+ .perform_later(identifier: identifier, operations: operations_payload)
29
34
  reset! if clear
30
35
  end
31
36
 
32
- def broadcast_later_to(model, clear: true)
33
- CableReadyBroadcastJob.perform_later(identifier: identifier.name, operations: operations_payload, model: model)
37
+ def broadcast_later_to(model, clear: true, queue: nil)
38
+ raise("Action Cable must be enabled to use broadcast_later_to") unless defined?(ActionCable)
39
+ CableReadyBroadcastJob
40
+ .set(queue: queue ? queue.to_sym : CableReady.config.broadcast_job_queue)
41
+ .perform_later(identifier: identifier.name, operations: operations_payload, model: model)
34
42
  reset! if clear
35
43
  end
36
44
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "thread/local"
4
+
3
5
  module CableReady
4
6
  # This class is a thread local singleton: CableReady::Channels.instance
5
7
  # SEE: https://github.com/socketry/thread-local/tree/master/guides/getting-started
@@ -13,7 +15,7 @@ module CableReady
13
15
 
14
16
  def [](*keys)
15
17
  keys.select!(&:itself)
16
- identifier = keys.many? || (keys.one? && keys.first.respond_to?(:to_global_id)) ? compound(keys) : keys.pop
18
+ identifier = (keys.many? || (keys.one? && keys.first.respond_to?(:to_global_id))) ? compound(keys) : keys.pop
17
19
  @channels[identifier] ||= CableReady::Channel.new(identifier)
18
20
  end
19
21
 
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "monitor"
4
+ require "observer"
5
+ require "singleton"
6
+
3
7
  module CableReady
4
8
  # This class is a process level singleton shared by all threads: CableReady::Config.instance
5
9
  class Config
@@ -7,14 +11,23 @@ module CableReady
7
11
  include Observable
8
12
  include Singleton
9
13
 
10
- attr_accessor :on_failed_sanity_checks, :on_new_version_available
14
+ attr_accessor :on_failed_sanity_checks, :broadcast_job_queue, :precompile_assets
11
15
  attr_writer :verifier_key
12
16
 
17
+ def on_new_version_available
18
+ warn "NOTICE: The `config.on_new_version_available` option has been removed from the CableReady initializer. You can safely remove this option from your initializer."
19
+ end
20
+
21
+ def on_new_version_available=(_)
22
+ warn "NOTICE: The `config.on_new_version_available` option has been removed from the CableReady initializer. You can safely remove this option from your initializer."
23
+ end
24
+
13
25
  def initialize
14
26
  super
15
27
  @operation_names = Set.new(default_operation_names)
16
28
  @on_failed_sanity_checks = :exit
17
- @on_new_version_available = :ignore
29
+ @broadcast_job_queue = :default
30
+ @precompile_assets = true
18
31
  end
19
32
 
20
33
  def observers
@@ -72,6 +85,7 @@ module CableReady
72
85
  set_storage_item
73
86
  set_style
74
87
  set_styles
88
+ set_title
75
89
  set_value
76
90
  text_content
77
91
  ]).freeze
@@ -1,7 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "rails/engine"
2
4
 
3
5
  module CableReady
4
6
  class Engine < Rails::Engine
7
+ # If you don't want to precompile CableReady's assets (eg. because you're using webpack),
8
+ # you can do this in an initializer:
9
+ #
10
+ # config.after_initialize do
11
+ # config.assets.precompile -= CableReady::Engine::PRECOMPILE_ASSETS
12
+ # end
13
+ PRECOMPILE_ASSETS = %w[
14
+ cable_ready.js
15
+ cable_ready.min.js
16
+ cable_ready.min.js.map
17
+ cable_ready.umd.js
18
+ cable_ready.umd.min.js
19
+ cable_ready.umd.min.js.map
20
+ ]
21
+
5
22
  initializer "cable_ready.sanity_check" do
6
23
  SanityChecker.check! unless Rails.env.production?
7
24
  end
@@ -18,15 +35,8 @@ module CableReady
18
35
  end
19
36
 
20
37
  initializer "cable_ready.assets" do |app|
21
- if app.config.respond_to?(:assets)
22
- app.config.assets.precompile += %w[
23
- cable_ready.js
24
- cable_ready.min.js
25
- cable_ready.min.js.map
26
- cable_ready.umd.js
27
- cable_ready.umd.min.js
28
- cable_ready.umd.min.js.map
29
- ]
38
+ if app.config.respond_to?(:assets) && CableReady.config.precompile_assets
39
+ app.config.assets.precompile += PRECOMPILE_ASSETS
30
40
  end
31
41
  end
32
42
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "action_view"
4
+
3
5
  module CableReady
4
6
  module Identifiable
5
7
  def dom_id(record, prefix = nil)
@@ -9,9 +11,9 @@ module CableReady
9
11
 
10
12
  id = if record.respond_to?(:to_dom_id)
11
13
  record.to_dom_id
12
- elsif record.is_a?(ActiveRecord::Relation)
14
+ elsif ar_relation?(record)
13
15
  [prefix, record.model_name.plural].compact.join("_")
14
- elsif record.is_a?(ActiveRecord::Base)
16
+ elsif ar_base?(record)
15
17
  ActionView::RecordIdentifier.dom_id(record, prefix)
16
18
  else
17
19
  [prefix, record.to_s.strip].compact.join("_")
@@ -21,10 +23,26 @@ module CableReady
21
23
  end
22
24
 
23
25
  def identifiable?(obj)
24
- obj.respond_to?(:to_dom_selector) ||
26
+ (
27
+ obj.respond_to?(:to_dom_selector) ||
25
28
  obj.respond_to?(:to_dom_id) ||
26
- obj.is_a?(ActiveRecord::Relation) ||
27
- obj.is_a?(ActiveRecord::Base)
29
+ ar_relation?(obj) ||
30
+ ar_base?(obj)
31
+ )
32
+ end
33
+
34
+ private
35
+
36
+ def ar_relation?(obj)
37
+ return false if defined?(ActiveRecord).nil? || defined?(ActiveRecord::Relation).nil?
38
+
39
+ obj.is_a?(ActiveRecord::Relation)
40
+ end
41
+
42
+ def ar_base?(obj)
43
+ return false if defined?(ActiveRecord).nil? || defined?(ActiveRecord::Base).nil?
44
+
45
+ obj.is_a?(ActiveRecord::Base)
28
46
  end
29
47
  end
30
48
  end
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  pin "morphdom", to: "https://ga.jspm.io/npm:morphdom@2.6.1/dist/morphdom.js", preload: true
2
4
  pin "cable_ready", to: "cable_ready.min.js", preload: true
@@ -0,0 +1,224 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cable_ready/version"
4
+
5
+ ### general utilities
6
+
7
+ def fetch(step_path, file)
8
+ relative_path = step_path + file
9
+ location = template_src + relative_path
10
+
11
+ Pathname.new(location)
12
+ end
13
+
14
+ def complete_step(step)
15
+ create_file "tmp/cable_ready_installer/#{step}", verbose: false
16
+ end
17
+
18
+ def create_or_append(path, *args, &block)
19
+ FileUtils.touch(path)
20
+ append_file(path, *args, &block)
21
+ end
22
+
23
+ def current_template
24
+ ENV["LOCATION"].split("/").last.gsub(".rb", "")
25
+ end
26
+
27
+ def pack_path_missing?
28
+ return false unless pack_path.nil?
29
+ halt "#{friendly_pack_path} is missing. You need a valid application pack file to proceed."
30
+ end
31
+
32
+ def halt(message)
33
+ say "❌ #{message}", :red
34
+ create_file "tmp/cable_ready_installer/halt", verbose: false
35
+ end
36
+
37
+ def backup(path, delete: false)
38
+ if !path.exist?
39
+ yield
40
+ return
41
+ end
42
+
43
+ backup_path = Pathname.new("#{path}.bak")
44
+ old_path = path.relative_path_from(Rails.root).to_s
45
+ filename = path.to_path.split("/").last
46
+
47
+ if backup_path.exist?
48
+ if backup_path.read == path.read
49
+ path.delete if delete
50
+ yield
51
+ return
52
+ end
53
+ backup_path.delete
54
+ end
55
+
56
+ copy_file(path, backup_path, verbose: false)
57
+ path.delete if delete
58
+
59
+ yield
60
+
61
+ if path.read != backup_path.read
62
+ create_or_append(backups_path, "#{old_path}\n", verbose: false)
63
+ end
64
+ say "📦 #{old_path} backed up as #{filename}.bak"
65
+ end
66
+
67
+ def add_gem(name)
68
+ create_or_append(add_gem_list, "#{name}\n", verbose: false)
69
+ say "☑️ Added #{name} to the Gemfile"
70
+ end
71
+
72
+ def remove_gem(name)
73
+ create_or_append(remove_gem_list, "#{name}\n", verbose: false)
74
+ say "❎ Removed #{name} from Gemfile"
75
+ end
76
+
77
+ def add_package(name)
78
+ create_or_append(package_list, "#{name}\n", verbose: false)
79
+ say "☑️ Enqueued #{name} to be added to dependencies"
80
+ end
81
+
82
+ def add_dev_package(name)
83
+ create_or_append(dev_package_list, "#{name}\n", verbose: false)
84
+ say "☑️ Enqueued #{name} to be added to dev dependencies"
85
+ end
86
+
87
+ def drop_package(name)
88
+ create_or_append(drop_package_list, "#{name}\n", verbose: false)
89
+ say "❎ Enqueued #{name} to be removed from dependencies"
90
+ end
91
+
92
+ def gemfile_hash
93
+ Digest::MD5.hexdigest(gemfile_path.read)
94
+ end
95
+
96
+ ### memoized values
97
+
98
+ def cr_npm_version
99
+ @cr_npm_version ||= CableReady::VERSION.gsub(".pre", "-pre")
100
+ end
101
+
102
+ def package_json
103
+ @package_json ||= Rails.root.join("package.json")
104
+ end
105
+
106
+ def entrypoint
107
+ @entrypoint ||= File.read("tmp/cable_ready_installer/entrypoint")
108
+ end
109
+
110
+ def bundler
111
+ @bundler ||= File.read("tmp/cable_ready_installer/bundler")
112
+ end
113
+
114
+ def config_path
115
+ @config_path ||= Rails.root.join(entrypoint, "config")
116
+ end
117
+
118
+ def importmap_path
119
+ @importmap_path ||= Rails.root.join("config/importmap.rb")
120
+ end
121
+
122
+ def friendly_importmap_path
123
+ @friendly_importmap_path ||= importmap_path.relative_path_from(Rails.root).to_s
124
+ end
125
+
126
+ def pack
127
+ @pack ||= pack_path.read
128
+ end
129
+
130
+ def friendly_pack_path
131
+ @friendly_pack_path ||= pack_path.relative_path_from(Rails.root).to_s
132
+ end
133
+
134
+ def pack_path
135
+ @pack_path ||= [
136
+ Rails.root.join(entrypoint, "application.js"),
137
+ Rails.root.join(entrypoint, "packs/application.js"),
138
+ Rails.root.join(entrypoint, "entrypoints/application.js")
139
+ ].find(&:exist?)
140
+ end
141
+
142
+ def package_list
143
+ @package_list ||= Rails.root.join("tmp/cable_ready_installer/npm_package_list")
144
+ end
145
+
146
+ def dev_package_list
147
+ @dev_package_list ||= Rails.root.join("tmp/cable_ready_installer/npm_dev_package_list")
148
+ end
149
+
150
+ def drop_package_list
151
+ @drop_package_list ||= Rails.root.join("tmp/cable_ready_installer/drop_npm_package_list")
152
+ end
153
+
154
+ def template_src
155
+ @template_src ||= File.read("tmp/cable_ready_installer/template_src")
156
+ end
157
+
158
+ def controllers_path
159
+ @controllers_path ||= Rails.root.join(entrypoint, "controllers")
160
+ end
161
+
162
+ def gemfile_path
163
+ @gemfile_path ||= Rails.root.join("Gemfile")
164
+ end
165
+
166
+ def gemfile
167
+ @gemfile ||= gemfile_path.read
168
+ end
169
+
170
+ def prefix
171
+ # standard:disable Style/RedundantStringEscape
172
+ @prefix ||= {
173
+ "vite" => "..\/",
174
+ "webpacker" => "",
175
+ "shakapacker" => "",
176
+ "importmap" => "",
177
+ "esbuild" => ".\/"
178
+ }[bundler]
179
+ # standard:enable Style/RedundantStringEscape
180
+ end
181
+
182
+ def application_record_path
183
+ @application_record_path ||= Rails.root.join("app/models/application_record.rb")
184
+ end
185
+
186
+ def action_cable_initializer_path
187
+ @action_cable_initializer_path ||= Rails.root.join("config/initializers/action_cable.rb")
188
+ end
189
+
190
+ def action_cable_initializer_working_path
191
+ @action_cable_initializer_working_path ||= Rails.root.join(working, "action_cable.rb")
192
+ end
193
+
194
+ def development_path
195
+ @development_path ||= Rails.root.join("config/environments/development.rb")
196
+ end
197
+
198
+ def development_working_path
199
+ @development_working_path ||= Rails.root.join(working, "development.rb")
200
+ end
201
+
202
+ def backups_path
203
+ @backups_path ||= Rails.root.join("tmp/cable_ready_installer/backups")
204
+ end
205
+
206
+ def add_gem_list
207
+ @add_gem_list ||= Rails.root.join("tmp/cable_ready_installer/add_gem_list")
208
+ end
209
+
210
+ def remove_gem_list
211
+ @remove_gem_list ||= Rails.root.join("tmp/cable_ready_installer/remove_gem_list")
212
+ end
213
+
214
+ def options_path
215
+ @options_path ||= Rails.root.join("tmp/cable_ready_installer/options")
216
+ end
217
+
218
+ def options
219
+ @options ||= YAML.safe_load(File.read(options_path))
220
+ end
221
+
222
+ def working
223
+ @working ||= Rails.root.join("tmp/cable_ready_installer/working")
224
+ end
@@ -64,7 +64,7 @@ module CableReady
64
64
  rescue JSON::ParserError
65
65
  {}
66
66
  end
67
- @enqueued_operations.push(operations)
67
+ @enqueued_operations.concat(Array.wrap(operations))
68
68
  self
69
69
  end
70
70