hold 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|