diff options
Diffstat (limited to 'actioncable/lib/rails')
8 files changed, 117 insertions, 0 deletions
diff --git a/actioncable/lib/rails/generators/channel/USAGE b/actioncable/lib/rails/generators/channel/USAGE new file mode 100644 index 0000000000..ea9662436c --- /dev/null +++ b/actioncable/lib/rails/generators/channel/USAGE @@ -0,0 +1,12 @@ +Description: +============ + Stubs out a new cable channel for the server (in Ruby) and client (in JavaScript). + Pass the channel name, either CamelCased or under_scored, and an optional list of channel actions as arguments. + +Example: +======== + rails generate channel Chat speak + + creates a Chat channel class and JavaScript asset: + Channel: app/channels/chat_channel.rb + Assets: app/javascript/channels/chat_channel.js diff --git a/actioncable/lib/rails/generators/channel/channel_generator.rb b/actioncable/lib/rails/generators/channel/channel_generator.rb new file mode 100644 index 0000000000..ef51981e89 --- /dev/null +++ b/actioncable/lib/rails/generators/channel/channel_generator.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +module Rails + module Generators + class ChannelGenerator < NamedBase + source_root File.expand_path("templates", __dir__) + + argument :actions, type: :array, default: [], banner: "method method" + + class_option :assets, type: :boolean + + check_class_collision suffix: "Channel" + + def create_channel_file + template "channel.rb", File.join("app/channels", class_path, "#{file_name}_channel.rb") + + if options[:assets] + if behavior == :invoke + template "javascript/index.js", "app/javascript/channels/index.js" + template "javascript/consumer.js", "app/javascript/channels/consumer.js" + end + + js_template "javascript/channel", File.join("app/javascript/channels", class_path, "#{file_name}_channel") + end + + generate_application_cable_files + end + + private + def file_name + @_file_name ||= super.sub(/_channel\z/i, "") + end + + # FIXME: Change these files to symlinks once RubyGems 2.5.0 is required. + def generate_application_cable_files + return if behavior != :invoke + + files = [ + "application_cable/channel.rb", + "application_cable/connection.rb" + ] + + files.each do |name| + path = File.join("app/channels/", name) + template(name, path) if !File.exist?(path) + end + end + end + end +end diff --git a/actioncable/lib/rails/generators/channel/templates/application_cable/channel.rb.tt b/actioncable/lib/rails/generators/channel/templates/application_cable/channel.rb.tt new file mode 100644 index 0000000000..d672697283 --- /dev/null +++ b/actioncable/lib/rails/generators/channel/templates/application_cable/channel.rb.tt @@ -0,0 +1,4 @@ +module ApplicationCable + class Channel < ActionCable::Channel::Base + end +end diff --git a/actioncable/lib/rails/generators/channel/templates/application_cable/connection.rb.tt b/actioncable/lib/rails/generators/channel/templates/application_cable/connection.rb.tt new file mode 100644 index 0000000000..0ff5442f47 --- /dev/null +++ b/actioncable/lib/rails/generators/channel/templates/application_cable/connection.rb.tt @@ -0,0 +1,4 @@ +module ApplicationCable + class Connection < ActionCable::Connection::Base + end +end diff --git a/actioncable/lib/rails/generators/channel/templates/channel.rb.tt b/actioncable/lib/rails/generators/channel/templates/channel.rb.tt new file mode 100644 index 0000000000..4bcfb2be4d --- /dev/null +++ b/actioncable/lib/rails/generators/channel/templates/channel.rb.tt @@ -0,0 +1,16 @@ +<% module_namespacing do -%> +class <%= class_name %>Channel < ApplicationCable::Channel + def subscribed + # stream_from "some_channel" + end + + def unsubscribed + # Any cleanup needed when channel is unsubscribed + end +<% actions.each do |action| -%> + + def <%= action %> + end +<% end -%> +end +<% end -%> diff --git a/actioncable/lib/rails/generators/channel/templates/javascript/channel.js.tt b/actioncable/lib/rails/generators/channel/templates/javascript/channel.js.tt new file mode 100644 index 0000000000..33baaa5a22 --- /dev/null +++ b/actioncable/lib/rails/generators/channel/templates/javascript/channel.js.tt @@ -0,0 +1,20 @@ +import consumer from "./consumer" + +consumer.subscriptions.create("<%= class_name %>Channel", { + connected: function() { + // Called when the subscription is ready for use on the server + }, + + disconnected: function() { + // Called when the subscription has been terminated by the server + }, + + received: function(data) { + // Called when there's incoming data on the websocket for this channel + }<%= actions.any? ? ",\n" : '' %> +<% actions.each do |action| -%> + <%=action %>: function() { + return this.perform('<%= action %>'); + }<%= action == actions[-1] ? '' : ",\n" %> +<% end -%> +}); diff --git a/actioncable/lib/rails/generators/channel/templates/javascript/consumer.js.tt b/actioncable/lib/rails/generators/channel/templates/javascript/consumer.js.tt new file mode 100644 index 0000000000..76ca3d0f2f --- /dev/null +++ b/actioncable/lib/rails/generators/channel/templates/javascript/consumer.js.tt @@ -0,0 +1,6 @@ +// 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. + +import ActionCable from "actioncable" + +export default ActionCable.createConsumer() diff --git a/actioncable/lib/rails/generators/channel/templates/javascript/index.js.tt b/actioncable/lib/rails/generators/channel/templates/javascript/index.js.tt new file mode 100644 index 0000000000..0cfcf74919 --- /dev/null +++ b/actioncable/lib/rails/generators/channel/templates/javascript/index.js.tt @@ -0,0 +1,5 @@ +// Load all the channels within this directory and all subdirectories. +// Channel files must be named *_channel.js. + +const channels = require.context('.', true, /_channel\.js$/) +channels.keys().forEach(channels) |