diff --git a/actioncable/app/assets/javascripts/action_cable.coffee.erb b/actioncable/app/assets/javascripts/action_cable.coffee.erb index d95fe78ac56b6880844a361f5ee6f1c63926e381..6a8b4eeb85575137dec41fd129db622259d7bd97 100644 --- a/actioncable/app/assets/javascripts/action_cable.coffee.erb +++ b/actioncable/app/assets/javascripts/action_cable.coffee.erb @@ -9,7 +9,7 @@ getConfig: (name) -> element = document.head.querySelector("meta[name='action-cable-#{name}']") - element?.getAttribute("content") + element?.getAttribute("content") ? '/cable' createWebSocketURL: (url) -> if url and not /^wss?:/i.test(url) diff --git a/actioncable/app/assets/javascripts/action_cable/connection.coffee b/actioncable/app/assets/javascripts/action_cable/connection.coffee index ee888f567b40c1633b3e7c19cfc1bfccfcb69979..4244322a1e715795096b0a6c2813a1be4d71edc0 100644 --- a/actioncable/app/assets/javascripts/action_cable/connection.coffee +++ b/actioncable/app/assets/javascripts/action_cable/connection.coffee @@ -6,9 +6,11 @@ class ActionCable.Connection @reopenDelay: 500 constructor: (@consumer) -> - @open() send: (data) -> + unless @isOpen() + @open() + if @isOpen() @webSocket.send(JSON.stringify(data)) true diff --git a/actioncable/lib/action_cable/engine.rb b/actioncable/lib/action_cable/engine.rb index f5f1cb59e0a43ac945705b0f2763f8fcebab8ccf..ae0c59dccddbe4b158ccaa69cacc175dfe8649b8 100644 --- a/actioncable/lib/action_cable/engine.rb +++ b/actioncable/lib/action_cable/engine.rb @@ -6,7 +6,7 @@ module ActionCable class Railtie < Rails::Engine # :nodoc: config.action_cable = ActiveSupport::OrderedOptions.new - config.action_cable.url = '/cable' + config.action_cable.mount_path = '/cable' config.eager_load_namespaces << ActionCable @@ -40,5 +40,16 @@ class Railtie < Rails::Engine # :nodoc: options.each { |k,v| send("#{k}=", v) } end end + + initializer "action_cable.routes" do + config.after_initialize do |app| + config = app.config + unless config.action_cable.mount_path.nil? + app.routes.prepend do + mount ActionCable.server => config.action_cable.mount_path, internal: true + end + end + end + end end end diff --git a/actioncable/lib/action_cable/helpers/action_cable_helper.rb b/actioncable/lib/action_cable/helpers/action_cable_helper.rb index 3067542b33ae57dcaa568f10c6edc17333f71685..200732fdcdfc9def416a9abf80c78374b09cb760 100644 --- a/actioncable/lib/action_cable/helpers/action_cable_helper.rb +++ b/actioncable/lib/action_cable/helpers/action_cable_helper.rb @@ -20,9 +20,20 @@ module ActionCableHelper # Make sure to specify the correct server location in each of your environments # config file: # - # config.action_cable.url = "ws://example.com:28080" + # config.action_cable.mount_path = "/cable123" + # <%= action_cable_meta_tag %> would render: + # => + # + # config.action_cable.url = "ws://actioncable.com" + # <%= action_cable_meta_tag %> would render: + # => + # def action_cable_meta_tag - tag "meta", name: "action-cable-url", content: Rails.application.config.action_cable.url + tag "meta", name: "action-cable-url", content: ( + ActionCable.server.config.url || + ActionCable.server.config.mount_path || + raise("No Action Cable URL configured -- please configure this at config.action_cable.url") + ) end end end diff --git a/actioncable/lib/action_cable/server/configuration.rb b/actioncable/lib/action_cable/server/configuration.rb index ee17bff13b0f891a7d0ac457250b42e24ef0e9f2..9a7301287ccc19567a712c0554216b37b3202150 100644 --- a/actioncable/lib/action_cable/server/configuration.rb +++ b/actioncable/lib/action_cable/server/configuration.rb @@ -6,7 +6,7 @@ class Configuration attr_accessor :logger, :log_tags attr_accessor :connection_class, :worker_pool_size attr_accessor :disable_request_forgery_protection, :allowed_request_origins - attr_accessor :cable, :url + attr_accessor :cable, :url, :mount_path attr_accessor :channel_paths # :nodoc: diff --git a/guides/source/configuring.md b/guides/source/configuring.md index 23866b1800d50e29a55635f2124e3a9f61c7246b..3f522386d308541ad913e5dbc1b30ee0a69a7329 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -613,6 +613,17 @@ There are a few configuration options available in Active Support: * `config.active_job.logger` accepts a logger conforming to the interface of Log4r or the default Ruby Logger class, which is then used to log information from Active Job. You can retrieve this logger by calling `logger` on either an Active Job class or an Active Job instance. Set to `nil` to disable logging. +### Configuring Action Cable + +* `config.action_cable.url` accepts a string for the URL for where + you are hosting your Action Cable server. You would use this option +if you are running Action Cable servers that are separated from your +main application. +* `config.action_cable.mount_path` accepts a string for where to mount Action + Cable, as apart of the main server process. Defaults to `/cable`. +You can set this as nil to not mount Action Cable as apart of your +normal Rails server. + ### Configuring a Database Just about every Rails application will interact with a database. You can connect to the database by setting an environment variable `ENV['DATABASE_URL']` or by using a configuration file called `config/database.yml`. diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/cable.coffee b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/cable.coffee index 07934d026f77c08f23d223a8cb9f3533d595881f..af08f58e340d9ab1a32fb0f894cdc7ca9b7dd12f 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/cable.coffee +++ b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/cable.coffee @@ -1,11 +1,9 @@ # Action Cable provides the framework to deal with WebSockets in Rails. # You can generate new channels where WebSocket features live using the rails generate channel command. # -# Turn on the cable connection by removing the comments after the require statements (and ensure it's also on in config/routes.rb). -# #= require action_cable #= require_self #= require_tree ./channels -# -# @App ||= {} -# App.cable = ActionCable.createConsumer() + +@App ||= {} +App.cable = ActionCable.createConsumer() diff --git a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt index ec781721cbfb780cac7bdf4ad565c9e27332ff59..72258cc96b7eb7dbf68aa3f2bb81298577b6cc9c 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +++ b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt @@ -3,9 +3,6 @@ <%= camelized %> <%%= csrf_meta_tags %> - <%- unless options[:skip_action_cable] -%> - <%%= action_cable_meta_tag %> - <%- end -%> <%- if options[:skip_javascript] -%> <%%= stylesheet_link_tag 'application', media: 'all' %> diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt index 236e42fcd76f90b00c0fb27813d2d8aaad93bfe6..0fc1179339d92b773c985641e524913bfc339806 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt @@ -91,5 +91,9 @@ Rails.application.configure do # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false + + # Don't mount Action Cable in the main server process. + # config.action_cable.mount_path = nil + # config.action_cable.url = "ws://example.com" <%- end -%> end diff --git a/railties/lib/rails/generators/rails/app/templates/config/routes.rb b/railties/lib/rails/generators/rails/app/templates/config/routes.rb index 8293c8a483e8fa6c03eb0fd8e7360cd741a0cad7..787824f888b3bd1c3a56968e39c1fd47675b9c7a 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/routes.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/routes.rb @@ -1,6 +1,3 @@ Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html - - # Serve websocket cable requests in-process - # mount ActionCable.server => '/cable' end diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb index d1c828b509a20a66547fc2d83ae9a6eebf31b5e2..3db467256e8ca5789c8837f75fd41d7877d2b824 100644 --- a/railties/test/application/rake_test.rb +++ b/railties/test/application/rake_test.rb @@ -118,7 +118,7 @@ def test_should_not_eager_load_model_for_rake end def test_code_statistics_sanity - assert_match "Code LOC: 14 Test LOC: 0 Code to Test Ratio: 1:0.0", + assert_match "Code LOC: 16 Test LOC: 0 Code to Test Ratio: 1:0.0", Dir.chdir(app_path){ `bin/rails stats` } end diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index c2c3638f07ab04ee9113f68da03648aa0c7013d1..bc80c7eb1bf5ef07fce0861d56add92f74603b92 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -406,9 +406,6 @@ def test_generator_if_skip_action_cable_is_given assert_no_file "config/cable.yml" assert_no_file "app/assets/javascripts/cable.coffee" assert_no_file "app/channels" - assert_file "app/views/layouts/application.html.erb" do |content| - assert_no_match(/action_cable_meta_tag/, content) - end assert_file "Gemfile" do |content| assert_no_match(/redis/, content) end