Class: Zui::StateStore

Inherits:
Object
  • Object
show all
Defined in:
lib/zui/state_store.rb

Instance Method Summary collapse

Constructor Details

#initialize(on_change) ⇒ StateStore

Returns a new instance of StateStore.



5
6
7
8
9
10
11
# File 'lib/zui/state_store.rb', line 5

def initialize(on_change)
  @values = {}
  @on_change = on_change
  @lock = Mutex.new
  @transaction_depth = 0
  @pending = {}
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *arguments) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/zui/state_store.rb', line 41

def method_missing(name, *arguments)
  raw = name.to_s
  if raw.end_with?("=")
    raise ArgumentError, "expected one value" unless arguments.length == 1

    return write(raw.delete_suffix("=").to_sym, arguments.first)
  end
  if arguments.empty?
    found, value = @lock.synchronize { [@values.key?(name), @values[name]] }
    return value if found
  end

  super
end

Instance Method Details

#[](name) ⇒ Object



21
22
23
# File 'lib/zui/state_store.rb', line 21

def [](name)
  @lock.synchronize { @values.fetch(name.to_sym) }
end

#[]=(name, value) ⇒ Object



25
26
27
# File 'lib/zui/state_store.rb', line 25

def []=(name, value)
  write(name.to_sym, value)
end

#define(name, initial) ⇒ Object



13
14
15
16
17
18
19
# File 'lib/zui/state_store.rb', line 13

def define(name, initial)
  key = name.to_sym
  @lock.synchronize do
    raise ArgumentError, "state already defined: #{key}" if @values.key?(key)
    @values[key] = initial
  end
end

#respond_to_missing?(name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


56
57
58
59
# File 'lib/zui/state_store.rb', line 56

def respond_to_missing?(name, include_private = false)
  key = name.to_s.delete_suffix("=").to_sym
  @lock.synchronize { @values.key?(key) } || super
end

#transactionObject



61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/zui/state_store.rb', line 61

def transaction
  raise ArgumentError, "transaction requires a block" unless block_given?
  @lock.synchronize { @transaction_depth += 1 }
  yield self
ensure
  changes = @lock.synchronize do
    @transaction_depth -= 1
    next [] unless @transaction_depth.zero?
    flushed = @pending.values
    @pending.clear
    flushed
  end
  changes.each { |change| @on_change.call(*change) }
end

#update(name) ⇒ Object

Raises:

  • (ArgumentError)


29
30
31
32
33
34
35
36
37
38
39
# File 'lib/zui/state_store.rb', line 29

def update(name)
  raise ArgumentError, "update requires a block" unless block_given?
  key = name.to_sym
  change, value = @lock.synchronize do
    raise NoMethodError, "unknown state: #{key}" unless @values.key?(key)
    next_value = yield(@values[key])
    [store_locked(key, next_value), next_value]
  end
  @on_change.call(*change) if change
  value
end