Skip to content

Commit

Permalink
refactor: avoid Action Cable "hard" monkey-patching
Browse files Browse the repository at this point in the history
This PR changes the (historical) way of making Action Cable compatible with AnyCable:

- Extend (via #prepend) instead of reopening classes
- Preserve the original functionality (by using #anycabled? checks where necessary)

Closes #165
  • Loading branch information
palkan committed Feb 18, 2022
1 parent dfc5ecd commit 9b95e7a
Show file tree
Hide file tree
Showing 23 changed files with 497 additions and 499 deletions.
9 changes: 5 additions & 4 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ source 'https://rubygems.org'

gemspec

gem "pry-byebug", platform: :mri
gem "debug", platform: :mri

local_gemfile = "#{File.dirname(__FILE__)}/Gemfile.local"

Expand All @@ -11,7 +11,8 @@ eval_gemfile "gemfiles/rubocop.gemfile"
if File.exist?(local_gemfile)
eval(File.read(local_gemfile)) # rubocop:disable Lint/Eval
else
gem 'sqlite3', '~> 1.3'
gem 'actioncable', '~> 6.0'
gem 'activerecord'
gem 'actioncable', '~> 7.0'
end

gem 'sqlite3', '~> 1.3'
gem 'activerecord'
47 changes: 47 additions & 0 deletions lib/anycable/rails/action_cable_ext/channel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

require "action_cable/channel"

ActionCable::Channel::Base.prepend(Module.new do
def subscribe_to_channel(force: false)
return if anycabled? && !force
super()
end

def handle_subscribe
subscribe_to_channel(force: true)
end

def start_periodic_timers
super unless anycabled?
end

def stop_periodic_timers
super unless anycabled?
end

def stream_from(broadcasting, _callback = nil, _options = {})
return super unless anycabled?

connection.anycable_socket.subscribe identifier, broadcasting
end

def stop_stream_from(broadcasting)
return super unless anycabled?

connection.anycable_socket.unsubscribe identifier, broadcasting
end

def stop_all_streams
return super unless anycabled?

connection.anycable_socket.unsubscribe_from_all identifier
end

private

def anycabled?
# Use instance variable check here for testing compatibility
connection.instance_variable_defined?(:@anycable_socket)
end
end)
30 changes: 30 additions & 0 deletions lib/anycable/rails/action_cable_ext/connection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

require "action_cable/connection"
require "anycable/rails/connections/serializable_identification"

ActionCable::Connection::Base.include(AnyCable::Rails::Connections::SerializableIdentification)
ActionCable::Connection::Base.prepend(Module.new do
attr_reader :anycable_socket
attr_accessor :anycable_request_builder

# In AnyCable, we lazily populate env by passing it through the middleware chain,
# so we access it via #request
def env
return super unless anycabled?

request.env
end

def anycabled?
@anycable_socket
end

private

def request
return super unless anycabled?

@request ||= anycable_request_builder.build_rack_request(@env)
end
end)
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

require "action_cable/remote_connections"

ActionCable::RemoteConnections::RemoteConnection.include(ActionCable::Connection::SerializableIdentification)
ActionCable::RemoteConnections::RemoteConnection.include(AnyCable::Rails::Connections::SerializableIdentification)

ActionCable::RemoteConnections::RemoteConnection.prepend(Module.new do
def disconnect(reconnect: true)
Expand Down
40 changes: 0 additions & 40 deletions lib/anycable/rails/actioncable/channel.rb

This file was deleted.

220 changes: 0 additions & 220 deletions lib/anycable/rails/actioncable/connection.rb

This file was deleted.

Loading

0 comments on commit 9b95e7a

Please sign in to comment.