Class: Crimson::Model

Inherits:
SimpleDelegator
  • Object
show all
Defined in:
lib/crimson/model.rb

Direct Known Subclasses

Object

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeModel

Returns a new instance of Model.



12
13
14
15
16
17
18
19
20
# File 'lib/crimson/model.rb', line 12

def initialize
  @observers = {}
  @revisions = [Mash.new]
  @revision_number = 1
  @max_number_of_revisions = 2
  @local = Mash.new

  super(local)
end

Instance Attribute Details

#localObject (readonly)

Returns the value of attribute local.



10
11
12
# File 'lib/crimson/model.rb', line 10

def local
  @local
end

#observersObject (readonly)

Returns the value of attribute observers.



10
11
12
# File 'lib/crimson/model.rb', line 10

def observers
  @observers
end

#revision_numberObject (readonly)

Returns the value of attribute revision_number.



10
11
12
# File 'lib/crimson/model.rb', line 10

def revision_number
  @revision_number
end

#revisionsObject (readonly)

Returns the value of attribute revisions.



10
11
12
# File 'lib/crimson/model.rb', line 10

def revisions
  @revisions
end

Instance Method Details

#add_observer(observer, handler = :on_commit) ⇒ Object



22
23
24
# File 'lib/crimson/model.rb', line 22

def add_observer(observer, handler = :on_commit)
  observers[observer] = observer.method(handler)
end

#apply_changes!(*keys) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
# File 'lib/crimson/model.rb', line 74

def apply_changes!(*keys)
  if keys.empty?
    revisions << Utilities.deep_copy(local)
  else
    revisions << Utilities.deep_copy(master)
    keys.each { |key| master[key] = Utilities.deep_copy(local[key]) }
  end

  @revision_number += 1
  revisions.shift if revisions.length > @max_number_of_revisions
end

#changed?(*keys) ⇒ Boolean

Returns:

  • (Boolean)


38
39
40
41
42
43
44
# File 'lib/crimson/model.rb', line 38

def changed?(*keys)
  if keys.empty?
    local != master
  else
    keys.map { |key| local[key] != master[key] }.any?(true)
  end
end

#changes(*keys) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/crimson/model.rb', line 46

def changes(*keys)
  keys = ( master.keys | local.keys ) if keys.empty?
  diff = Mash.new

  keys.each do |k|
    v1 = master[k]
    v2 = local[k]
    diff[k] = ModelChange.new(v1, v2) if v1 != v2
  end

  diff
end

#commit!(*keys) ⇒ Object



67
68
69
70
71
72
# File 'lib/crimson/model.rb', line 67

def commit!(*keys)
  if changed?(*keys)
    notify_observers(new_changes(*keys))
    apply_changes!(*keys)
  end
end

#masterObject



63
64
65
# File 'lib/crimson/model.rb', line 63

def master
  revisions.last
end

#modify(modifications = {}) ⇒ Object



34
35
36
# File 'lib/crimson/model.rb', line 34

def modify(modifications = {})
  local.merge(modifications)
end

#new_changes(*keys) ⇒ Object



59
60
61
# File 'lib/crimson/model.rb', line 59

def new_changes(*keys)
  changes(*keys).transform_values(&:new_value)
end

#notify_observers(changes) ⇒ Object



30
31
32
# File 'lib/crimson/model.rb', line 30

def notify_observers(changes)
  observers.each { |_observer, handler| handler.call(self, changes) }
end

#reload!Object



86
87
88
# File 'lib/crimson/model.rb', line 86

def reload!
  @local = Utilities.deep_copy(master)
end

#remove_observer(observer) ⇒ Object



26
27
28
# File 'lib/crimson/model.rb', line 26

def remove_observer(observer)
  observers.delete(observer)
end

#rollback!Object



90
91
92
93
94
95
96
# File 'lib/crimson/model.rb', line 90

def rollback!
  if revisions.length > 1
    @local = revisions.pop
  else
    reload!
  end
end