anycable-rails 1.0.0.rc1 → 1.0.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36b6e47a498bfc2d1156e4635a5c30f60258c925142c59ad837c1b6708f1ff73
4
- data.tar.gz: f27c94856df0db9d178537e8ac75598f8a355b338e725a80a5cb06a6e0ac610c
3
+ metadata.gz: d2c1f822cbb79135290b3c404544d937f0f083751657057b7bdd4445a33a95f1
4
+ data.tar.gz: ae4f5e42da49c8f668ee2cf56a434e30872d04cee9bc3596f914fb2e48404ac1
5
5
  SHA512:
6
- metadata.gz: 28b72e3f6a9950d3a95eb8d4f1c6a59f24a704ff63ac50384ffb2d22aa97c9f6b6e1f0c882a89cc6a0fd9ac22ea553a381514d56885f6f1cce41e7146153ab24
7
- data.tar.gz: ac7c402d2b57a332ced9372a4546709d6b41a0fb082c823d292b87c8b11e4bf741047cbc10258f68acd228712f0ca974b6723246bd3ddc689920f656b1488974
6
+ metadata.gz: 55bb99bacfdbd2b29120e29598aedc467f56325096602c7713bc2bfee9c4c40f826089ee4dd4d76e80d7171bdd1989db0d21c002edae0e429174509d24f8d836
7
+ data.tar.gz: 2ee8318ebd5c27dd95b21bd784c75d0d78da08538f1dd466235b889485d2229a4f35202b036a422466f38422905fbda16f84a028ecb3772e0669ce2bfc203dda
@@ -1,6 +1,27 @@
1
1
  # Change log
2
2
 
3
- ## 1.0.0.rc1 (2020-06-10)
3
+ ## master
4
+
5
+ ## 1.0.1 (2020-07-07)
6
+
7
+ - Fixed patching Action Cable testing classes. ([@palkan][])
8
+
9
+ ## 1.0.0 (2020-07-01)
10
+
11
+ - Support `rescue_from` in connections (Rails 6.1). ([@palkan][])
12
+
13
+ - Make AnyCable patches compatible with Action Cable testing. ([@palkan][])
14
+
15
+ - Do not add localhost `redis_url` to `anycable.yml` when Docker development method is chosen in `anycable:setup`. ([@palkan][])
16
+
17
+ - Fix connection identifiers deserialization regression. ([@palkan][])
18
+
19
+ Using non-strings or non-GlobalId-encoded objects was broken.
20
+
21
+ - Improve `anycable:setup` generator. ([@palkan][])
22
+
23
+ Update Docker snippet, do not enable persistent sessions automatically,
24
+ fix setting `config.action_cable.url` in environment configuration.
4
25
 
5
26
  - Add `state_attr_accessor` for channels. ([@palkan][])
6
27
 
@@ -35,7 +35,7 @@ module AnyCable
35
35
  # If the resulting object is a Hash, make it indifferent
36
36
  def deserialize(str, json: false)
37
37
  str.yield_self do |val|
38
- next unless val.is_a?(String)
38
+ next val unless val.is_a?(String)
39
39
 
40
40
  gval = GlobalID::Locator.locate(val)
41
41
  return gval if gval
@@ -21,6 +21,8 @@ module ActionCable
21
21
 
22
22
  attr_reader :socket
23
23
 
24
+ alias anycable_socket socket
25
+
24
26
  delegate :env, :session, to: :request
25
27
 
26
28
  class << self
@@ -196,3 +198,18 @@ module ActionCable
196
198
  # rubocop:enable Metrics/ClassLength
197
199
  end
198
200
  end
201
+
202
+ # Support rescue_from
203
+ # https://github.com/rails/rails/commit/d2571e560c62116f60429c933d0c41a0e249b58b
204
+ if ActionCable::Connection::Base.respond_to?(:rescue_from)
205
+ ActionCable::Connection::Base.prepend(Module.new do
206
+ def handle_channel_command(*)
207
+ super
208
+ rescue Exception => e # rubocop:disable Lint/RescueException
209
+ rescue_with_handler(e) || raise
210
+ false
211
+ end
212
+ end)
213
+ end
214
+
215
+ require "anycable/rails/actioncable/testing" if ::Rails.env.test?
@@ -15,16 +15,20 @@ module ActionCable
15
15
  return super unless socket.session
16
16
 
17
17
  super.tap do |req|
18
- req.env[Rack::RACK_SESSION] =
19
- AnyCable::Rails::SessionProxy.new(req.env[Rack::RACK_SESSION], socket.session)
18
+ req.env[::Rack::RACK_SESSION] =
19
+ AnyCable::Rails::SessionProxy.new(req.env[::Rack::RACK_SESSION], socket.session)
20
20
  end
21
21
  end
22
22
 
23
23
  def commit_session!
24
- return unless request_loaded? && request.session.loaded?
24
+ return unless request_loaded? && request.session.respond_to?(:loaded?) && request.session.loaded?
25
25
 
26
26
  socket.session = request.session.to_json
27
27
  end
28
28
  end
29
29
  end
30
30
  end
31
+
32
+ ::ActionCable::Connection::Base.prepend(
33
+ ::ActionCable::Connection::PersistentSession
34
+ )
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file contains patches to Action Cable testing modules
4
+
5
+ # Trigger autoload (if constant is defined)
6
+ begin
7
+ ActionCable::Channel::TestCase # rubocop:disable Lint/Void
8
+ ActionCable::Connection::TestCase # rubocop:disable Lint/Void
9
+ rescue NameError
10
+ return
11
+ end
12
+
13
+ ActionCable::Channel::ChannelStub.prepend(Module.new do
14
+ def subscribe_to_channel
15
+ # allocate @streams
16
+ streams
17
+ handle_subscribe
18
+ end
19
+ end)
20
+
21
+ ActionCable::Channel::ConnectionStub.prepend(Module.new do
22
+ def socket
23
+ @socket ||= AnyCable::Socket.new(env: {})
24
+ end
25
+
26
+ alias_method :anycable_socket, :socket
27
+ end)
28
+
29
+ ActionCable::Connection::TestConnection.prepend(Module.new do
30
+ def initialize(request)
31
+ @request = request
32
+ @cached_ids = {}
33
+ super
34
+ end
35
+ end)
@@ -5,18 +5,16 @@ module AnyCable
5
5
  module ChannelState
6
6
  module ClassMethods
7
7
  def state_attr_accessor(*names)
8
- return attr_accessor(*names) unless AnyCable::Rails.enabled?
9
-
10
8
  names.each do |name|
11
9
  channel_state_attributes << name
12
10
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
13
11
  def #{name}
14
12
  return @#{name} if instance_variable_defined?(:@#{name})
15
- @#{name} = AnyCable::Rails.deserialize(connection.socket.istate["#{name}"], json: true)
13
+ @#{name} = AnyCable::Rails.deserialize(connection.socket.istate["#{name}"], json: true) if connection.anycable_socket
16
14
  end
17
15
 
18
16
  def #{name}=(val)
19
- connection.socket.istate["#{name}"] = AnyCable::Rails.serialize(val, json: true)
17
+ connection.socket.istate["#{name}"] = AnyCable::Rails.serialize(val, json: true) if connection.anycable_socket
20
18
  instance_variable_set(:@#{name}, val)
21
19
  end
22
20
  RUBY
@@ -43,18 +43,18 @@ module AnyCable
43
43
 
44
44
  initializer "anycable.connection_factory", after: "action_cable.set_configs" do |app|
45
45
  ActiveSupport.on_load(:action_cable) do
46
+ # Add AnyCable patch method stub (we use it in ChannelState to distinguish between Action Cable and AnyCable)
47
+ # NOTE: Method could be already defined if patch was loaded manually
48
+ ActionCable::Connection::Base.attr_reader(:anycable_socket) unless ActionCable::Connection::Base.method_defined?(:anycable_socket)
49
+
50
+ app.config.to_prepare do
51
+ AnyCable.connection_factory = ActionCable.server.config.connection_class.call
52
+ end
53
+
46
54
  if AnyCable::Rails.enabled?
47
55
  require "anycable/rails/actioncable/connection"
48
-
49
56
  if AnyCable.config.persistent_session_enabled
50
57
  require "anycable/rails/actioncable/connection/persistent_session"
51
- ::ActionCable::Connection::Base.prepend(
52
- ::ActionCable::Connection::PersistentSession
53
- )
54
- end
55
-
56
- app.config.to_prepare do
57
- AnyCable.connection_factory = ActionCable.server.config.connection_class.call
58
58
  end
59
59
  end
60
60
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module AnyCable
4
4
  module Rails
5
- VERSION = "1.0.0.rc1"
5
+ VERSION = "1.0.1"
6
6
  end
7
7
  end
@@ -1,5 +1,5 @@
1
1
  Description:
2
- Install AnyCable-Go web server.
2
+ Install AnyCable-Go web server locally (the latest version by default).
3
3
 
4
4
  Example:
5
5
  rails generate anycable:download
@@ -9,8 +9,7 @@ module AnyCableRailsGenerators
9
9
 
10
10
  include WithOSHelpers
11
11
 
12
- # TODO: change to latest release
13
- VERSION = "1.0.0.preview1"
12
+ VERSION = "latest"
14
13
 
15
14
  class_option :bin_path,
16
15
  type: :string,
@@ -35,20 +34,27 @@ module AnyCableRailsGenerators
35
34
  private
36
35
 
37
36
  def release_url(version)
37
+ return latest_release_url(version) if version == "latest"
38
+
38
39
  if Gem::Version.new(version).segments.first >= 1
39
- new_release_url(version)
40
+ new_release_url("v#{version}")
40
41
  else
41
- legacy_release_url(version)
42
+ legacy_release_url("v#{version}")
42
43
  end
43
44
  end
44
45
 
45
46
  def legacy_release_url(version)
46
- "https://github.com/anycable/anycable-go/releases/download/v#{version}/" \
47
+ "https://github.com/anycable/anycable-go/releases/download/#{version}/" \
47
48
  "anycable-go-v#{version}-#{os_name}-#{cpu_name}"
48
49
  end
49
50
 
50
51
  def new_release_url(version)
51
- "https://github.com/anycable/anycable-go/releases/download/v#{version}/" \
52
+ "https://github.com/anycable/anycable-go/releases/download/#{version}/" \
53
+ "anycable-go-#{os_name}-#{cpu_name}"
54
+ end
55
+
56
+ def latest_release_url(version)
57
+ "https://github.com/anycable/anycable-go/releases/latest/download/" \
52
58
  "anycable-go-#{os_name}-#{cpu_name}"
53
59
  end
54
60
 
@@ -49,14 +49,18 @@ module AnyCableRailsGenerators
49
49
  environment(nil, env: :development) do
50
50
  <<~SNIPPET
51
51
  # Specify AnyCable WebSocket server URL to use by JS client
52
- config.action_cable.url = ENV.fetch("CABLE_URL", "ws://localhost:8080/cable") if AnyCable::Rails.enabled?
52
+ config.after_initialize do
53
+ config.action_cable.url = ActionCable.server.config.url = ENV.fetch("CABLE_URL", "ws://localhost:8080/cable") if AnyCable::Rails.enabled?
54
+ end
53
55
  SNIPPET
54
56
  end
55
57
 
56
58
  environment(nil, env: :production) do
57
59
  <<~SNIPPET
58
60
  # Specify AnyCable WebSocket server URL to use by JS client
59
- config.action_cable.url = ENV.fetch("CABLE_URL") if AnyCable::Rails.enabled?
61
+ config.after_initialize do
62
+ config.action_cable.url = ActionCable.server.config.url = ENV.fetch("CABLE_URL") if AnyCable::Rails.enabled?
63
+ end
60
64
  SNIPPET
61
65
  end
62
66
 
@@ -111,6 +115,12 @@ module AnyCableRailsGenerators
111
115
  say_status :info, "✅ config/initializers/anycable.rb with Devise configuration has been added"
112
116
  end
113
117
 
118
+ def stimulus_reflex
119
+ return unless stimulus_reflex?
120
+
121
+ say_status :help, "⚠️ Please, check out the documentation on using AnyCable with Stimulus Reflex: https://docs.anycable.io/v1/#/ruby/stimulus_reflex"
122
+ end
123
+
114
124
  def rubocop_compatibility
115
125
  return unless rubocop?
116
126
 
@@ -133,6 +143,10 @@ module AnyCableRailsGenerators
133
143
  !!gemfile_lock&.match?(/^\s+redis\b/)
134
144
  end
135
145
 
146
+ def webpacker?
147
+ !!gemfile_lock&.match?(/^\s+webpacker\b/)
148
+ end
149
+
136
150
  def rubocop?
137
151
  !!gemfile_lock&.match?(/^\s+rubocop\b/)
138
152
  end
@@ -149,21 +163,26 @@ module AnyCableRailsGenerators
149
163
  end
150
164
 
151
165
  def install_for_docker
166
+ # Remove localhost from configuraiton
167
+ gsub_file "config/anycable.yml", /^.*redis_url:.*localhost[^\n]+\n/, ""
168
+
152
169
  say_status :help, "️️⚠️ Docker development configuration could vary", :yellow
153
170
 
154
171
  say "Here is an example snippet for docker-compose.yml:"
155
172
  say <<~YML
156
173
  ─────────────────────────────────────────
157
174
  ws:
158
- image: anycable/anycable-go:1.0.0.preview1
175
+ image: anycable/anycable-go:1.0
159
176
  ports:
160
177
  - '8080:8080'
161
178
  environment:
179
+ ANYCABLE_HOST: "0.0.0.0"
162
180
  ANYCABLE_REDIS_URL: redis://redis:6379/0
163
181
  ANYCABLE_RPC_HOST: anycable:50051
182
+ ANYCABLE_DEBUG: 1
164
183
  depends_on:
165
- - anycable-rpc
166
- - redis
184
+ redis:
185
+ condition: service_healthy
167
186
 
168
187
  anycable:
169
188
  <<: *backend
@@ -172,8 +191,13 @@ module AnyCableRailsGenerators
172
191
  <<: *backend_environment
173
192
  ANYCABLE_REDIS_URL: redis://redis:6379/0
174
193
  ANYCABLE_RPC_HOST: 0.0.0.0:50051
194
+ ANYCABLE_DEBUG: 1
175
195
  ports:
176
196
  - '50051'
197
+ depends_on:
198
+ <<: *backend_depends_on
199
+ ws:
200
+ condition: service_started
177
201
  ─────────────────────────────────────────
178
202
  YML
179
203
  end
@@ -204,8 +228,8 @@ module AnyCableRailsGenerators
204
228
  def template_proc_files
205
229
  file_name = "Procfile.dev"
206
230
 
207
- if File.exist?(file_name)
208
- append_file file_name, 'anycable: bundle exec anycable --server-command "anycable-go --port 3334"'
231
+ if file_exists?(file_name)
232
+ append_file file_name, "anycable: bundle exec anycable\nws: anycable-go#{anycable_go_options}", force: true
209
233
  else
210
234
  say_status :help, "💡 We recommend using Hivemind to manage multiple processes in development 👉 https://github.com/DarthSim/hivemind", :yellow
211
235
 
@@ -242,5 +266,15 @@ module AnyCableRailsGenerators
242
266
  args << "--version #{opts[:version]}" if opts[:version]
243
267
  end.join(" ")
244
268
  end
269
+
270
+ def anycable_go_options
271
+ redis? ? " --port=8080" : " --port=8080 --broadcast_adapter=http"
272
+ end
273
+
274
+ def file_exists?(name)
275
+ in_root do
276
+ return File.file?(name)
277
+ end
278
+ end
245
279
  end
246
280
  end
@@ -0,0 +1,6 @@
1
+ server: bundle exec rails s
2
+ <%- if webpacker? -%>
3
+ assets: bundle exec bin/webpack-dev-server
4
+ <%- end -%>
5
+ anycable: bundle exec anycable
6
+ ws: anycable-go<%= anycable_go_options %>
@@ -12,8 +12,8 @@
12
12
  default: &default
13
13
  # Turn on/off access logs ("Started..." and "Finished...")
14
14
  access_logs_disabled: false
15
- # Persist "dirty" session between RPC calls (might be required for StimulusReflex apps)
16
- persistent_session_enabled: <%= stimulus_reflex? %>
15
+ # Persist "dirty" session between RPC calls (might be required for apps using stimulus_reflex <3.0)
16
+ # persistent_session_enabled: true
17
17
  # This is the host and the port to run AnyCable RPC server on.
18
18
  # You must configure your WebSocket server to connect to it, e.g.:
19
19
  # $ anycable-go --rpc-host="<rpc hostname>:50051"
@@ -30,10 +30,17 @@ default: &default
30
30
  # Use the same channel name for WebSocket server, e.g.:
31
31
  # $ anycable-go --redis-channel="__anycable__"
32
32
  redis_channel: "__anycable__"
33
+ <%- if redis? -%>
34
+ # You can use REDIS_URL env var to configure Redis URL.
35
+ # Localhost is used by default.
36
+ # redis_url: "redis://localhost:6379/1"
37
+ <%- end -%>
33
38
 
34
39
  development:
35
40
  <<: *default
36
- redis_url: "redis://localhost:6379/1"
41
+
42
+ test:
43
+ <<: *default
37
44
 
38
45
  production:
39
46
  <<: *default
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: anycable-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.rc1
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - palkan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-10 00:00:00.000000000 Z
11
+ date: 2020-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: anycable
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 1.0.0.rc1
19
+ version: 1.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 1.0.0.rc1
26
+ version: 1.0.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rails
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -81,19 +81,19 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '13.0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: rspec
84
+ name: rspec-rails
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: '3.4'
89
+ version: 4.0.0
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: '3.4'
96
+ version: 4.0.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rubocop
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -141,6 +141,7 @@ files:
141
141
  - lib/anycable/rails/actioncable/connection/persistent_session.rb
142
142
  - lib/anycable/rails/actioncable/connection/serializable_identification.rb
143
143
  - lib/anycable/rails/actioncable/remote_connections.rb
144
+ - lib/anycable/rails/actioncable/testing.rb
144
145
  - lib/anycable/rails/channel_state.rb
145
146
  - lib/anycable/rails/compatibility.rb
146
147
  - lib/anycable/rails/compatibility/rubocop.rb
@@ -160,7 +161,7 @@ files:
160
161
  - lib/generators/anycable/download/download_generator.rb
161
162
  - lib/generators/anycable/setup/USAGE
162
163
  - lib/generators/anycable/setup/setup_generator.rb
163
- - lib/generators/anycable/setup/templates/Procfile.dev
164
+ - lib/generators/anycable/setup/templates/Procfile.dev.tt
164
165
  - lib/generators/anycable/setup/templates/config/anycable.yml.tt
165
166
  - lib/generators/anycable/setup/templates/config/cable.yml.tt
166
167
  - lib/generators/anycable/setup/templates/config/initializers/anycable.rb.tt
@@ -185,9 +186,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
185
186
  version: '2.5'
186
187
  required_rubygems_version: !ruby/object:Gem::Requirement
187
188
  requirements:
188
- - - ">"
189
+ - - ">="
189
190
  - !ruby/object:Gem::Version
190
- version: 1.3.1
191
+ version: '0'
191
192
  requirements: []
192
193
  rubygems_version: 3.0.6
193
194
  signing_key:
@@ -1,3 +0,0 @@
1
- server: bin/rails server
2
- assets: bin/webpack-dev-server
3
- anycable: bundle exec anycable --server-command "anycable-go --port 3334"