Class: Swarm::HiveDweller

Inherits:
Object
  • Object
show all
Extended by:
Enumerable
Defined in:
lib/swarm/hive_dweller.rb

Direct Known Subclasses

Expression, Process, ProcessDefinition, StoredWorkitem

Defined Under Namespace

Classes: MissingTypeError, RecordNotFoundError

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(hive: Hive.default, **args) ⇒ HiveDweller

Returns a new instance of HiveDweller.



10
11
12
13
14
# File 'lib/swarm/hive_dweller.rb', line 10

def initialize(hive: Hive.default, **args)
  @hive = hive
  @changed_attributes = {}
  set_attributes(args, record_changes: false)
end

Class Attribute Details

.associationsObject (readonly)

Returns the value of attribute associations.



97
98
99
# File 'lib/swarm/hive_dweller.rb', line 97

def associations
  @associations
end

.columnsObject (readonly)

Returns the value of attribute columns.



97
98
99
# File 'lib/swarm/hive_dweller.rb', line 97

def columns
  @columns
end

Instance Attribute Details

#hiveObject (readonly)

Returns the value of attribute hive.



8
9
10
# File 'lib/swarm/hive_dweller.rb', line 8

def hive
  @hive
end

#idObject (readonly)

Returns the value of attribute id.



8
9
10
# File 'lib/swarm/hive_dweller.rb', line 8

def id
  @id
end

Class Method Details

.all(hive: Hive.default, subtypes: true) ⇒ Object



211
212
213
214
215
# File 'lib/swarm/hive_dweller.rb', line 211

def all(hive: Hive.default, subtypes: true)
  hive.storage.all_of_type(storage_type, subtypes: subtypes).map { |hsh|
    reify_from_hash(hsh.dup, hive: hive)
  }
end

.create(hive: Hive.default, **args) ⇒ Object



168
169
170
# File 'lib/swarm/hive_dweller.rb', line 168

def create(hive: Hive.default, **args)
  new(hive: hive, created_at: Time.now, **args).save
end

.define_getter(arg) ⇒ Object



120
121
122
123
124
125
126
127
128
# File 'lib/swarm/hive_dweller.rb', line 120

def define_getter(arg)
  define_method(arg) {
    val = instance_variable_get(:"@#{arg}")
    if /_at$/.match(arg) && val.is_a?(String)
      val = Time.parse(val)
    end
    val
  }
end

.define_setter(arg) ⇒ Object



114
115
116
117
118
# File 'lib/swarm/hive_dweller.rb', line 114

def define_setter(arg)
  define_method("#{arg}=") do |value|
    change_attribute(arg, value)
  end
end

.each(hive: Hive.default, subtypes: true) ⇒ Object



200
201
202
203
204
205
206
207
208
209
# File 'lib/swarm/hive_dweller.rb', line 200

def each(hive: Hive.default, subtypes: true)
  return to_enum(__method__, hive: hive, subtypes: subtypes) unless block_given?

  ids(hive: hive).each do |id|
    object = fetch(id, hive: hive)
    if (subtypes && object.is_a?(self)) || object.instance_of?(self)
      yield object
    end
  end
end

.fetch(key, hive: Hive.default) ⇒ Object



191
192
193
194
# File 'lib/swarm/hive_dweller.rb', line 191

def fetch(key, hive: Hive.default)
  hsh = hive.storage[storage_id_for_key(key)].dup
  reify_from_hash(hsh, hive: hive)
end

.ids(hive: Hive.default) ⇒ Object



196
197
198
# File 'lib/swarm/hive_dweller.rb', line 196

def ids(hive: Hive.default)
  hive.storage.ids_for_type(storage_type)
end

.inherited(subclass) ⇒ Object



99
100
101
102
103
104
# File 'lib/swarm/hive_dweller.rb', line 99

def inherited(subclass)
  super
  subclass.instance_variable_set(:@columns, [])
  subclass.instance_variable_set(:@associations, {})
  subclass.set_columns :updated_at, :created_at
end

.many_to_one(association_name, class_name: nil, key: nil) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/swarm/hive_dweller.rb', line 151

def many_to_one(association_name, class_name: nil, key: nil)
  define_method(association_name) do
    memo = instance_variable_get(:"@#{association_name}")
    memo || begin
      key ||= :"#{association_name}_id"
      associated_id = send(key)
      return nil unless associated_id

      klass = Swarm::Support.constantize((class_name || association_name).to_s)
      instance_variable_set(:"@#{association_name}", klass.fetch(associated_id, hive: hive))
    end
  end
  @associations[association_name] = {
    type: :many_to_one, class_name: class_name || association_name, key: key
  }
end

.new_from_storage(**args) ⇒ Object



184
185
186
187
188
189
# File 'lib/swarm/hive_dweller.rb', line 184

def new_from_storage(**args)
  id = args.delete(:id)
  new(**args).tap { |instance|
    instance.instance_variable_set(:@id, id)
  }
end

.one_to_many(association_name, class_name: nil, foreign_key: nil) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/swarm/hive_dweller.rb', line 130

def one_to_many(association_name, class_name: nil, foreign_key: nil)
  define_method(association_name) do
    memo = instance_variable_get(:"@#{association_name}")
    memo || begin
      associations = hive.storage.load_associations(
        association_name, owner: self, class_name: class_name || association_name, foreign_key: foreign_key
      )
      entities = associations.map { |association| self.class.reify_from_hash(association, hive: hive) }
      instance_variable_set(:"@#{association_name}", entities)
    end
  end
  define_method(:"add_to_#{association_name}") do |associated|
    hive.storage.add_association(
      association_name, associated, owner: self, class_name: class_name || association_name, foreign_key: foreign_key
    )
  end
  @associations[association_name] = {
    type: :one_to_many, class_name: class_name || association_name, foreign_key: foreign_key
  }
end

.reify_from_hash(hsh, hive: Hive.default) ⇒ Object

Raises:



217
218
219
220
221
222
223
224
# File 'lib/swarm/hive_dweller.rb', line 217

def reify_from_hash(hsh, hive: Hive.default)
  Support.symbolize_keys!(hsh)
  raise MissingTypeError, hsh.inspect unless hsh[:type]

  Swarm::Support.constantize(hsh.delete(:type)).new_from_storage(
    **hsh.merge(hive: hive)
  )
end

.set_columns(*args) ⇒ Object



106
107
108
109
110
111
112
# File 'lib/swarm/hive_dweller.rb', line 106

def set_columns(*args)
  args.each do |arg|
    define_setter(arg)
    define_getter(arg)
  end
  @columns |= args
end

.storage_id_for_key(key) ⇒ Object



176
177
178
179
180
181
182
# File 'lib/swarm/hive_dweller.rb', line 176

def storage_id_for_key(key)
  if key.match(/^#{storage_type}:/)
    key
  else
    "#{storage_type}:#{key}"
  end
end

.storage_typeObject



172
173
174
# File 'lib/swarm/hive_dweller.rb', line 172

def storage_type
  name.split("::").last
end

Instance Method Details

#==(other) ⇒ Object



42
43
44
# File 'lib/swarm/hive_dweller.rb', line 42

def ==(other)
  other.is_a?(self.class) && other.to_hash == to_hash
end

#attributesObject



68
69
70
71
72
# File 'lib/swarm/hive_dweller.rb', line 68

def attributes
  self.class.columns.each_with_object({}) { |col_name, hsh|
    hsh[col_name.to_sym] = send(:"#{col_name}")
  }
end

#change_attribute(key, value, record: true) ⇒ Object



35
36
37
38
39
40
# File 'lib/swarm/hive_dweller.rb', line 35

def change_attribute(key, value, record: true)
  if record
    @changed_attributes[key] = [send(key), value]
  end
  instance_variable_set(:"@#{key}", value)
end

#changed?Boolean

Returns:

  • (Boolean)


20
21
22
# File 'lib/swarm/hive_dweller.rb', line 20

def changed?
  !@changed_attributes.empty?
end

#deleteObject



54
55
56
57
# File 'lib/swarm/hive_dweller.rb', line 54

def delete
  storage.delete(storage_id)
  self
end

#new?Boolean

Returns:

  • (Boolean)


16
17
18
# File 'lib/swarm/hive_dweller.rb', line 16

def new?
  id.nil?
end

#reload!Object



82
83
84
85
86
87
88
89
90
91
92
# File 'lib/swarm/hive_dweller.rb', line 82

def reload!
  hsh = hive.storage[storage_id]
  self.class.columns.each do |column|
    instance_variable_set(:"@#{column}", hsh[column.to_s])
  end
  self.class.associations.each_key do |name|
    instance_variable_set(:"@#{name}", nil)
  end
  @changed_attributes = {}
  self
end

#saveObject



59
60
61
62
63
64
65
66
# File 'lib/swarm/hive_dweller.rb', line 59

def save
  if new? || changed?
    @id ||= Swarm::Support.uuid_with_timestamp
    storage[storage_id] = to_hash.merge(updated_at: Time.now)
    reload!
  end
  self
end

#set_attributes(args, record_changes: true) ⇒ Object



24
25
26
27
28
29
30
31
32
33
# File 'lib/swarm/hive_dweller.rb', line 24

def set_attributes(args, record_changes: true)
  unknown_arguments = args.keys - self.class.columns
  unless unknown_arguments.empty?
    raise ArgumentError, "unknown keywords: #{unknown_arguments.join(', ')}"
  end

  args.each do |key, value|
    change_attribute(key, value, record: record_changes)
  end
end

#storageObject



50
51
52
# File 'lib/swarm/hive_dweller.rb', line 50

def storage
  @hive.storage
end

#storage_idObject



46
47
48
# File 'lib/swarm/hive_dweller.rb', line 46

def storage_id
  self.class.storage_id_for_key(id)
end

#to_hashObject



74
75
76
77
78
79
80
# File 'lib/swarm/hive_dweller.rb', line 74

def to_hash
  hsh = {
    id: id,
    type: self.class.name
  }
  hsh.merge(attributes)
end