ObjectModel 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +849 -0
- data/lib/ObjectModel.res/config.yaml +5 -0
- data/lib/ObjectModel/AnEntity/BackReferences.rb +113 -0
- data/lib/ObjectModel/AnEntity/Bag.rb +129 -0
- data/lib/ObjectModel/AnEntity/BagCopy.rb +29 -0
- data/lib/ObjectModel/AnEntity/ChildrenBag.rb +10 -0
- data/lib/ObjectModel/AnEntity/EntityCopy.rb +38 -0
- data/lib/ObjectModel/AnEntity/EntityType.rb +408 -0
- data/lib/ObjectModel/AnEntity/ReferencesBag.rb +10 -0
- data/lib/ObjectModel/AnEntity/entity_cm.rb +108 -0
- data/lib/ObjectModel/Entity.rb +278 -0
- data/lib/ObjectModel/Errors/LoadError.rb +3 -0
- data/lib/ObjectModel/Errors/NoTransactionError.rb +3 -0
- data/lib/ObjectModel/Errors/NotFoundError.rb +2 -0
- data/lib/ObjectModel/Errors/OutdatedError.rb +8 -0
- data/lib/ObjectModel/Errors/ValidationError.rb +3 -0
- data/lib/ObjectModel/Indexes/HashIndex.rb +64 -0
- data/lib/ObjectModel/Indexes/IndexStorage.rb +64 -0
- data/lib/ObjectModel/Indexes/Manager.rb +72 -0
- data/lib/ObjectModel/Metadata.rb +34 -0
- data/lib/ObjectModel/Metadata.res/after_event_types.rb +25 -0
- data/lib/ObjectModel/Metadata.res/attribute_types_shortcuts.rb +10 -0
- data/lib/ObjectModel/Metadata.res/before_event_types.rb +25 -0
- data/lib/ObjectModel/Metadata.res/child_types_shortcuts.rb +4 -0
- data/lib/ObjectModel/Metadata.res/metadata_checks.rb +9 -0
- data/lib/ObjectModel/Metadata.res/reference_types_shortcuts.rb +4 -0
- data/lib/ObjectModel/Metadata/DSL.rb +11 -0
- data/lib/ObjectModel/Metadata/attribute.rb +56 -0
- data/lib/ObjectModel/Metadata/child.rb +50 -0
- data/lib/ObjectModel/Metadata/events.rb +109 -0
- data/lib/ObjectModel/Metadata/name.rb +20 -0
- data/lib/ObjectModel/Metadata/reference.rb +50 -0
- data/lib/ObjectModel/Metadata/require.rb +10 -0
- data/lib/ObjectModel/Metadata/validate.rb +66 -0
- data/lib/ObjectModel/Repository.rb +326 -0
- data/lib/ObjectModel/Repository/EventProcessor.rb +58 -0
- data/lib/ObjectModel/Repository/ObjectStorage.rb +102 -0
- data/lib/ObjectModel/Repository/StreamID.rb +20 -0
- data/lib/ObjectModel/Repository/StreamStorage.rb +121 -0
- data/lib/ObjectModel/Repository/SystemListener.rb +143 -0
- data/lib/ObjectModel/Repository/Transaction.rb +63 -0
- data/lib/ObjectModel/Repository/TransactionProcessor.rb +36 -0
- data/lib/ObjectModel/Tools/DefaultTransactionStrategy.rb +9 -0
- data/lib/ObjectModel/Tools/InMemoryCache.rb +9 -0
- data/lib/ObjectModel/Tools/NoCache.rb +18 -0
- data/lib/ObjectModel/Tools/OGLRUCache.rb +37 -0
- data/lib/ObjectModel/Types/BagType.rb +94 -0
- data/lib/ObjectModel/Types/BooleanType.rb +42 -0
- data/lib/ObjectModel/Types/ClassType.rb +43 -0
- data/lib/ObjectModel/Types/DataType.rb +44 -0
- data/lib/ObjectModel/Types/DateType.rb +43 -0
- data/lib/ObjectModel/Types/NumberType.rb +62 -0
- data/lib/ObjectModel/Types/ObjectType.rb +164 -0
- data/lib/ObjectModel/Types/ProcType.rb +43 -0
- data/lib/ObjectModel/Types/SingleType.rb +59 -0
- data/lib/ObjectModel/Types/StringType.rb +39 -0
- data/lib/ObjectModel/_require.rb +43 -0
- data/lib/ObjectModel/require.rb +1 -0
- data/rakefile +62 -0
- data/spec/ObjectModel/BasicSpec/BaseClass.rb +7 -0
- data/spec/ObjectModel/BasicSpec/BaseTypes.rb +11 -0
- data/spec/ObjectModel/BasicSpec/Descendant.rb +5 -0
- data/spec/ObjectModel/BasicSpec/EachTest.rb +14 -0
- data/spec/ObjectModel/BasicSpec/UpChild.rb +10 -0
- data/spec/ObjectModel/BasicSpec/UpParent.rb +11 -0
- data/spec/ObjectModel/ErrorsSpec/AfterCommitError.rb +9 -0
- data/spec/ObjectModel/ExtendedSpec/CustomInitialization.rb +11 -0
- data/spec/ObjectModel/ExtendedSpec/UpNotNil.rb +8 -0
- data/spec/ObjectModel/ExtendedSpec/UpParent.rb +11 -0
- data/spec/ObjectModel/ValidationSpec/BaseTypes.rb +11 -0
- data/spec/aspect_spec.rb +55 -0
- data/spec/back_references_spec.rb +161 -0
- data/spec/basic_spec.rb +162 -0
- data/spec/cascade_delete_spec.rb +168 -0
- data/spec/complex_events_spec.rb +134 -0
- data/spec/concurrency_spec.rb +186 -0
- data/spec/containment_spec.rb +146 -0
- data/spec/data_migration_spec.rb +51 -0
- data/spec/errors_spec.rb +65 -0
- data/spec/events_spec.rb +173 -0
- data/spec/extended_spec.rb +171 -0
- data/spec/indexing_spec.rb +56 -0
- data/spec/set_in_memory.rb +2 -0
- data/spec/set_no_cache.rb +2 -0
- data/spec/smoke_test_spec.rb +85 -0
- data/spec/stream_spec.rb +143 -0
- data/spec/stream_storage.rb +148 -0
- data/spec/timer.rb +5 -0
- data/spec/validation_spec.rb +87 -0
- metadata +186 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
class Transaction
|
|
2
|
+
attr_reader :copies, :name, :new_entities, :event_processor, :repository, :system_listener, :deleted_entities
|
|
3
|
+
attr_writer :repository, :name
|
|
4
|
+
attr_accessor :managed
|
|
5
|
+
|
|
6
|
+
def initialize
|
|
7
|
+
@name = "default"
|
|
8
|
+
@copies = Hash.new{|hash, key| raise "Can't find Copy for '#{key}'entity_id!"}
|
|
9
|
+
@new_entities = Hash.new{|hash, key| raise "Can't find New Entity for '#{key}' entity_id!"}
|
|
10
|
+
@deleted_entities = Hash.new{|hash, key| raise "Can't find Deleted Entity for '#{key}' entity_id!"}
|
|
11
|
+
@event_processor = EventProcessor.new(self)
|
|
12
|
+
@system_listener = SystemListener.new(self)
|
|
13
|
+
@commited = false
|
|
14
|
+
@managed = false
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def copy_get! entity
|
|
18
|
+
unless @copies.include? entity.entity_id
|
|
19
|
+
copy = AnEntity::EntityType.create_copy entity
|
|
20
|
+
@copies[entity.entity_id] = copy
|
|
21
|
+
end
|
|
22
|
+
@copies[entity.entity_id]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def resolve entity_id
|
|
26
|
+
if @new_entities.include? entity_id
|
|
27
|
+
@new_entities[entity_id]
|
|
28
|
+
elsif @deleted_entities.include? entity_id
|
|
29
|
+
@deleted_entities[entity_id]
|
|
30
|
+
else
|
|
31
|
+
@repository.by_id(entity_id)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def commited!
|
|
36
|
+
@commited = true
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def commited?
|
|
40
|
+
@commited
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def commit
|
|
44
|
+
@repository.commit self
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def changed? entity_id
|
|
48
|
+
entity_id.should! :be_a, String
|
|
49
|
+
@copies.include?(entity_id) || @new_entities.include?(entity_id)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def to_s
|
|
53
|
+
types = {:new => 0, :deleted => 0, :updated => 0, :moved => 0}
|
|
54
|
+
methods = types.keys
|
|
55
|
+
@copies.values.each do |c|
|
|
56
|
+
methods.each do |m|
|
|
57
|
+
types[m] += 1 if c.send :"#{m}?"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
return "#<Transaction: #{@name}#{commited? ? ", commited" : ""}, #{types.inspect}>"
|
|
61
|
+
end
|
|
62
|
+
alias_method :inspect, :to_s
|
|
63
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
class TransactionProcessor
|
|
2
|
+
inherit Log
|
|
3
|
+
|
|
4
|
+
def initialize repository, transaction
|
|
5
|
+
@repository, @transaction = repository, transaction
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def check_outdated
|
|
9
|
+
outdated = []
|
|
10
|
+
@transaction.copies.each do |entity_id, c|
|
|
11
|
+
next if c.new?
|
|
12
|
+
e = @repository.by_id(entity_id)
|
|
13
|
+
outdated << entity_id if c.om_version != e.om_version
|
|
14
|
+
end
|
|
15
|
+
raise_without_self OutdatedError.new(outdated), "Outdated Entities: ['#{outdated.join('\', \'')}']", ObjectModel unless outdated.empty?
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def write_back
|
|
19
|
+
@transaction.copies.each do |entity_id, copy|
|
|
20
|
+
next if copy.deleted?
|
|
21
|
+
entity = @transaction.resolve entity_id
|
|
22
|
+
AnEntity::EntityType.write_back copy, entity
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def persist
|
|
27
|
+
@transaction.copies.each do |entity_id, copy|
|
|
28
|
+
entity = @transaction.resolve entity_id
|
|
29
|
+
if copy.deleted?
|
|
30
|
+
AnEntity::EntityType.delete entity, @repository.storage
|
|
31
|
+
else
|
|
32
|
+
AnEntity::EntityType.persist copy, entity, @repository.storage
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# It should have max_items at least equal to 1!
|
|
2
|
+
class OGLRUCache < LRUCache
|
|
3
|
+
class EntityContainer
|
|
4
|
+
include LRUCache::Item
|
|
5
|
+
|
|
6
|
+
attr_reader :entity
|
|
7
|
+
def initialize entity
|
|
8
|
+
@entity = entity
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def initialize repository, percentage
|
|
13
|
+
@repository, @percentage = repository, percentage
|
|
14
|
+
super(1)
|
|
15
|
+
update_size
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def [](key)
|
|
19
|
+
container = super(key)
|
|
20
|
+
nil == container ? nil : container.entity
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def []=(key, item)
|
|
24
|
+
container = EntityContainer.new item
|
|
25
|
+
super(key, container)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def update transaction
|
|
29
|
+
transaction.copies.each{|entity_id, c| delete entity_id if c.deleted?}
|
|
30
|
+
update_size
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
protected
|
|
34
|
+
def update_size
|
|
35
|
+
self.max_items = (@repository.size * @percentage).floor + 1
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
class BagType
|
|
2
|
+
class << self
|
|
3
|
+
def initial_value m, e
|
|
4
|
+
calculate_class(m).new e, m.name, e.om_repository
|
|
5
|
+
# e.instance_variable_set m.ivname, bag
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def initialize_copy m, e, c
|
|
9
|
+
bag = e.instance_variable_get m.ivname
|
|
10
|
+
bag_copy = AnEntity::BagCopy.new bag._array
|
|
11
|
+
c[m.ivname] = bag_copy
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize_storage db
|
|
15
|
+
db.create_table :bags do
|
|
16
|
+
column :entity_id, :text
|
|
17
|
+
column :name, :text
|
|
18
|
+
column :reference_id, :text
|
|
19
|
+
# index :entity_id
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def print_storage db, name
|
|
24
|
+
return unless name == nil or name == :bags
|
|
25
|
+
puts "\nBags:"
|
|
26
|
+
db[:bags].print
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def load m, e, storage
|
|
30
|
+
rows = storage[:bags].filter :entity_id => e.entity_id, :name => m.name.to_s
|
|
31
|
+
bag = calculate_class(m).new e, m.name, e.om_repository
|
|
32
|
+
rows.each do |row|
|
|
33
|
+
value = AnEntity::EntityType.load_id row[:reference_id]
|
|
34
|
+
bag._array << value
|
|
35
|
+
end
|
|
36
|
+
e.instance_variable_set m.ivname, bag
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def write_back c, e, m
|
|
40
|
+
bag_copy = c[m.ivname]
|
|
41
|
+
bag = e.instance_variable_get m.ivname
|
|
42
|
+
bag._array.replace bag_copy._array # TODO reimplement more efficiently
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def persist c, entity_id, m, storage
|
|
46
|
+
# TODO reimplement more efficiently
|
|
47
|
+
sname = m.name.to_s
|
|
48
|
+
storage[:bags].filter(:entity_id => entity_id, :name => sname).delete
|
|
49
|
+
c[m.ivname]._array.each do |ref_id|
|
|
50
|
+
ref_id.should_not! :be_nil
|
|
51
|
+
storage[:bags].insert(
|
|
52
|
+
:entity_id => entity_id,
|
|
53
|
+
:name => sname,
|
|
54
|
+
:reference_id => AnEntity::EntityType.dump_id(ref_id)
|
|
55
|
+
)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def delete e, m, storage
|
|
60
|
+
storage[:bags].filter(:entity_id => e.entity_id).delete
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def delete_all_children e, m
|
|
64
|
+
bag = e.send m.name
|
|
65
|
+
bag.every.delete
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def delete_all_references_to referrer, e, m
|
|
69
|
+
bag = referrer.send m.name
|
|
70
|
+
bag.delete e
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def delete_from_parent e, parent, m
|
|
74
|
+
bag = parent.send m.name
|
|
75
|
+
bag.delete e
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def each e, m, &b
|
|
79
|
+
bag = e.send m.name
|
|
80
|
+
bag.each &b
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
protected
|
|
84
|
+
def calculate_class m
|
|
85
|
+
if m.is_a? Metadata::Child
|
|
86
|
+
AnEntity::ChildrenBag
|
|
87
|
+
elsif m.is_a? Metadata::Reference
|
|
88
|
+
AnEntity::ReferencesBag
|
|
89
|
+
else
|
|
90
|
+
should! :be_never_called
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
class BooleanType
|
|
2
|
+
class << self
|
|
3
|
+
inherit Log
|
|
4
|
+
|
|
5
|
+
def initial_value m, e
|
|
6
|
+
false
|
|
7
|
+
# e.instance_variable_set m.ivname, false
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def initialize_copy m, e, c
|
|
11
|
+
value_copy = e.instance_variable_get(m.ivname).copy
|
|
12
|
+
c[m.ivname] = value_copy
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def load m, e, storage
|
|
16
|
+
row = storage[:entities_content][:entity_id => e.entity_id, :name => m.name.to_s]
|
|
17
|
+
raise LoadError unless row and row[:class] == "BOOLEAN"
|
|
18
|
+
|
|
19
|
+
e.instance_variable_set m.ivname, (row[:value] == "false" ? false : true)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def persist c, entity_id, m, storage
|
|
23
|
+
value = c[m.ivname] ? "true" : "false"
|
|
24
|
+
storage[:entities_content].insert(
|
|
25
|
+
:entity_id => entity_id,
|
|
26
|
+
:name => m.name.to_s,
|
|
27
|
+
:value => value,
|
|
28
|
+
:class => "BOOLEAN"
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def write_back c, e, m
|
|
33
|
+
value = c[m.ivname]
|
|
34
|
+
value.should! :be_a, [TrueClass, FalseClass]
|
|
35
|
+
e.instance_variable_set m.ivname, value
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def validate_type value
|
|
39
|
+
value == true or value == false
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
class ClassType
|
|
2
|
+
class << self
|
|
3
|
+
def initial_value m, e
|
|
4
|
+
nil
|
|
5
|
+
# e.instance_variable_set m.ivname, nil
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def initialize_copy m, e, c
|
|
9
|
+
value_copy = e.instance_variable_get(m.ivname)
|
|
10
|
+
c[m.ivname] = value_copy
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def write_back c, e, m
|
|
14
|
+
value = c[m.ivname]
|
|
15
|
+
value.should! :be_a, [NilClass, Module, Class]
|
|
16
|
+
e.instance_variable_set m.ivname, value
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def load m, e, storage
|
|
20
|
+
row = storage[:entities_content][:entity_id => e.entity_id, :name => m.name.to_s]
|
|
21
|
+
|
|
22
|
+
raise LoadError unless row and row[:class] == "CLASS"
|
|
23
|
+
value = row[:value]
|
|
24
|
+
value = eval(value, TOPLEVEL_BINDING, __FILE__, __LINE__) if value
|
|
25
|
+
e.instance_variable_set m.ivname, value
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def persist c, entity_id, m, storage
|
|
29
|
+
value = c[m.ivname]
|
|
30
|
+
value = value.name if value
|
|
31
|
+
storage[:entities_content].insert(
|
|
32
|
+
:entity_id => entity_id,
|
|
33
|
+
:name => m.name.to_s,
|
|
34
|
+
:value => value,
|
|
35
|
+
:class => "CLASS"
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def validate_type value
|
|
40
|
+
value == nil or value.is_a?(Module) or value.is_a?(Class)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
class DataType
|
|
2
|
+
class << self
|
|
3
|
+
def initial_value m, e
|
|
4
|
+
nil
|
|
5
|
+
# e.instance_variable_set m.ivname, nil
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def initialize_copy m, e, c
|
|
9
|
+
value = e.instance_variable_get(m.ivname)
|
|
10
|
+
value_copy = value != nil ? Repository::StreamID.new(value.sid) : nil
|
|
11
|
+
c[m.ivname] = value_copy
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def write_back c, e, m
|
|
15
|
+
value = c[m.ivname]
|
|
16
|
+
value.should! :be_a, [NilClass, Repository::StreamID]
|
|
17
|
+
e.instance_variable_set m.ivname, value
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def load m, e, storage
|
|
21
|
+
row = storage[:entities_content][:entity_id => e.entity_id, :name => m.name.to_s]
|
|
22
|
+
raise LoadError unless row and row[:class] == "STREAM_ID"
|
|
23
|
+
|
|
24
|
+
stream_id = row[:value]
|
|
25
|
+
value = stream_id == "nil" ? nil : Repository::StreamID.new(stream_id)
|
|
26
|
+
e.instance_variable_set m.ivname, value
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def persist c, entity_id, m, storage
|
|
30
|
+
value = c[m.ivname]
|
|
31
|
+
stream_id = value == nil ? "nil" : value.sid
|
|
32
|
+
storage[:entities_content].insert(
|
|
33
|
+
:entity_id => entity_id,
|
|
34
|
+
:name => m.name.to_s,
|
|
35
|
+
:value => stream_id,
|
|
36
|
+
:class => "STREAM_ID"
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def validate_type value
|
|
41
|
+
value == nil or value.is_a? StreamID
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
class DateType
|
|
2
|
+
class << self
|
|
3
|
+
def initial_value m, e
|
|
4
|
+
nil
|
|
5
|
+
# e.instance_variable_set m.ivname, nil
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def initialize_copy m, e, c
|
|
9
|
+
value = e.instance_variable_get(m.ivname)
|
|
10
|
+
value_copy = value != nil ? value.clone : nil
|
|
11
|
+
c[m.ivname] = value_copy
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def write_back c, e, m
|
|
15
|
+
value = c[m.ivname]
|
|
16
|
+
value.should! :be_a, [NilClass, DateTime]
|
|
17
|
+
e.instance_variable_set m.ivname, value
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def persist c, entity_id, m, storage
|
|
21
|
+
value = c[m.ivname]
|
|
22
|
+
str_value = value == nil ? "nil" : value.to_s
|
|
23
|
+
storage[:entities_content].insert(
|
|
24
|
+
:entity_id => entity_id,
|
|
25
|
+
:name => m.name.to_s,
|
|
26
|
+
:value => str_value,
|
|
27
|
+
:class => "DATE"
|
|
28
|
+
)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def load m, e, storage
|
|
32
|
+
row = storage[:entities_content][:entity_id => e.entity_id, :name => m.name.to_s]
|
|
33
|
+
raise LoadError unless row and row[:class] == "DATE"
|
|
34
|
+
|
|
35
|
+
value = row[:value]
|
|
36
|
+
e.instance_variable_set m.ivname, (value == "nil" ? nil : DateTime.parse(value))
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def validate_type value
|
|
40
|
+
value == nil or value.is_a? DateTime
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|