omg-actioncable 8.0.0.alpha2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +24 -0
  5. data/app/assets/javascripts/action_cable.js +511 -0
  6. data/app/assets/javascripts/actioncable.esm.js +512 -0
  7. data/app/assets/javascripts/actioncable.js +510 -0
  8. data/lib/action_cable/channel/base.rb +335 -0
  9. data/lib/action_cable/channel/broadcasting.rb +50 -0
  10. data/lib/action_cable/channel/callbacks.rb +76 -0
  11. data/lib/action_cable/channel/naming.rb +28 -0
  12. data/lib/action_cable/channel/periodic_timers.rb +78 -0
  13. data/lib/action_cable/channel/streams.rb +215 -0
  14. data/lib/action_cable/channel/test_case.rb +356 -0
  15. data/lib/action_cable/connection/authorization.rb +18 -0
  16. data/lib/action_cable/connection/base.rb +294 -0
  17. data/lib/action_cable/connection/callbacks.rb +57 -0
  18. data/lib/action_cable/connection/client_socket.rb +159 -0
  19. data/lib/action_cable/connection/identification.rb +51 -0
  20. data/lib/action_cable/connection/internal_channel.rb +50 -0
  21. data/lib/action_cable/connection/message_buffer.rb +57 -0
  22. data/lib/action_cable/connection/stream.rb +117 -0
  23. data/lib/action_cable/connection/stream_event_loop.rb +136 -0
  24. data/lib/action_cable/connection/subscriptions.rb +85 -0
  25. data/lib/action_cable/connection/tagged_logger_proxy.rb +47 -0
  26. data/lib/action_cable/connection/test_case.rb +246 -0
  27. data/lib/action_cable/connection/web_socket.rb +45 -0
  28. data/lib/action_cable/deprecator.rb +9 -0
  29. data/lib/action_cable/engine.rb +98 -0
  30. data/lib/action_cable/gem_version.rb +19 -0
  31. data/lib/action_cable/helpers/action_cable_helper.rb +45 -0
  32. data/lib/action_cable/remote_connections.rb +82 -0
  33. data/lib/action_cable/server/base.rb +109 -0
  34. data/lib/action_cable/server/broadcasting.rb +62 -0
  35. data/lib/action_cable/server/configuration.rb +70 -0
  36. data/lib/action_cable/server/connections.rb +44 -0
  37. data/lib/action_cable/server/worker/active_record_connection_management.rb +23 -0
  38. data/lib/action_cable/server/worker.rb +75 -0
  39. data/lib/action_cable/subscription_adapter/async.rb +29 -0
  40. data/lib/action_cable/subscription_adapter/base.rb +36 -0
  41. data/lib/action_cable/subscription_adapter/channel_prefix.rb +30 -0
  42. data/lib/action_cable/subscription_adapter/inline.rb +39 -0
  43. data/lib/action_cable/subscription_adapter/postgresql.rb +134 -0
  44. data/lib/action_cable/subscription_adapter/redis.rb +256 -0
  45. data/lib/action_cable/subscription_adapter/subscriber_map.rb +61 -0
  46. data/lib/action_cable/subscription_adapter/test.rb +41 -0
  47. data/lib/action_cable/test_case.rb +13 -0
  48. data/lib/action_cable/test_helper.rb +163 -0
  49. data/lib/action_cable/version.rb +12 -0
  50. data/lib/action_cable.rb +80 -0
  51. data/lib/rails/generators/channel/USAGE +19 -0
  52. data/lib/rails/generators/channel/channel_generator.rb +127 -0
  53. data/lib/rails/generators/channel/templates/application_cable/channel.rb.tt +4 -0
  54. data/lib/rails/generators/channel/templates/application_cable/connection.rb.tt +4 -0
  55. data/lib/rails/generators/channel/templates/channel.rb.tt +16 -0
  56. data/lib/rails/generators/channel/templates/javascript/channel.js.tt +20 -0
  57. data/lib/rails/generators/channel/templates/javascript/consumer.js.tt +6 -0
  58. data/lib/rails/generators/channel/templates/javascript/index.js.tt +1 -0
  59. data/lib/rails/generators/test_unit/channel_generator.rb +22 -0
  60. data/lib/rails/generators/test_unit/templates/channel_test.rb.tt +8 -0
  61. metadata +181 -0
@@ -0,0 +1,163 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ module ActionCable
6
+ # Provides helper methods for testing Action Cable broadcasting
7
+ module TestHelper
8
+ def before_setup # :nodoc:
9
+ server = ActionCable.server
10
+ test_adapter = ActionCable::SubscriptionAdapter::Test.new(server)
11
+
12
+ @old_pubsub_adapter = server.pubsub
13
+
14
+ server.instance_variable_set(:@pubsub, test_adapter)
15
+ super
16
+ end
17
+
18
+ def after_teardown # :nodoc:
19
+ super
20
+ ActionCable.server.instance_variable_set(:@pubsub, @old_pubsub_adapter)
21
+ end
22
+
23
+ # Asserts that the number of broadcasted messages to the stream matches the
24
+ # given number.
25
+ #
26
+ # def test_broadcasts
27
+ # assert_broadcasts 'messages', 0
28
+ # ActionCable.server.broadcast 'messages', { text: 'hello' }
29
+ # assert_broadcasts 'messages', 1
30
+ # ActionCable.server.broadcast 'messages', { text: 'world' }
31
+ # assert_broadcasts 'messages', 2
32
+ # end
33
+ #
34
+ # If a block is passed, that block should cause the specified number of messages
35
+ # to be broadcasted.
36
+ #
37
+ # def test_broadcasts_again
38
+ # assert_broadcasts('messages', 1) do
39
+ # ActionCable.server.broadcast 'messages', { text: 'hello' }
40
+ # end
41
+ #
42
+ # assert_broadcasts('messages', 2) do
43
+ # ActionCable.server.broadcast 'messages', { text: 'hi' }
44
+ # ActionCable.server.broadcast 'messages', { text: 'how are you?' }
45
+ # end
46
+ # end
47
+ #
48
+ def assert_broadcasts(stream, number, &block)
49
+ if block_given?
50
+ new_messages = new_broadcasts_from(broadcasts(stream), stream, "assert_broadcasts", &block)
51
+
52
+ actual_count = new_messages.size
53
+ assert_equal number, actual_count, "#{number} broadcasts to #{stream} expected, but #{actual_count} were sent"
54
+ else
55
+ actual_count = broadcasts(stream).size
56
+ assert_equal number, actual_count, "#{number} broadcasts to #{stream} expected, but #{actual_count} were sent"
57
+ end
58
+ end
59
+
60
+ # Asserts that no messages have been sent to the stream.
61
+ #
62
+ # def test_no_broadcasts
63
+ # assert_no_broadcasts 'messages'
64
+ # ActionCable.server.broadcast 'messages', { text: 'hi' }
65
+ # assert_broadcasts 'messages', 1
66
+ # end
67
+ #
68
+ # If a block is passed, that block should not cause any message to be sent.
69
+ #
70
+ # def test_broadcasts_again
71
+ # assert_no_broadcasts 'messages' do
72
+ # # No job messages should be sent from this block
73
+ # end
74
+ # end
75
+ #
76
+ # Note: This assertion is simply a shortcut for:
77
+ #
78
+ # assert_broadcasts 'messages', 0, &block
79
+ #
80
+ def assert_no_broadcasts(stream, &block)
81
+ assert_broadcasts stream, 0, &block
82
+ end
83
+
84
+ # Returns the messages that are broadcasted in the block.
85
+ #
86
+ # def test_broadcasts
87
+ # messages = capture_broadcasts('messages') do
88
+ # ActionCable.server.broadcast 'messages', { text: 'hi' }
89
+ # ActionCable.server.broadcast 'messages', { text: 'how are you?' }
90
+ # end
91
+ # assert_equal 2, messages.length
92
+ # assert_equal({ text: 'hi' }, messages.first)
93
+ # assert_equal({ text: 'how are you?' }, messages.last)
94
+ # end
95
+ #
96
+ def capture_broadcasts(stream, &block)
97
+ new_broadcasts_from(broadcasts(stream), stream, "capture_broadcasts", &block).map { |m| ActiveSupport::JSON.decode(m) }
98
+ end
99
+
100
+ # Asserts that the specified message has been sent to the stream.
101
+ #
102
+ # def test_assert_transmitted_message
103
+ # ActionCable.server.broadcast 'messages', text: 'hello'
104
+ # assert_broadcast_on('messages', text: 'hello')
105
+ # end
106
+ #
107
+ # If a block is passed, that block should cause a message with the specified
108
+ # data to be sent.
109
+ #
110
+ # def test_assert_broadcast_on_again
111
+ # assert_broadcast_on('messages', text: 'hello') do
112
+ # ActionCable.server.broadcast 'messages', text: 'hello'
113
+ # end
114
+ # end
115
+ #
116
+ def assert_broadcast_on(stream, data, &block)
117
+ # Encode to JSON and back–we want to use this value to compare with decoded
118
+ # JSON. Comparing JSON strings doesn't work due to the order if the keys.
119
+ serialized_msg =
120
+ ActiveSupport::JSON.decode(ActiveSupport::JSON.encode(data))
121
+
122
+ new_messages = broadcasts(stream)
123
+ if block_given?
124
+ new_messages = new_broadcasts_from(new_messages, stream, "assert_broadcast_on", &block)
125
+ end
126
+
127
+ message = new_messages.find { |msg| ActiveSupport::JSON.decode(msg) == serialized_msg }
128
+
129
+ error_message = "No messages sent with #{data} to #{stream}"
130
+
131
+ if new_messages.any?
132
+ error_message = new_messages.inject("#{error_message}\nMessage(s) found:\n") do |error_message, new_message|
133
+ error_message + "#{ActiveSupport::JSON.decode(new_message)}\n"
134
+ end
135
+ else
136
+ error_message = "#{error_message}\nNo message found for #{stream}"
137
+ end
138
+
139
+ assert message, error_message
140
+ end
141
+
142
+ def pubsub_adapter # :nodoc:
143
+ ActionCable.server.pubsub
144
+ end
145
+
146
+ delegate :broadcasts, :clear_messages, to: :pubsub_adapter
147
+
148
+ private
149
+ def new_broadcasts_from(current_messages, stream, assertion, &block)
150
+ old_messages = current_messages
151
+ clear_messages(stream)
152
+
153
+ _assert_nothing_raised_or_warn(assertion, &block)
154
+ new_messages = broadcasts(stream)
155
+ clear_messages(stream)
156
+
157
+ # Restore all sent messages
158
+ (old_messages + new_messages).each { |m| pubsub_adapter.broadcast(stream, m) }
159
+
160
+ new_messages
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ require_relative "gem_version"
6
+
7
+ module ActionCable
8
+ # Returns the currently loaded version of Action Cable as a `Gem::Version`.
9
+ def self.version
10
+ gem_version
11
+ end
12
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # Copyright (c) 37signals LLC
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #++
25
+
26
+ require "active_support"
27
+ require "active_support/rails"
28
+ require "zeitwerk"
29
+
30
+ # We compute lib this way instead of using __dir__ because __dir__ gives a real
31
+ # path, while __FILE__ honors symlinks. If the gem is stored under a symlinked
32
+ # directory, this matters.
33
+ lib = File.dirname(__FILE__)
34
+
35
+ Zeitwerk::Loader.for_gem.tap do |loader|
36
+ loader.ignore(
37
+ "#{lib}/rails", # Contains generators, templates, docs, etc.
38
+ "#{lib}/action_cable/gem_version.rb",
39
+ "#{lib}/action_cable/version.rb",
40
+ "#{lib}/action_cable/deprecator.rb",
41
+ )
42
+
43
+ loader.do_not_eager_load(
44
+ "#{lib}/action_cable/subscription_adapter", # Adapters are required and loaded on demand.
45
+ "#{lib}/action_cable/test_helper.rb",
46
+ Dir["#{lib}/action_cable/**/test_case.rb"]
47
+ )
48
+
49
+ loader.inflector.inflect("postgresql" => "PostgreSQL")
50
+ end.setup
51
+
52
+ # :markup: markdown
53
+ # :include: ../README.md
54
+ module ActionCable
55
+ require_relative "action_cable/version"
56
+ require_relative "action_cable/deprecator"
57
+
58
+ INTERNAL = {
59
+ message_types: {
60
+ welcome: "welcome",
61
+ disconnect: "disconnect",
62
+ ping: "ping",
63
+ confirmation: "confirm_subscription",
64
+ rejection: "reject_subscription"
65
+ },
66
+ disconnect_reasons: {
67
+ unauthorized: "unauthorized",
68
+ invalid_request: "invalid_request",
69
+ server_restart: "server_restart",
70
+ remote: "remote"
71
+ },
72
+ default_mount_path: "/cable",
73
+ protocols: ["actioncable-v1-json", "actioncable-unsupported"].freeze
74
+ }
75
+
76
+ # Singleton instance of the server
77
+ module_function def server
78
+ @server ||= ActionCable::Server::Base.new
79
+ end
80
+ end
@@ -0,0 +1,19 @@
1
+ Description:
2
+ Generates a new cable channel for the server (in Ruby) and client (in JavaScript).
3
+ Pass the channel name, either CamelCased or under_scored, and an optional list of channel actions as arguments.
4
+
5
+ Examples:
6
+ `bin/rails generate channel notification`
7
+
8
+ creates a notification channel class, test and JavaScript asset:
9
+ Channel: app/channels/notification_channel.rb
10
+ Test: test/channels/notification_channel_test.rb
11
+ Assets: $JAVASCRIPT_PATH/channels/notification_channel.js
12
+
13
+ `bin/rails generate channel chat speak`
14
+
15
+ creates a chat channel with a speak action.
16
+
17
+ `bin/rails generate channel comments --no-assets`
18
+
19
+ creates a comments channel without JavaScript assets.
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ module Rails
6
+ module Generators
7
+ class ChannelGenerator < NamedBase
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ argument :actions, type: :array, default: [], banner: "method method"
11
+
12
+ class_option :assets, type: :boolean
13
+
14
+ check_class_collision suffix: "Channel"
15
+
16
+ hook_for :test_framework
17
+
18
+ def create_channel_files
19
+ create_shared_channel_files
20
+ create_channel_file
21
+
22
+ if using_javascript?
23
+ if first_setup_required?
24
+ create_shared_channel_javascript_files
25
+ import_channels_in_javascript_entrypoint
26
+
27
+ if using_importmap?
28
+ pin_javascript_dependencies
29
+ elsif using_js_runtime?
30
+ install_javascript_dependencies
31
+ end
32
+ end
33
+
34
+ create_channel_javascript_file
35
+ import_channel_in_javascript_entrypoint
36
+ end
37
+ end
38
+
39
+ private
40
+ def create_shared_channel_files
41
+ return if behavior != :invoke
42
+
43
+ copy_file "#{__dir__}/templates/application_cable/channel.rb",
44
+ "app/channels/application_cable/channel.rb"
45
+ copy_file "#{__dir__}/templates/application_cable/connection.rb",
46
+ "app/channels/application_cable/connection.rb"
47
+ end
48
+
49
+ def create_channel_file
50
+ template "channel.rb",
51
+ File.join("app/channels", class_path, "#{file_name}_channel.rb")
52
+ end
53
+
54
+ def create_shared_channel_javascript_files
55
+ template "javascript/index.js", "app/javascript/channels/index.js"
56
+ template "javascript/consumer.js", "app/javascript/channels/consumer.js"
57
+ end
58
+
59
+ def create_channel_javascript_file
60
+ channel_js_path = File.join("app/javascript/channels", class_path, "#{file_name}_channel")
61
+ js_template "javascript/channel", channel_js_path
62
+ gsub_file "#{channel_js_path}.js", /\.\/consumer/, "channels/consumer" unless using_js_runtime?
63
+ end
64
+
65
+ def import_channels_in_javascript_entrypoint
66
+ append_to_file "app/javascript/application.js",
67
+ using_js_runtime? ? %(import "./channels"\n) : %(import "channels"\n)
68
+ end
69
+
70
+ def import_channel_in_javascript_entrypoint
71
+ append_to_file "app/javascript/channels/index.js",
72
+ using_js_runtime? ? %(import "./#{file_name}_channel"\n) : %(import "channels/#{file_name}_channel"\n)
73
+ end
74
+
75
+ def install_javascript_dependencies
76
+ say "Installing JavaScript dependencies", :green
77
+ if using_bun?
78
+ run "bun add @rails/actioncable"
79
+ elsif using_node?
80
+ run "yarn add @rails/actioncable"
81
+ end
82
+ end
83
+
84
+ def pin_javascript_dependencies
85
+ append_to_file "config/importmap.rb", <<-RUBY
86
+ pin "@rails/actioncable", to: "actioncable.esm.js"
87
+ pin_all_from "app/javascript/channels", under: "channels"
88
+ RUBY
89
+ end
90
+
91
+ def file_name
92
+ @_file_name ||= super.sub(/_channel\z/i, "")
93
+ end
94
+
95
+ def first_setup_required?
96
+ !root.join("app/javascript/channels/index.js").exist?
97
+ end
98
+
99
+ def using_javascript?
100
+ @using_javascript ||= options[:assets] && root.join("app/javascript").exist?
101
+ end
102
+
103
+ def using_js_runtime?
104
+ @using_js_runtime ||= root.join("package.json").exist?
105
+ end
106
+
107
+ def using_bun?
108
+ # Cannot assume bun.lockb has been generated yet so we look for a file known to
109
+ # be generated by the jsbundling-rails gem
110
+ @using_bun ||= using_js_runtime? && root.join("bun.config.js").exist?
111
+ end
112
+
113
+ def using_node?
114
+ # Bun is the only runtime that _isn't_ node.
115
+ @using_node ||= using_js_runtime? && !root.join("bun.config.js").exist?
116
+ end
117
+
118
+ def using_importmap?
119
+ @using_importmap ||= root.join("config/importmap.rb").exist?
120
+ end
121
+
122
+ def root
123
+ @root ||= Pathname(destination_root)
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,4 @@
1
+ module ApplicationCable
2
+ class Channel < ActionCable::Channel::Base
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module ApplicationCable
2
+ class Connection < ActionCable::Connection::Base
3
+ end
4
+ end
@@ -0,0 +1,16 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %>Channel < ApplicationCable::Channel
3
+ def subscribed
4
+ # stream_from "some_channel"
5
+ end
6
+
7
+ def unsubscribed
8
+ # Any cleanup needed when channel is unsubscribed
9
+ end
10
+ <% actions.each do |action| -%>
11
+
12
+ def <%= action %>
13
+ end
14
+ <% end -%>
15
+ end
16
+ <% end -%>
@@ -0,0 +1,20 @@
1
+ import consumer from "./consumer"
2
+
3
+ consumer.subscriptions.create("<%= class_name %>Channel", {
4
+ connected() {
5
+ // Called when the subscription is ready for use on the server
6
+ },
7
+
8
+ disconnected() {
9
+ // Called when the subscription has been terminated by the server
10
+ },
11
+
12
+ received(data) {
13
+ // Called when there's incoming data on the websocket for this channel
14
+ }<%= actions.any? ? ",\n" : '' %>
15
+ <% actions.each do |action| -%>
16
+ <%=action %>: function() {
17
+ return this.perform('<%= action %>');
18
+ }<%= action == actions[-1] ? '' : ",\n" %>
19
+ <% end -%>
20
+ });
@@ -0,0 +1,6 @@
1
+ // Action Cable provides the framework to deal with WebSockets in Rails.
2
+ // You can generate new channels where WebSocket features live using the `bin/rails generate channel` command.
3
+
4
+ import { createConsumer } from "@rails/actioncable"
5
+
6
+ export default createConsumer()
@@ -0,0 +1 @@
1
+ // Import all the channels to be used by Action Cable
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ module TestUnit
6
+ module Generators
7
+ class ChannelGenerator < ::Rails::Generators::NamedBase
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ check_class_collision suffix: "ChannelTest"
11
+
12
+ def create_test_files
13
+ template "channel_test.rb", File.join("test/channels", class_path, "#{file_name}_channel_test.rb")
14
+ end
15
+
16
+ private
17
+ def file_name # :doc:
18
+ @_file_name ||= super.sub(/_channel\z/i, "")
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,8 @@
1
+ require "test_helper"
2
+
3
+ class <%= class_name %>ChannelTest < ActionCable::Channel::TestCase
4
+ # test "subscribes" do
5
+ # subscribe
6
+ # assert subscription.confirmed?
7
+ # end
8
+ end
metadata ADDED
@@ -0,0 +1,181 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: omg-actioncable
3
+ version: !ruby/object:Gem::Version
4
+ version: 8.0.0.alpha2
5
+ platform: ruby
6
+ authors:
7
+ - Pratik Naik
8
+ - David Heinemeier Hansson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2024-09-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: omg-activesupport
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - '='
19
+ - !ruby/object:Gem::Version
20
+ version: 8.0.0.alpha2
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - '='
26
+ - !ruby/object:Gem::Version
27
+ version: 8.0.0.alpha2
28
+ - !ruby/object:Gem::Dependency
29
+ name: omg-actionpack
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '='
33
+ - !ruby/object:Gem::Version
34
+ version: 8.0.0.alpha2
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '='
40
+ - !ruby/object:Gem::Version
41
+ version: 8.0.0.alpha2
42
+ - !ruby/object:Gem::Dependency
43
+ name: nio4r
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '2.0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '2.0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: websocket-driver
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 0.6.1
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 0.6.1
70
+ - !ruby/object:Gem::Dependency
71
+ name: zeitwerk
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '2.6'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '2.6'
84
+ description: Structure many real-time application concerns into channels over a single
85
+ WebSocket connection.
86
+ email:
87
+ - pratiknaik@gmail.com
88
+ - david@loudthinking.com
89
+ executables: []
90
+ extensions: []
91
+ extra_rdoc_files: []
92
+ files:
93
+ - CHANGELOG.md
94
+ - MIT-LICENSE
95
+ - README.md
96
+ - app/assets/javascripts/action_cable.js
97
+ - app/assets/javascripts/actioncable.esm.js
98
+ - app/assets/javascripts/actioncable.js
99
+ - lib/action_cable.rb
100
+ - lib/action_cable/channel/base.rb
101
+ - lib/action_cable/channel/broadcasting.rb
102
+ - lib/action_cable/channel/callbacks.rb
103
+ - lib/action_cable/channel/naming.rb
104
+ - lib/action_cable/channel/periodic_timers.rb
105
+ - lib/action_cable/channel/streams.rb
106
+ - lib/action_cable/channel/test_case.rb
107
+ - lib/action_cable/connection/authorization.rb
108
+ - lib/action_cable/connection/base.rb
109
+ - lib/action_cable/connection/callbacks.rb
110
+ - lib/action_cable/connection/client_socket.rb
111
+ - lib/action_cable/connection/identification.rb
112
+ - lib/action_cable/connection/internal_channel.rb
113
+ - lib/action_cable/connection/message_buffer.rb
114
+ - lib/action_cable/connection/stream.rb
115
+ - lib/action_cable/connection/stream_event_loop.rb
116
+ - lib/action_cable/connection/subscriptions.rb
117
+ - lib/action_cable/connection/tagged_logger_proxy.rb
118
+ - lib/action_cable/connection/test_case.rb
119
+ - lib/action_cable/connection/web_socket.rb
120
+ - lib/action_cable/deprecator.rb
121
+ - lib/action_cable/engine.rb
122
+ - lib/action_cable/gem_version.rb
123
+ - lib/action_cable/helpers/action_cable_helper.rb
124
+ - lib/action_cable/remote_connections.rb
125
+ - lib/action_cable/server/base.rb
126
+ - lib/action_cable/server/broadcasting.rb
127
+ - lib/action_cable/server/configuration.rb
128
+ - lib/action_cable/server/connections.rb
129
+ - lib/action_cable/server/worker.rb
130
+ - lib/action_cable/server/worker/active_record_connection_management.rb
131
+ - lib/action_cable/subscription_adapter/async.rb
132
+ - lib/action_cable/subscription_adapter/base.rb
133
+ - lib/action_cable/subscription_adapter/channel_prefix.rb
134
+ - lib/action_cable/subscription_adapter/inline.rb
135
+ - lib/action_cable/subscription_adapter/postgresql.rb
136
+ - lib/action_cable/subscription_adapter/redis.rb
137
+ - lib/action_cable/subscription_adapter/subscriber_map.rb
138
+ - lib/action_cable/subscription_adapter/test.rb
139
+ - lib/action_cable/test_case.rb
140
+ - lib/action_cable/test_helper.rb
141
+ - lib/action_cable/version.rb
142
+ - lib/rails/generators/channel/USAGE
143
+ - lib/rails/generators/channel/channel_generator.rb
144
+ - lib/rails/generators/channel/templates/application_cable/channel.rb.tt
145
+ - lib/rails/generators/channel/templates/application_cable/connection.rb.tt
146
+ - lib/rails/generators/channel/templates/channel.rb.tt
147
+ - lib/rails/generators/channel/templates/javascript/channel.js.tt
148
+ - lib/rails/generators/channel/templates/javascript/consumer.js.tt
149
+ - lib/rails/generators/channel/templates/javascript/index.js.tt
150
+ - lib/rails/generators/test_unit/channel_generator.rb
151
+ - lib/rails/generators/test_unit/templates/channel_test.rb.tt
152
+ homepage: https://rubyonrails.org
153
+ licenses:
154
+ - MIT
155
+ metadata:
156
+ bug_tracker_uri: https://github.com/rails/rails/issues
157
+ changelog_uri: https://github.com/rails/rails/blob/v8.0.0.alpha2/actioncable/CHANGELOG.md
158
+ documentation_uri: https://api.rubyonrails.org/v8.0.0.alpha2/
159
+ mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
160
+ source_code_uri: https://github.com/rails/rails/tree/v8.0.0.alpha2/actioncable
161
+ rubygems_mfa_required: 'true'
162
+ post_install_message:
163
+ rdoc_options: []
164
+ require_paths:
165
+ - lib
166
+ required_ruby_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: 3.1.0
171
+ required_rubygems_version: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: '0'
176
+ requirements: []
177
+ rubygems_version: 3.5.11
178
+ signing_key:
179
+ specification_version: 4
180
+ summary: WebSocket framework for Rails.
181
+ test_files: []