actioncable 6.1.3.1 → 7.0.0.alpha1

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.
@@ -25,7 +25,7 @@ module ActionCable
25
25
  serialize_broadcasting([ channel_name, model ])
26
26
  end
27
27
 
28
- def serialize_broadcasting(object) #:nodoc:
28
+ def serialize_broadcasting(object) # :nodoc:
29
29
  case
30
30
  when object.is_a?(Array)
31
31
  object.map { |m| serialize_broadcasting(m) }.join(":")
@@ -124,13 +124,11 @@ module ActionCable
124
124
  end.clear
125
125
  end
126
126
 
127
- # Calls stream_for if record is present, otherwise calls reject.
128
- # This method is intended to be called when you're looking
129
- # for a record based on a parameter, if its found it will start
130
- # streaming. If the record is nil then it will reject the connection.
131
- def stream_or_reject_for(record)
132
- if record
133
- stream_for record
127
+ # Calls stream_for with the given <tt>model</tt> if it's present to start streaming,
128
+ # otherwise rejects the subscription.
129
+ def stream_or_reject_for(model)
130
+ if model
131
+ stream_for model
134
132
  else
135
133
  reject
136
134
  end
@@ -246,7 +246,7 @@ module ActionCable
246
246
  # Returns messages transmitted into channel
247
247
  def transmissions
248
248
  # Return only directly sent message (via #transmit)
249
- connection.transmissions.map { |data| data["message"] }.compact
249
+ connection.transmissions.filter_map { |data| data["message"] }
250
250
  end
251
251
 
252
252
  # Enhance TestHelper assertions to handle non-String
@@ -68,7 +68,7 @@ module ActionCable
68
68
 
69
69
  # Called by the server when a new WebSocket connection is established. This configures the callbacks intended for overwriting by the user.
70
70
  # This method should not be called directly -- instead rely upon on the #connect (and #disconnect) callbacks.
71
- def process #:nodoc:
71
+ def process # :nodoc:
72
72
  logger.info started_request_message
73
73
 
74
74
  if websocket.possible? && allow_request_origin?
@@ -80,11 +80,11 @@ module ActionCable
80
80
 
81
81
  # Decodes WebSocket messages and dispatches them to subscribed channels.
82
82
  # WebSocket message transfer encoding is always JSON.
83
- def receive(websocket_message) #:nodoc:
83
+ def receive(websocket_message) # :nodoc:
84
84
  send_async :dispatch_websocket_message, websocket_message
85
85
  end
86
86
 
87
- def dispatch_websocket_message(websocket_message) #:nodoc:
87
+ def dispatch_websocket_message(websocket_message) # :nodoc:
88
88
  if websocket.alive?
89
89
  subscriptions.execute_command decode(websocket_message)
90
90
  else
@@ -26,7 +26,7 @@ module ActionCable
26
26
  # Return a single connection identifier that combines the value of all the registered identifiers into a single gid.
27
27
  def connection_identifier
28
28
  unless defined? @connection_identifier
29
- @connection_identifier = connection_gid identifiers.map { |id| instance_variable_get("@#{id}") }.compact
29
+ @connection_identifier = connection_gid identifiers.filter_map { |id| instance_variable_get("@#{id}") }
30
30
  end
31
31
 
32
32
  @connection_identifier
@@ -33,7 +33,7 @@ module ActionCable
33
33
 
34
34
  subscription_klass = id_options[:channel].safe_constantize
35
35
 
36
- if subscription_klass && ActionCable::Channel::Base >= subscription_klass
36
+ if subscription_klass && ActionCable::Channel::Base > subscription_klass
37
37
  subscription = subscription_klass.new(connection, id_key, id_options)
38
38
  subscriptions[id_key] = subscription
39
39
  subscription.subscribe_to_channel
@@ -18,10 +18,10 @@ module ActionCable
18
18
  @tags = @tags.uniq
19
19
  end
20
20
 
21
- def tag(logger)
21
+ def tag(logger, &block)
22
22
  if logger.respond_to?(:tagged)
23
23
  current_tags = tags - logger.formatter.current_tags
24
- logger.tagged(*current_tags) { yield }
24
+ logger.tagged(*current_tags, &block)
25
25
  else
26
26
  yield
27
27
  end
@@ -9,6 +9,7 @@ module ActionCable
9
9
  class Engine < Rails::Engine # :nodoc:
10
10
  config.action_cable = ActiveSupport::OrderedOptions.new
11
11
  config.action_cable.mount_path = ActionCable::INTERNAL[:default_mount_path]
12
+ config.action_cable.precompile_assets = true
12
13
 
13
14
  config.eager_load_namespaces << ActionCable
14
15
 
@@ -22,6 +23,14 @@ module ActionCable
22
23
  ActiveSupport.on_load(:action_cable) { self.logger ||= ::Rails.logger }
23
24
  end
24
25
 
26
+ initializer "action_cable.asset" do
27
+ config.after_initialize do |app|
28
+ if Rails.application.config.respond_to?(:assets) && app.config.action_cable.precompile_assets
29
+ Rails.application.config.assets.precompile += %w( actioncable.js actioncable.esm.js )
30
+ end
31
+ end
32
+ end
33
+
25
34
  initializer "action_cable.set_configs" do |app|
26
35
  options = app.config.action_cable
27
36
  options.allowed_request_origins ||= /https?:\/\/localhost:\d+/ if ::Rails.env.development?
@@ -7,10 +7,10 @@ module ActionCable
7
7
  end
8
8
 
9
9
  module VERSION
10
- MAJOR = 6
11
- MINOR = 1
12
- TINY = 3
13
- PRE = "1"
10
+ MAJOR = 7
11
+ MINOR = 0
12
+ TINY = 0
13
+ PRE = "alpha1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -8,14 +8,15 @@ module ActionCable
8
8
  #
9
9
  # <head>
10
10
  # <%= action_cable_meta_tag %>
11
- # <%= javascript_include_tag 'application', 'data-turbolinks-track' => 'reload' %>
11
+ # <%= javascript_include_tag 'application', 'data-turbo-track' => 'reload' %>
12
12
  # </head>
13
13
  #
14
14
  # This is then used by Action Cable to determine the URL of your WebSocket server.
15
15
  # Your JavaScript can then connect to the server without needing to specify the
16
16
  # URL directly:
17
17
  #
18
- # window.Cable = require("@rails/actioncable")
18
+ # import Cable from "@rails/actioncable"
19
+ # window.Cable = Cable
19
20
  # window.App = {}
20
21
  # App.cable = Cable.createConsumer()
21
22
  #
@@ -45,7 +45,7 @@ module ActionCable
45
45
 
46
46
  # Uses the internal channel to disconnect the connection.
47
47
  def disconnect
48
- server.broadcast internal_channel, type: "disconnect"
48
+ server.broadcast internal_channel, { type: "disconnect" }
49
49
  end
50
50
 
51
51
  # Returns all the identifiers that were applied to this connection.
@@ -40,7 +40,7 @@ module ActionCable
40
40
  end
41
41
 
42
42
  def broadcast(message)
43
- server.logger.debug { "[ActionCable] Broadcasting to #{broadcasting}: #{message.inspect}" }
43
+ server.logger.debug { "[ActionCable] Broadcasting to #{broadcasting}: #{message.inspect.truncate(300)}" }
44
44
 
45
45
  payload = { broadcasting: broadcasting, message: message, coder: coder }
46
46
  ActiveSupport::Notifications.instrument("broadcast.action_cable", payload) do
@@ -9,6 +9,7 @@ module ActionCable
9
9
  attr_accessor :connection_class, :worker_pool_size
10
10
  attr_accessor :disable_request_forgery_protection, :allowed_request_origins, :allow_same_origin_as_host
11
11
  attr_accessor :cable, :url, :mount_path
12
+ attr_accessor :precompile_assets
12
13
 
13
14
  def initialize
14
15
  @log_tags = []
@@ -12,8 +12,8 @@ module ActionCable
12
12
  end
13
13
  end
14
14
 
15
- def with_database_connections
16
- connection.logger.tag(ActiveRecord::Base.logger) { yield }
15
+ def with_database_connections(&block)
16
+ connection.logger.tag(ActiveRecord::Base.logger, &block)
17
17
  end
18
18
  end
19
19
  end
@@ -19,6 +19,7 @@ module ActionCable
19
19
 
20
20
  def initialize(max_size: 5)
21
21
  @executor = Concurrent::ThreadPoolExecutor.new(
22
+ name: "ActionCable",
22
23
  min_threads: 1,
23
24
  max_threads: max_size,
24
25
  max_queue: 0,
@@ -35,12 +36,10 @@ module ActionCable
35
36
  @executor.shuttingdown?
36
37
  end
37
38
 
38
- def work(connection)
39
+ def work(connection, &block)
39
40
  self.connection = connection
40
41
 
41
- run_callbacks :work do
42
- yield
43
- end
42
+ run_callbacks :work, &block
44
43
  ensure
45
44
  self.connection = nil
46
45
  end
@@ -3,7 +3,7 @@
3
3
  gem "pg", "~> 1.1"
4
4
  require "pg"
5
5
  require "thread"
6
- require "digest/sha1"
6
+ require "openssl"
7
7
 
8
8
  module ActionCable
9
9
  module SubscriptionAdapter
@@ -58,7 +58,7 @@ module ActionCable
58
58
 
59
59
  private
60
60
  def channel_identifier(channel)
61
- channel.size > 63 ? Digest::SHA1.hexdigest(channel) : channel
61
+ channel.size > 63 ? OpenSSL::Digest::SHA1.hexdigest(channel) : channel
62
62
  end
63
63
 
64
64
  def listener
@@ -45,7 +45,7 @@ module ActionCable
45
45
  def assert_broadcasts(stream, number, &block)
46
46
  if block_given?
47
47
  original_count = broadcasts_size(stream)
48
- assert_nothing_raised(&block)
48
+ _assert_nothing_raised_or_warn("assert_broadcasts", &block)
49
49
  new_count = broadcasts_size(stream)
50
50
  actual_count = new_count - original_count
51
51
  else
@@ -106,7 +106,7 @@ module ActionCable
106
106
  old_messages = new_messages
107
107
  clear_messages(stream)
108
108
 
109
- assert_nothing_raised(&block)
109
+ _assert_nothing_raised_or_warn("assert_broadcast_on", &block)
110
110
  new_messages = broadcasts(stream)
111
111
  clear_messages(stream)
112
112
 
data/lib/action_cable.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # Copyright (c) 2015-2020 Basecamp, LLC
4
+ # Copyright (c) 2015-2021 Basecamp, LLC
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining
7
7
  # a copy of this software and associated documentation files (the
@@ -10,4 +10,4 @@ Example:
10
10
  creates a Chat channel class, test and JavaScript asset:
11
11
  Channel: app/channels/chat_channel.rb
12
12
  Test: test/channels/chat_channel_test.rb
13
- Assets: app/javascript/channels/chat_channel.js
13
+ Assets: $JAVASCRIPT_PATH/channels/chat_channel.js
@@ -13,39 +13,98 @@ module Rails
13
13
 
14
14
  hook_for :test_framework
15
15
 
16
- def create_channel_file
17
- template "channel.rb", File.join("app/channels", class_path, "#{file_name}_channel.rb")
16
+ def create_channel_files
17
+ create_shared_channel_files
18
+ create_channel_file
18
19
 
19
- if options[:assets]
20
- if behavior == :invoke
21
- template "javascript/index.js", "app/javascript/channels/index.js"
22
- template "javascript/consumer.js", "app/javascript/channels/consumer.js"
20
+ if using_javascript?
21
+ if first_setup_required?
22
+ create_shared_channel_javascript_files
23
+ import_channels_in_javascript_entrypoint
24
+
25
+ if using_importmap?
26
+ pin_javascript_dependencies
27
+ elsif using_node?
28
+ install_javascript_dependencies
29
+ end
23
30
  end
24
31
 
25
- js_template "javascript/channel", File.join("app/javascript/channels", class_path, "#{file_name}_channel")
32
+ create_channel_javascript_file
33
+ import_channel_in_javascript_entrypoint
26
34
  end
27
-
28
- generate_application_cable_files
29
35
  end
30
36
 
31
37
  private
38
+ def create_shared_channel_files
39
+ return if behavior != :invoke
40
+
41
+ copy_file "#{__dir__}/templates/application_cable/channel.rb",
42
+ "app/channels/application_cable/channel.rb"
43
+ copy_file "#{__dir__}/templates/application_cable/connection.rb",
44
+ "app/channels/application_cable/connection.rb"
45
+ end
46
+
47
+ def create_channel_file
48
+ template "channel.rb",
49
+ File.join("app/channels", class_path, "#{file_name}_channel.rb")
50
+ end
51
+
52
+ def create_shared_channel_javascript_files
53
+ template "javascript/index.js", "app/javascript/channels/index.js"
54
+ template "javascript/consumer.js", "app/javascript/channels/consumer.js"
55
+ end
56
+
57
+ def create_channel_javascript_file
58
+ channel_js_path = File.join("app/javascript/channels", class_path, "#{file_name}_channel")
59
+ js_template "javascript/channel", channel_js_path
60
+ gsub_file "#{channel_js_path}.js", /\.\/consumer/, "channels/consumer" unless using_node?
61
+ end
62
+
63
+ def import_channels_in_javascript_entrypoint
64
+ append_to_file "app/javascript/application.js",
65
+ using_node? ? %(import "./channels"\n) : %(import "channels"\n)
66
+ end
67
+
68
+ def import_channel_in_javascript_entrypoint
69
+ append_to_file "app/javascript/channels/index.js",
70
+ using_node? ? %(import "./#{file_name}_channel"\n) : %(import "channels/#{file_name}_channel"\n)
71
+ end
72
+
73
+ def install_javascript_dependencies
74
+ say "Installing JavaScript dependencies", :green
75
+ run "yarn add @rails/actioncable"
76
+ end
77
+
78
+ def pin_javascript_dependencies
79
+ append_to_file "config/importmap.rb", <<-RUBY
80
+ pin "@rails/actioncable", to: "actioncable.esm.js"
81
+ pin_all_from "app/javascript/channels", under: "channels"
82
+ RUBY
83
+ end
84
+
85
+
32
86
  def file_name
33
87
  @_file_name ||= super.sub(/_channel\z/i, "")
34
88
  end
35
89
 
36
- # FIXME: Change these files to symlinks once RubyGems 2.5.0 is required.
37
- def generate_application_cable_files
38
- return if behavior != :invoke
90
+ def first_setup_required?
91
+ !root.join("app/javascript/channels/index.js").exist?
92
+ end
39
93
 
40
- files = [
41
- "application_cable/channel.rb",
42
- "application_cable/connection.rb"
43
- ]
94
+ def using_javascript?
95
+ @using_javascript ||= options[:assets] && root.join("app/javascript").exist?
96
+ end
44
97
 
45
- files.each do |name|
46
- path = File.join("app/channels/", name)
47
- template(name, path) if !File.exist?(path)
48
- end
98
+ def using_node?
99
+ @using_node ||= root.join("package.json").exist?
100
+ end
101
+
102
+ def using_importmap?
103
+ @using_importmap ||= root.join("config/importmap.rb").exist?
104
+ end
105
+
106
+ def root
107
+ @root ||= Pathname(destination_root)
49
108
  end
50
109
  end
51
110
  end
@@ -1,5 +1 @@
1
- // Load all the channels within this directory and all subdirectories.
2
- // Channel files must be named *_channel.js.
3
-
4
- const channels = require.context('.', true, /_channel\.js$/)
5
- channels.keys().forEach(channels)
1
+ // Import all the channels to be used by Action Cable
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actioncable
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.3.1
4
+ version: 7.0.0.alpha1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pratik Naik
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-03-26 00:00:00.000000000 Z
12
+ date: 2021-09-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -17,28 +17,28 @@ dependencies:
17
17
  requirements:
18
18
  - - '='
19
19
  - !ruby/object:Gem::Version
20
- version: 6.1.3.1
20
+ version: 7.0.0.alpha1
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - '='
26
26
  - !ruby/object:Gem::Version
27
- version: 6.1.3.1
27
+ version: 7.0.0.alpha1
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: actionpack
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - '='
33
33
  - !ruby/object:Gem::Version
34
- version: 6.1.3.1
34
+ version: 7.0.0.alpha1
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - '='
40
40
  - !ruby/object:Gem::Version
41
- version: 6.1.3.1
41
+ version: 7.0.0.alpha1
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: nio4r
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -127,8 +127,8 @@ files:
127
127
  - lib/action_cable/version.rb
128
128
  - lib/rails/generators/channel/USAGE
129
129
  - lib/rails/generators/channel/channel_generator.rb
130
- - lib/rails/generators/channel/templates/application_cable/channel.rb.tt
131
- - lib/rails/generators/channel/templates/application_cable/connection.rb.tt
130
+ - lib/rails/generators/channel/templates/application_cable/channel.rb
131
+ - lib/rails/generators/channel/templates/application_cable/connection.rb
132
132
  - lib/rails/generators/channel/templates/channel.rb.tt
133
133
  - lib/rails/generators/channel/templates/javascript/channel.js.tt
134
134
  - lib/rails/generators/channel/templates/javascript/consumer.js.tt
@@ -140,10 +140,10 @@ licenses:
140
140
  - MIT
141
141
  metadata:
142
142
  bug_tracker_uri: https://github.com/rails/rails/issues
143
- changelog_uri: https://github.com/rails/rails/blob/v6.1.3.1/actioncable/CHANGELOG.md
144
- documentation_uri: https://api.rubyonrails.org/v6.1.3.1/
143
+ changelog_uri: https://github.com/rails/rails/blob/v7.0.0.alpha1/actioncable/CHANGELOG.md
144
+ documentation_uri: https://api.rubyonrails.org/v7.0.0.alpha1/
145
145
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
146
- source_code_uri: https://github.com/rails/rails/tree/v6.1.3.1/actioncable
146
+ source_code_uri: https://github.com/rails/rails/tree/v7.0.0.alpha1/actioncable
147
147
  post_install_message:
148
148
  rdoc_options: []
149
149
  require_paths:
@@ -152,14 +152,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
152
152
  requirements:
153
153
  - - ">="
154
154
  - !ruby/object:Gem::Version
155
- version: 2.5.0
155
+ version: 2.7.0
156
156
  required_rubygems_version: !ruby/object:Gem::Requirement
157
157
  requirements:
158
- - - ">="
158
+ - - ">"
159
159
  - !ruby/object:Gem::Version
160
- version: '0'
160
+ version: 1.3.1
161
161
  requirements: []
162
- rubygems_version: 3.1.2
162
+ rubygems_version: 3.1.6
163
163
  signing_key:
164
164
  specification_version: 4
165
165
  summary: WebSocket framework for Rails.