Class: CableReady::OperationBuilder

Inherits:
Object
  • Object
show all
Includes:
Identifiable
Defined in:
lib/cable_ready/operation_builder.rb

Direct Known Subclasses

CableCar, Channel

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Identifiable

#dom_id, #identifiable?

Constructor Details

#initialize(identifier) ⇒ OperationBuilder

Returns a new instance of OperationBuilder.



15
16
17
18
19
20
21
22
# File 'lib/cable_ready/operation_builder.rb', line 15

def initialize(identifier)
  @identifier = identifier

  reset!
  CableReady.config.operation_names.each { |name| add_operation_method name }
  CableReady.config.add_observer self, :add_operation_method
  ObjectSpace.define_finalizer self, self.class.finalizer_for(identifier)
end

Instance Attribute Details

#identifierObject (readonly)

Returns the value of attribute identifier.



6
7
8
# File 'lib/cable_ready/operation_builder.rb', line 6

def identifier
  @identifier
end

#previous_selectorObject (readonly)

Returns the value of attribute previous_selector.



6
7
8
# File 'lib/cable_ready/operation_builder.rb', line 6

def previous_selector
  @previous_selector
end

#previous_xpathObject (readonly)

Returns the value of attribute previous_xpath.



6
7
8
# File 'lib/cable_ready/operation_builder.rb', line 6

def previous_xpath
  @previous_xpath
end

Class Method Details

.finalizer_for(identifier) ⇒ Object



8
9
10
11
12
13
# File 'lib/cable_ready/operation_builder.rb', line 8

def self.finalizer_for(identifier)
  proc {
    channel = CableReady.config.observers.find { |o| o.try(:identifier) == identifier }
    CableReady.config.delete_observer channel if channel
  }
end

Instance Method Details

#add_operation_method(name) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/cable_ready/operation_builder.rb', line 24

def add_operation_method(name)
  return if respond_to?(name)
  singleton_class.public_send :define_method, name, ->(*args) {
    if args.one? && args.first.respond_to?(:to_operation_options) && [Array, Hash].include?(args.first.to_operation_options.class)
      case args.first.to_operation_options
      when Array
        selector, options = nil, args.first.to_operation_options
          .select { |e| e.is_a?(Symbol) && args.first.respond_to?("to_#{e}".to_sym) }
          .each_with_object({}) { |option, memo| memo[option.to_s] = args.first.send("to_#{option}".to_sym) }
      when Hash
        selector, options = nil, args.first.to_operation_options
      else
        raise TypeError, ":to_operation_options returned an #{args.first.to_operation_options.class.name}. Must be an Array or Hash."
      end
    else
      selector, options = nil, args.first || {} # 1 or 0 params
      selector, options = options, {} unless options.is_a?(Hash) # swap if only selector provided
      selector, options = args[0, 2] if args.many? # 2 or more params
      options.stringify_keys!
      options.each { |key, value| options[key] = value.send("to_#{key}".to_sym) if value.respond_to?("to_#{key}".to_sym) }
    end
    options["selector"] = selector if selector && options.exclude?("selector")
    if previous_selector && options.exclude?("selector")
      options["selector"] = previous_selector
      options["xpath"] = previous_xpath if previous_xpath
    end
    if options.include?("selector")
      @previous_selector = options["selector"]
      @previous_xpath = options["xpath"]
      options["selector"] = identifiable?(previous_selector) ? dom_id(previous_selector) : previous_selector
    end
    options["operation"] = name.to_s.camelize(:lower)
    @enqueued_operations << options
    self
  }
end

#apply!(operations = "[]") ⇒ Object



65
66
67
68
69
70
71
72
73
# File 'lib/cable_ready/operation_builder.rb', line 65

def apply!(operations = "[]")
  operations = begin
    JSON.parse(operations.is_a?(String) ? operations : operations.to_json)
  rescue JSON::ParserError
    {}
  end
  @enqueued_operations.concat(Array.wrap(operations))
  self
end

#operations_payloadObject



75
76
77
# File 'lib/cable_ready/operation_builder.rb', line 75

def operations_payload
  @enqueued_operations.map { |operation| operation.deep_transform_keys! { |key| key.to_s.camelize(:lower) } }
end

#reset!Object



79
80
81
82
# File 'lib/cable_ready/operation_builder.rb', line 79

def reset!
  @enqueued_operations = []
  @previous_selector = nil
end

#to_json(*args) ⇒ Object



61
62
63
# File 'lib/cable_ready/operation_builder.rb', line 61

def to_json(*args)
  @enqueued_operations.to_json(*args)
end