Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cable_car aka 'Ajax mode' #108

Merged
merged 12 commits into from
Mar 30, 2021
9 changes: 9 additions & 0 deletions lib/cable_ready.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@

module CableReady
class Engine < Rails::Engine
initializer "renderer" do
ActiveSupport.on_load(:action_controller) do
ActionController::Renderers.add :operations do |operations, options|
self.content_type = Mime[:json]
# operations.respond_to?(:ride) ? operations.ride(options) : operations
operations
end
end
end
end

def self.config
Expand Down
5 changes: 5 additions & 0 deletions lib/cable_ready/broadcaster.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require_relative "channels"
require_relative "cable_car"

module CableReady
module Broadcaster
Expand All @@ -10,6 +11,10 @@ def cable_ready
CableReady::Channels.instance
end

def cable_car
CableReady::CableCar.instance
end

def dom_id(record, prefix = nil)
"##{ActionView::RecordIdentifier.dom_id(record, prefix)}"
end
Expand Down
56 changes: 56 additions & 0 deletions lib/cable_ready/cable_car.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# frozen_string_literal: true

require "thread/local"

module CableReady
class CableCar
extend Thread::Local
attr_reader :enqueued_operations

def initialize
reset
CableReady.config.operation_names.each { |name| add_operation_method name }

config_observer = self
CableReady.config.add_observer config_observer, :add_operation_method
ObjectSpace.define_finalizer self, -> { CableReady.config.delete_observer config_observer }
end

def ride(clear: true)
payload = transmitable_operations
reset if clear
payload
end

def add_operation_method(name)
return if respond_to?(name)
singleton_class.public_send :define_method, name, ->(options = {}) {
enqueued_operations[name.to_s] << options.stringify_keys
self # supports operation chaining
}
end

def apply(operations)
operations = operations.is_a?(Hash) ? operations : JSON.parse(operations)
operations.each do |operation_method|
key, operation = operation_method
operation.each do |enqueued_operation|
enqueued_operations[key] << enqueued_operation
end
end
self
end

private

def reset
@enqueued_operations = Hash.new { |hash, key| hash[key] = [] }
end

def transmitable_operations
enqueued_operations
.select { |_, list| list.present? }
.deep_transform_keys! { |key| key.to_s.camelize(:lower) }
end
end
end
3 changes: 0 additions & 3 deletions lib/cable_ready/channels.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,8 @@ module CableReady
class Channels
extend Thread::Local

attr_accessor :operations

def initialize
@channels = {}
@operations = {}
end

def [](identifier)
Expand Down