hold 1.0.2 → 1.0.3
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.
- checksums.yaml +4 -4
- data/lib/hold.rb +16 -8
- data/lib/hold/error.rb +28 -0
- data/lib/hold/file/hash_repository.rb +49 -42
- data/lib/hold/in_memory.rb +11 -179
- data/lib/hold/in_memory/array_cell.rb +27 -0
- data/lib/hold/in_memory/cell.rb +30 -0
- data/lib/hold/in_memory/hash_repository.rb +28 -0
- data/lib/hold/in_memory/identity_set_repository.rb +49 -0
- data/lib/hold/in_memory/object_cell.rb +30 -0
- data/lib/hold/in_memory/set_repository.rb +28 -0
- data/lib/hold/interfaces.rb +17 -439
- data/lib/hold/interfaces/array_cell.rb +49 -0
- data/lib/hold/interfaces/cell.rb +61 -0
- data/lib/hold/interfaces/hash_repository.rb +63 -0
- data/lib/hold/interfaces/identity_set_repository.rb +118 -0
- data/lib/hold/interfaces/object_cell.rb +103 -0
- data/lib/hold/interfaces/set_repository.rb +37 -0
- data/lib/hold/sequel.rb +12 -11
- data/lib/hold/sequel/identity_set_repository.rb +1 -8
- data/lib/hold/sequel/polymorphic_repository.rb +105 -96
- data/lib/hold/sequel/property_mapper.rb +144 -119
- data/lib/hold/sequel/query_array_cell.rb +19 -14
- data/lib/hold/sequel/repository_observer.rb +25 -21
- data/lib/hold/sequel/with_polymorphic_type_column.rb +145 -99
- data/lib/hold/serialized.rb +2 -104
- data/lib/hold/serialized/hash_repository.rb +50 -0
- data/lib/hold/serialized/identity_set_repository.rb +58 -0
- data/lib/hold/version.rb +2 -1
- metadata +78 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c24da8a40bff937b20200d7c3165c6b7f1aca2a
|
4
|
+
data.tar.gz: 34bc4c8bfe75830097e022376abd0a6b6d431d76
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eef09f90c3496dbedf8d9e651e8ae8dd6b9b2501a74fb9cf318c249b846787b622083eaee78a480d8d3a76fdca1611d219b9ec772edd98ca7949834d0cbe59c3
|
7
|
+
data.tar.gz: 3cfc1289ae4df6e2d633af0eeb2cfc129709e2b7d744f17eec5f48ee439ac793fa61dd0ae2a8bb5e8d956bbd9cb7a11f8520453240181e89a361223c7acf7b5e
|
data/lib/hold.rb
CHANGED
@@ -1,12 +1,20 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require 'hold/interfaces'
|
2
|
+
require 'hold/file/hash_repository'
|
3
|
+
require 'hold/sequel'
|
4
4
|
|
5
|
-
|
5
|
+
require 'hold/error'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
# Top level namespace
|
8
|
+
module Hold
|
9
|
+
end
|
10
|
+
|
11
|
+
unless defined?(Persistence)
|
12
|
+
|
13
|
+
# Display a warning if the old gem name is used.
|
14
|
+
module Persistence
|
15
|
+
def self.const_missing(const_name)
|
16
|
+
warn "'Persistence' has been deprecated, please use 'Hold' instead"
|
17
|
+
Hold.const_get(const_name)
|
18
|
+
end
|
11
19
|
end
|
12
20
|
end
|
data/lib/hold/error.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Hold
|
2
|
+
# Error tag module
|
3
|
+
module Error; end
|
4
|
+
|
5
|
+
# Base error for Hold module
|
6
|
+
class StdError < StandardError
|
7
|
+
extend Error
|
8
|
+
|
9
|
+
attr_reader :original
|
10
|
+
|
11
|
+
def initialize(msg = nil, original = $ERROR_INFO)
|
12
|
+
super(msg)
|
13
|
+
@original = original
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# UnsupoortedOperation
|
18
|
+
class UnsupportedOperation < StdError; end
|
19
|
+
|
20
|
+
# EmptyConflict
|
21
|
+
class EmptyConflict < StdError; end
|
22
|
+
|
23
|
+
# IdentityConflict
|
24
|
+
class IdentityConflict < StdError; end
|
25
|
+
|
26
|
+
# MissingIdentity
|
27
|
+
class MissingIdentity < StdError; end
|
28
|
+
end
|
@@ -1,59 +1,66 @@
|
|
1
1
|
require 'hold/interfaces'
|
2
2
|
require 'fileutils'
|
3
3
|
|
4
|
-
# A simple HashRepository (ie key/value store implementation) which stores each
|
5
|
-
# key in a separate file.
|
6
|
-
#
|
7
|
-
# * Keys must be suitable pathnames
|
8
|
-
# * Values must be strings
|
9
|
-
# * base_path should end with a /, or keys should start with a /, one or the other
|
10
|
-
# * subdirectories will be created as required if the keys contain path separators
|
11
|
-
# * watch out for per-directory file limits.
|
12
|
-
#
|
13
|
-
# NB: Not threadsafe for writes
|
14
4
|
module Hold
|
15
|
-
module File
|
5
|
+
module File
|
6
|
+
# A simple HashRepository (ie key/value store implementation) which stores
|
7
|
+
# each key in a separate file.
|
8
|
+
#
|
9
|
+
# * Keys must be suitable pathnames
|
10
|
+
# * Values must be strings
|
11
|
+
# * base_path should end with a /, or keys should start with a /, one or the
|
12
|
+
# other
|
13
|
+
# * subdirectories will be created as required if the keys contain path
|
14
|
+
# separators
|
15
|
+
# * watch out for per-directory file limits.
|
16
|
+
#
|
17
|
+
# NB: Not threadsafe for writes
|
18
|
+
class HashRepository
|
19
|
+
include Hold::HashRepository
|
16
20
|
|
17
|
-
|
18
|
-
|
21
|
+
def can_get_class?(klass)
|
22
|
+
klass == String
|
23
|
+
end
|
19
24
|
|
20
|
-
|
21
|
-
|
25
|
+
def can_set_class?(klass)
|
26
|
+
klass == String
|
27
|
+
end
|
22
28
|
|
23
|
-
|
24
|
-
|
25
|
-
|
29
|
+
def initialize(base_path)
|
30
|
+
@base_path = base_path
|
31
|
+
end
|
26
32
|
|
27
|
-
|
28
|
-
|
29
|
-
|
33
|
+
def path_to_key(key)
|
34
|
+
"#{@base_path}#{key}"
|
35
|
+
end
|
30
36
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
+
def set_with_key(key, value)
|
38
|
+
path = path_to_key(key)
|
39
|
+
FileUtils.mkdir_p(::File.dirname(path))
|
40
|
+
::File.open(path, 'wb') { |file| file.write(value.to_s) }
|
41
|
+
value
|
42
|
+
end
|
37
43
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
44
|
+
def get_with_key(key)
|
45
|
+
path = path_to_key(key)
|
46
|
+
begin
|
47
|
+
::File.read(path)
|
48
|
+
rescue Errno::ENOENT
|
49
|
+
end
|
43
50
|
end
|
44
|
-
end
|
45
51
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
52
|
+
def clear_key(key)
|
53
|
+
path = path_to_key(key)
|
54
|
+
begin
|
55
|
+
::File.unlink(path)
|
56
|
+
rescue Errno::ENOENT
|
57
|
+
end
|
51
58
|
end
|
52
|
-
end
|
53
59
|
|
54
|
-
|
55
|
-
|
60
|
+
def key?(key)
|
61
|
+
::File.exist?(path_to_key(key))
|
62
|
+
end
|
63
|
+
alias_method :has_key?, :key?
|
56
64
|
end
|
57
|
-
alias_method :key?, :has_key?
|
58
65
|
end
|
59
66
|
end
|
data/lib/hold/in_memory.rb
CHANGED
@@ -1,184 +1,16 @@
|
|
1
|
-
require '
|
2
|
-
|
1
|
+
require 'hold/in_memory/cell'
|
2
|
+
require 'hold/in_memory/array_cell'
|
3
|
+
require 'hold/in_memory/object_cell'
|
4
|
+
require 'hold/in_memory/hash_repository'
|
5
|
+
require 'hold/in_memory/set_repository'
|
6
|
+
require 'hold/in_memory/identity_set_repository'
|
7
|
+
|
8
|
+
# namespace module
|
3
9
|
module Hold
|
4
|
-
|
5
|
-
#
|
6
|
-
#
|
7
|
-
# tests, and for illustrative purposes.
|
10
|
+
# These are a set of implementations of Hold interfaces based on in-memory
|
11
|
+
# storage. They're not threadsafe or for production use, but are here as
|
12
|
+
# lightweight implementations to use in tests, and for illustrative purposes.
|
8
13
|
module InMemory; end
|
9
14
|
|
10
15
|
ARG_EMPTY = Object.new.freeze # something different to everything else
|
11
|
-
|
12
|
-
class InMemory::Cell
|
13
|
-
include Hold::Cell
|
14
|
-
|
15
|
-
# new -- empty
|
16
|
-
# new(nil) -- non-empty, value is nil
|
17
|
-
# new(123) -- non-empty, value is 123
|
18
|
-
def initialize(value=ARG_EMPTY)
|
19
|
-
@value = value unless ARG_EMPTY.equal?(value)
|
20
|
-
end
|
21
|
-
|
22
|
-
def get
|
23
|
-
@value
|
24
|
-
end
|
25
|
-
|
26
|
-
def set(value)
|
27
|
-
@value = value
|
28
|
-
end
|
29
|
-
|
30
|
-
def empty?
|
31
|
-
!instance_variable_defined?(:@value)
|
32
|
-
end
|
33
|
-
|
34
|
-
def clear
|
35
|
-
remove_instance_variable(:@value) if instance_variable_defined?(:@value)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
class InMemory::ArrayCell
|
40
|
-
include Hold::ArrayCell
|
41
|
-
|
42
|
-
def initialize(array=[])
|
43
|
-
@array = array
|
44
|
-
end
|
45
|
-
|
46
|
-
def get
|
47
|
-
@array.dup
|
48
|
-
end
|
49
|
-
|
50
|
-
def set(value)
|
51
|
-
@array.replace(value)
|
52
|
-
end
|
53
|
-
|
54
|
-
def get_slice(start,length)
|
55
|
-
@array[start, length]
|
56
|
-
end
|
57
|
-
|
58
|
-
def get_length
|
59
|
-
@array.length
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
class InMemory::ObjectCell < InMemory::Cell
|
64
|
-
include Hold::ObjectCell
|
65
|
-
|
66
|
-
def get
|
67
|
-
@value && @value.dup
|
68
|
-
end
|
69
|
-
|
70
|
-
def get_property(property_name)
|
71
|
-
@value && @value[property_name]
|
72
|
-
end
|
73
|
-
|
74
|
-
def set_property(property_name, value)
|
75
|
-
raise EmptyConflict unless @value
|
76
|
-
@value[property_name] = value
|
77
|
-
end
|
78
|
-
|
79
|
-
def clear_property(property_name)
|
80
|
-
raise EmptyConflict unless @value
|
81
|
-
@value.delete(property_name)
|
82
|
-
end
|
83
|
-
|
84
|
-
def has_property?(property_name)
|
85
|
-
raise EmptyConflict unless @value
|
86
|
-
@value.has_key?(property_name)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
class InMemory::HashRepository
|
91
|
-
include Hold::HashRepository
|
92
|
-
|
93
|
-
def initialize
|
94
|
-
@hash = {}
|
95
|
-
end
|
96
|
-
|
97
|
-
def set_with_key(key, value)
|
98
|
-
@hash[key] = value
|
99
|
-
end
|
100
|
-
|
101
|
-
def get_with_key(key)
|
102
|
-
value = @hash[key] and value.dup
|
103
|
-
end
|
104
|
-
|
105
|
-
def clear_key(key)
|
106
|
-
@hash.delete(key)
|
107
|
-
end
|
108
|
-
|
109
|
-
def has_key?(key)
|
110
|
-
@hash.key?(key)
|
111
|
-
end
|
112
|
-
alias_method :key?, :has_key?
|
113
|
-
end
|
114
|
-
|
115
|
-
class InMemory::SetRepository
|
116
|
-
include Hold::SetRepository
|
117
|
-
|
118
|
-
def initialize
|
119
|
-
@set = Set.new
|
120
|
-
end
|
121
|
-
|
122
|
-
def store(value)
|
123
|
-
@set << value
|
124
|
-
end
|
125
|
-
|
126
|
-
def delete(value)
|
127
|
-
@set.delete(value)
|
128
|
-
end
|
129
|
-
|
130
|
-
def contains?(value)
|
131
|
-
@set.include?(value)
|
132
|
-
end
|
133
|
-
|
134
|
-
def get_all
|
135
|
-
@set.to_a
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
class InMemory::IdentitySetRepository
|
140
|
-
include Hold::IdentitySetRepository
|
141
|
-
|
142
|
-
def initialize(allocates_ids=false)
|
143
|
-
@by_id = {}
|
144
|
-
@id_seq = 0 if allocates_ids
|
145
|
-
end
|
146
|
-
|
147
|
-
def allocates_ids?
|
148
|
-
!!@id_seq
|
149
|
-
end
|
150
|
-
|
151
|
-
def store(object)
|
152
|
-
id = object.id
|
153
|
-
object.send(:id=, id = @id_seq += 1) if @id_seq && !id
|
154
|
-
raise MissingIdentity unless id
|
155
|
-
@by_id[id] = object
|
156
|
-
end
|
157
|
-
|
158
|
-
def delete(object)
|
159
|
-
id = object.id or raise MissingIdentity
|
160
|
-
delete_id(id)
|
161
|
-
end
|
162
|
-
|
163
|
-
def contains?(object)
|
164
|
-
id = object.id or raise MissingIdentity
|
165
|
-
@by_id.include?(id)
|
166
|
-
end
|
167
|
-
|
168
|
-
def get_all
|
169
|
-
@by_id.values
|
170
|
-
end
|
171
|
-
|
172
|
-
def get_by_id(id)
|
173
|
-
value = @by_id[id] and value.dup
|
174
|
-
end
|
175
|
-
|
176
|
-
def delete_id(id)
|
177
|
-
@by_id.delete(id)
|
178
|
-
end
|
179
|
-
|
180
|
-
def contains_id?(id)
|
181
|
-
@by_id.include?(id)
|
182
|
-
end
|
183
|
-
end
|
184
16
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Hold
|
2
|
+
module InMemory
|
3
|
+
class ArrayCell
|
4
|
+
include Hold::ArrayCell
|
5
|
+
|
6
|
+
def initialize(array=[])
|
7
|
+
@array = array
|
8
|
+
end
|
9
|
+
|
10
|
+
def get
|
11
|
+
@array.dup
|
12
|
+
end
|
13
|
+
|
14
|
+
def set(value)
|
15
|
+
@array.replace(value)
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_slice(start,length)
|
19
|
+
@array[start, length]
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_length
|
23
|
+
@array.length
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Hold
|
2
|
+
module InMemory
|
3
|
+
class Cell
|
4
|
+
include Hold::Cell
|
5
|
+
|
6
|
+
# new -- empty
|
7
|
+
# new(nil) -- non-empty, value is nil
|
8
|
+
# new(123) -- non-empty, value is 123
|
9
|
+
def initialize(value=ARG_EMPTY)
|
10
|
+
@value = value unless ARG_EMPTY.equal?(value)
|
11
|
+
end
|
12
|
+
|
13
|
+
def get
|
14
|
+
@value
|
15
|
+
end
|
16
|
+
|
17
|
+
def set(value)
|
18
|
+
@value = value
|
19
|
+
end
|
20
|
+
|
21
|
+
def empty?
|
22
|
+
!instance_variable_defined?(:@value)
|
23
|
+
end
|
24
|
+
|
25
|
+
def clear
|
26
|
+
remove_instance_variable(:@value) if instance_variable_defined?(:@value)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Hold
|
2
|
+
module InMemory
|
3
|
+
class HashRepository
|
4
|
+
include Hold::HashRepository
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@hash = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def set_with_key(key, value)
|
11
|
+
@hash[key] = value
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_with_key(key)
|
15
|
+
value = @hash[key] and value.dup
|
16
|
+
end
|
17
|
+
|
18
|
+
def clear_key(key)
|
19
|
+
@hash.delete(key)
|
20
|
+
end
|
21
|
+
|
22
|
+
def has_key?(key)
|
23
|
+
@hash.key?(key)
|
24
|
+
end
|
25
|
+
alias_method :key?, :has_key?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|