From 62250e38a1269030e036cf23a6ea6714fb00ffac Mon Sep 17 00:00:00 2001 From: Mike Virata-Stone Date: Thu, 3 Sep 2015 17:17:48 -0700 Subject: [PATCH] Easy websocket url configuration Thanks to feedback from @ascrazy, @jeremy, and @javan --- README.md | 20 +++++++++++++ lib/action_cable/engine.rb | 5 ++++ .../helpers/action_cable_helper.rb | 29 +++++++++++++++++++ lib/action_cable/server/configuration.rb | 1 + lib/assets/javascripts/cable.coffee.erb | 6 +++- 5 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 lib/action_cable/helpers/action_cable_helper.rb diff --git a/README.md b/README.md index ebc505db19..601d5764e0 100644 --- a/README.md +++ b/README.md @@ -330,6 +330,26 @@ ActionCable.server.config.log_tags = [ ] ``` +Your websocket url might change between environments. If you host your production server via https, you will need to use the wss scheme +for your ActionCable server, but development might remain http and use the ws scheme. You might use localhost in development and your +domain in production. In any case, to vary the websocket url between environments, add the following configuration to each environment: + +```ruby +config.action_cable.url = "ws://example.com:28080" +``` + +Then add the following line to your layout before your JavaScript tag: + +```erb +<%= action_cable_meta_tag %> +``` + +And finally, create your consumer like so: + +```coffeescript +App.cable = Cable.createConsumer() +``` + For a full list of all configuration options, see the `ActionCable::Server::Configuration` class. Also note that your server must provide at least the same number of database connections as you have workers. The default worker pool is set to 100, so that means you have to make at least that available. You can change that in `config/database.yml` through the `pool` attribute. diff --git a/lib/action_cable/engine.rb b/lib/action_cable/engine.rb index 613a9b99f2..4777c3886b 100644 --- a/lib/action_cable/engine.rb +++ b/lib/action_cable/engine.rb @@ -1,10 +1,15 @@ require 'rails/engine' require 'active_support/ordered_options' +require 'action_cable/helpers/action_cable_helper' module ActionCable class Engine < ::Rails::Engine config.action_cable = ActiveSupport::OrderedOptions.new + config.to_prepare do + ApplicationController.helper ActionCable::Helpers::ActionCableHelper + end + initializer "action_cable.logger" do ActiveSupport.on_load(:action_cable) { self.logger ||= ::Rails.logger } end diff --git a/lib/action_cable/helpers/action_cable_helper.rb b/lib/action_cable/helpers/action_cable_helper.rb new file mode 100644 index 0000000000..b82751468a --- /dev/null +++ b/lib/action_cable/helpers/action_cable_helper.rb @@ -0,0 +1,29 @@ +module ActionCable + module Helpers + module ActionCableHelper + # Returns an "action-cable-url" meta tag with the value of the url specified in your + # configuration. Ensure this is above your javascript tag: + # + # + # <%= action_cable_meta_tag %> + # <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> + # + # + # This is then used by ActionCable to determine the url of your websocket server. + # Your CoffeeScript can then connect to the server without needing to specify the + # url directly: + # + # #= require cable + # @App = {} + # App.cable = Cable.createConsumer() + # + # Make sure to specify the correct server location in each of your environments + # config file: + # + # config.action_cable.url = "ws://example.com:28080" + def action_cable_meta_tag + tag "meta", name: "action-cable-url", content: Rails.application.config.action_cable.url + end + end + end +end diff --git a/lib/action_cable/server/configuration.rb b/lib/action_cable/server/configuration.rb index 89a0caddb4..f7fcee019b 100644 --- a/lib/action_cable/server/configuration.rb +++ b/lib/action_cable/server/configuration.rb @@ -9,6 +9,7 @@ module ActionCable attr_accessor :connection_class, :worker_pool_size attr_accessor :redis_path, :channels_path attr_accessor :disable_request_forgery_protection, :allowed_request_origins + attr_accessor :url def initialize @logger = Rails.logger diff --git a/lib/assets/javascripts/cable.coffee.erb b/lib/assets/javascripts/cable.coffee.erb index 8498233c11..25a9fc79c2 100644 --- a/lib/assets/javascripts/cable.coffee.erb +++ b/lib/assets/javascripts/cable.coffee.erb @@ -4,5 +4,9 @@ @Cable = INTERNAL: <%= ActionCable::INTERNAL.to_json %> - createConsumer: (url) -> + createConsumer: (url = @getConfig("url")) -> new Cable.Consumer url + + getConfig: (name) -> + element = document.head.querySelector("meta[name='action-cable-#{name}']") + element?.getAttribute("content")