garland 1.2.2 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a00d71fb025dd71c34da87926327385c4278a2a6
4
- data.tar.gz: 09a6733560c52e47f1065e35900ad4bbfd4a15c0
3
+ metadata.gz: 89056f6fadd0309a8e4829b17bdd788cd0643bc9
4
+ data.tar.gz: 33567da54c9bae23ffa87d26bb95ed3fc95795b0
5
5
  SHA512:
6
- metadata.gz: 04640cac5d39141ef5030df7d1b2b3b1e56c3b2b4e4ee31550ac9056675cdd55da7451e0332bc4a8b4e16e8998af9855b4c098ffdcf935afb9d17507c6af8a58
7
- data.tar.gz: ad3318e2a4b883b3cfe199870b30522c2e471088271eee39b58e9cc021c73d4f979dd164e41ae36493ec62fe7581c8e0f74ef0789c84010c28455dc8aa760c4d
6
+ metadata.gz: 17f6eec112cd6888fb8e2eac3bf654facaaf1195658739ee39ad1f2ccc2d834dc491e78b42dc92bc3516a8b62e9d655f27f70a7469318e8ce01c5cc44ceea812
7
+ data.tar.gz: 811a1222362482f420e5fc4db1b915a2a15f60da6a9b84ce39c66d2398c4db02b144167ca69577888d0fd5bd37d7986bf5c575abdca2022059eea54aea5195ce
@@ -1,267 +1,10 @@
1
1
  module GarlandRails
2
2
  DIFF = true
3
3
  SNAPSHOT = false
4
-
5
- module Extend
6
- def self.included(base)
7
- base.extend(self)
8
- end
9
-
10
- def has_many(name, scope = nil, options = {}, &extension)
11
- name_superclass = name.to_s.classify.constantize.superclass
12
- if name_superclass == GarlandRails::Base
13
- # if there are no scope and there are some options,
14
- # scope will contain options, and we need to swap them
15
- if scope.class == Hash
16
- options = scope
17
- scope = nil
18
- end
19
-
20
- belongs_to_type = self.name
21
- scope = -> { where(belongs_to_type: belongs_to_type) }
22
- options = options.merge(foreign_key: "belongs_to_id")
23
- end
24
-
25
- super(name, scope, options, &extension)
26
- end
27
- end
28
-
29
- class Base < Garland
30
- self.table_name = "garlands"
31
-
32
- validates :entity, presence: true
33
- validates_inclusion_of :entity_type, in: [DIFF, SNAPSHOT]
34
-
35
- # for given parent object, described by "belongs_to_id" and "belongs_to_type",
36
- # there are only one record of each type which is head or tail
37
- validates_uniqueness_of :type, scope: [
38
- :belongs_to_id,
39
- :belongs_to_type,
40
- :next_id,
41
- ], conditions: -> { where("next_id IS NULL OR previous_id IS NULL") }
42
-
43
- # everything seems to work without `polymorphic: true`,
44
- # but we will set it just for accordance to docs
45
- def self.belongs_to(name, scope = nil, options = {}, &extension)
46
- if scope.class == Hash
47
- options = scope
48
- scope = nil
49
- end
50
- options = options.merge(foreign_key: "belongs_to_id")
51
-
52
- super(name, scope, options, &extension)
53
- end
54
-
55
- def self.push(args)
56
- return nil unless args.class == Hash
57
-
58
- if args[:hash]
59
- hash = args[:hash]
60
- return nil unless hash.class == Hash
61
-
62
- belongs_to = args[:belongs_to]
63
- if belongs_to
64
- belongs_to_params = self._split_belongs_to(belongs_to)
65
- belongs_to_id, belongs_to_type =
66
- belongs_to_params.values_at(:belongs_to_id, :belongs_to_type)
67
- end
68
- else
69
- hash = args
70
- belongs_to = nil
71
- belongs_to_id = nil
72
- belongs_to_type = nil
73
- end
74
-
75
- head = self.head(belongs_to)
76
- if head
77
- diff = self.insert_diff(hash, belongs_to)
78
- else
79
- diff = self.init(hash, belongs_to)
80
- end
81
-
82
- diff
83
- end
84
-
85
- def self.thread(belongs_to = nil)
86
- if belongs_to
87
- return self.where(
88
- "belongs_to_id = ? AND belongs_to_type = ?",
89
- belongs_to.id, table_type(belongs_to)
90
- )
91
- else
92
- return self.where("belongs_to_id is null AND belongs_to_type is null")
93
- end
94
- end
95
-
96
- def self.tail(belongs_to = nil)
97
- self.thread(belongs_to).find_by(previous_id: nil)
98
- end
99
-
100
- def self.head(belongs_to = nil)
101
- self.thread(belongs_to).find_by(next_id: nil)
102
- end
103
-
104
- def self.last_diff(belongs_to = nil)
105
- head = self.head(belongs_to)
106
- return nil unless head
107
-
108
- head.previous
109
- end
110
-
111
- def next
112
- Garland.find(self.next_id) if self.next_id
113
- end
114
-
115
- def previous
116
- Garland.find(self.previous_id) if self.previous_id
117
- end
118
-
119
- def safe_eval_entity
120
- return nil unless self.entity =~ /\[.*\]/ || self.entity =~ /{.*}/
121
-
122
- eval(self.entity)
123
- end
124
-
125
- def self.table_type(record)
126
- record.class.name
127
- end
128
-
129
- def self.any?(belongs_to = nil)
130
- self.thread(belongs_to).any?
131
- end
132
-
133
- def self.init(hash, belongs_to = nil)
134
- common_props = self._split_belongs_to(belongs_to)
135
-
136
- tail_props = common_props.merge(entity: {}.to_s, entity_type: SNAPSHOT)
137
- brand_new_tail = self.new(tail_props)
138
-
139
- diff = HashDiffSym.diff({}, hash)
140
- first_diff_props = common_props.merge(entity: diff.to_s, entity_type: DIFF)
141
- first_diff = self.new(first_diff_props)
142
-
143
- head_props = common_props.merge(entity: hash.to_s, entity_type: SNAPSHOT)
144
- brand_new_head = self.new(head_props)
145
-
146
- self.transaction do
147
- ActiveRecord::Base.connection.create_savepoint("savepoint_before_init")
148
-
149
- # first id: tail ({})
150
- # second id: head (latest snapshot)
151
- # third+: diffs
152
- unless brand_new_tail.save
153
- Rails.logger.error("Unable to create new tail with props '#{tail_props}'")
154
- ActiveRecord::Base.connection.release_savepoint("savepoint_before_init")
155
- return nil
156
- end
157
-
158
- # belongs_to validations were in `brand_new_tail.save`
159
- # here and below validations may be skipped as long as we check for continuity later
160
- brand_new_head.save(validate: false)
161
- first_diff.save(validate: false)
162
- brand_new_tail.update_attribute(:next_id, first_diff.id)
163
- first_diff.update_attribute(:previous_id, brand_new_tail.id)
164
- first_diff.update_attribute(:next_id, brand_new_head.id)
165
- brand_new_head.update_attribute(:previous_id, first_diff.id)
166
-
167
- unless self.continuous?(belongs_to)
168
- Rails.logger.error("Initialized garland is not continuous")
169
- ActiveRecord::Base.connection.exec_rollback_to_savepoint("savepoint_before_init")
170
- ActiveRecord::Base.connection.release_savepoint("savepoint_before_init")
171
- return nil
172
- end
173
- end
174
-
175
- first_diff
176
- end
177
-
178
- def self.insert_diff(hash, belongs_to = nil)
179
- head = self.head(belongs_to)
180
- last_diff = self.find_by(id: head.previous_id)
181
- common_props = self._split_belongs_to(belongs_to)
182
-
183
- diff = HashDiffSym.diff(head.safe_eval_entity, hash)
184
- return unless diff.any?
185
-
186
- new_diff_props = common_props.merge(
187
- entity: diff.to_s,
188
- entity_type: DIFF,
189
- previous_id: last_diff.id,
190
- next_id: head.id,
191
- )
192
- new_diff = self.new(new_diff_props)
193
-
194
- self.transaction do
195
- ActiveRecord::Base.connection.create_savepoint("savepoint_before_insert_diff")
196
-
197
- # insert_diff should not use skipping valudatuons methods
198
- # because we don't want to check for continuity on every push
199
- unless new_diff.save
200
- Rails.logger.error("Unable to create new_diff with props '#{new_diff_props}'")
201
- ActiveRecord::Base.connection.release_savepoint("savepoint_before_init")
202
- return nil
203
- end
204
-
205
- last_diff.next_id = new_diff.id
206
- unless last_diff.save
207
- Rails.logger.error("Unable to save last_diff with 'next_id' = '#{new_diff.id}'")
208
- ActiveRecord::Base.connection.exec_rollback_to_savepoint("savepoint_before_insert_diff")
209
- ActiveRecord::Base.connection.release_savepoint("savepoint_before_init")
210
- return nil
211
- end
212
-
213
- head.previous_id = new_diff.id
214
- unless head.save
215
- Rails.logger.error("Unable to save head with 'previous_id' = '#{new_diff.id}'")
216
- ActiveRecord::Base.connection.exec_rollback_to_savepoint("savepoint_before_insert_diff")
217
- ActiveRecord::Base.connection.release_savepoint("savepoint_before_init")
218
- return nil
219
- end
220
-
221
- head.entity = hash.to_s
222
- unless head.save
223
- Rails.logger.error("Unable to save head with 'entity' = '#{hash}'")
224
- ActiveRecord::Base.connection.exec_rollback_to_savepoint("savepoint_before_insert_diff")
225
- ActiveRecord::Base.connection.release_savepoint("savepoint_before_init")
226
- return nil
227
- end
228
- end
229
-
230
- new_diff
231
- end
232
-
233
- def self.continuous?(belongs_to = nil)
234
- tail = self.tail(belongs_to)
235
- head = self.head(belongs_to)
236
- return false unless tail && head
237
-
238
- current_bulb = tail
239
- current_hash = tail.safe_eval_entity
240
- items_counted = 1
241
- while current_bulb.next_id do
242
- items_counted += 1
243
- current_bulb = current_bulb.next
244
- if current_bulb.entity_type == DIFF
245
- current_hash = HashDiffSym.patch!(current_hash, current_bulb.safe_eval_entity)
246
- else
247
- break
248
- end
249
- end
250
-
251
- items_counted == self.thread(belongs_to).size && current_hash == head.safe_eval_entity
252
- end
253
-
254
- private
255
- def self._split_belongs_to(belongs_to)
256
- if belongs_to
257
- belongs_to_id = belongs_to.id
258
- belongs_to_type = table_type(belongs_to)
259
- else
260
- belongs_to_id = nil
261
- belongs_to_type = nil
262
- end
263
-
264
- { belongs_to_id: belongs_to_id, belongs_to_type: belongs_to_type }
265
- end
266
- end
267
4
  end
5
+
6
+ require "garland_rails/extend.rb"
7
+ require "garland_rails/base.rb"
8
+ require "garland_rails/utils.rb"
9
+ require "garland_rails/snapshot.rb"
10
+ require "garland_rails/push.rb"
@@ -0,0 +1,34 @@
1
+ module GarlandRails
2
+ class Base < Garland
3
+ self.table_name = "garlands"
4
+
5
+ validates :entity, presence: true
6
+ validates_inclusion_of :entity_type, in: [DIFF, SNAPSHOT]
7
+
8
+ # for given parent object, described by "belongs_to_id" and "belongs_to_type",
9
+ # there are only one record of each type which is head or tail
10
+ validates_uniqueness_of :type, scope: [
11
+ :belongs_to_id,
12
+ :belongs_to_type,
13
+ :next_id,
14
+ ], conditions: -> { where("next_id IS NULL OR previous_id IS NULL") }
15
+
16
+ # Minitest raises "No visible difference in the *#inspect output" error
17
+ # while comparing Garland objects without this.
18
+ def ==(other)
19
+ self.attributes == other.attributes
20
+ end
21
+
22
+ # everything seems to work without `polymorphic: true`,
23
+ # but we will set it just for accordance to docs
24
+ def self.belongs_to(name, scope = nil, options = {}, &extension)
25
+ if scope.class == Hash
26
+ options = scope
27
+ scope = nil
28
+ end
29
+ options = options.merge(foreign_key: "belongs_to_id")
30
+
31
+ super(name, scope, options, &extension)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,25 @@
1
+ module GarlandRails
2
+ module Extend
3
+ def self.included(base)
4
+ base.extend(self)
5
+ end
6
+
7
+ def has_many(name, scope = nil, options = {}, &extension)
8
+ name_superclass = name.to_s.classify.constantize.superclass
9
+ if name_superclass == GarlandRails::Base
10
+ # if there are no scope and there are some options,
11
+ # scope will contain options, and we need to swap them
12
+ if scope.class == Hash
13
+ options = scope
14
+ scope = nil
15
+ end
16
+
17
+ belongs_to_type = self.name
18
+ scope = -> { where(belongs_to_type: belongs_to_type) }
19
+ options = options.merge(foreign_key: "belongs_to_id")
20
+ end
21
+
22
+ super(name, scope, options, &extension)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,133 @@
1
+ module GarlandRails
2
+ class Base < Garland
3
+ def self.push(args)
4
+ return nil unless args.class == Hash
5
+
6
+ if args[:hash]
7
+ hash = args[:hash]
8
+ return nil unless hash.class == Hash
9
+
10
+ belongs_to = args[:belongs_to]
11
+ if belongs_to
12
+ belongs_to_params = self._split_belongs_to(belongs_to)
13
+ belongs_to_id, belongs_to_type =
14
+ belongs_to_params.values_at(:belongs_to_id, :belongs_to_type)
15
+ end
16
+ else
17
+ hash = args
18
+ belongs_to = nil
19
+ belongs_to_id = nil
20
+ belongs_to_type = nil
21
+ end
22
+
23
+ head = self.head(belongs_to)
24
+ if head
25
+ diff = self.insert_diff(hash, belongs_to)
26
+ else
27
+ diff = self.init(hash, belongs_to)
28
+ end
29
+
30
+ diff
31
+ end
32
+
33
+ def self.init(hash, belongs_to = nil)
34
+ common_props = self._split_belongs_to(belongs_to)
35
+
36
+ tail_props = common_props.merge(entity: {}.to_s, entity_type: SNAPSHOT)
37
+ brand_new_tail = self.new(tail_props)
38
+
39
+ diff = HashDiffSym.diff({}, hash)
40
+ first_diff_props = common_props.merge(entity: diff.to_s, entity_type: DIFF)
41
+ first_diff = self.new(first_diff_props)
42
+
43
+ head_props = common_props.merge(entity: hash.to_s, entity_type: SNAPSHOT)
44
+ brand_new_head = self.new(head_props)
45
+
46
+ self.transaction do
47
+ ActiveRecord::Base.connection.create_savepoint("savepoint_before_init")
48
+
49
+ # first id: tail ({})
50
+ # second id: head (latest snapshot)
51
+ # third+: diffs
52
+ unless brand_new_tail.save
53
+ Rails.logger.error("Unable to create new tail with props '#{tail_props}'")
54
+ ActiveRecord::Base.connection.release_savepoint("savepoint_before_init")
55
+ return nil
56
+ end
57
+
58
+ # belongs_to validations were in `brand_new_tail.save`
59
+ # here and below validations may be skipped as long as we check for continuity later
60
+ brand_new_head.save(validate: false)
61
+ first_diff.save(validate: false)
62
+ brand_new_tail.update_attribute(:next_id, first_diff.id)
63
+ first_diff.update_attribute(:previous_id, brand_new_tail.id)
64
+ first_diff.update_attribute(:next_id, brand_new_head.id)
65
+ brand_new_head.update_attribute(:previous_id, first_diff.id)
66
+
67
+ unless self.continuous?(belongs_to)
68
+ Rails.logger.error("Initialized garland is not continuous")
69
+ ActiveRecord::Base.connection.exec_rollback_to_savepoint("savepoint_before_init")
70
+ ActiveRecord::Base.connection.release_savepoint("savepoint_before_init")
71
+ return nil
72
+ end
73
+ end
74
+
75
+ first_diff
76
+ end
77
+
78
+ def self.insert_diff(hash, belongs_to = nil)
79
+ head = self.head(belongs_to)
80
+ last_diff = self.find_by(id: head.previous_id)
81
+ common_props = self._split_belongs_to(belongs_to)
82
+
83
+ diff = HashDiffSym.diff(head.safe_eval_entity, hash)
84
+ return unless diff.any?
85
+
86
+ new_diff_props = common_props.merge(
87
+ entity: diff.to_s,
88
+ entity_type: DIFF,
89
+ previous_id: last_diff.id,
90
+ next_id: head.id,
91
+ )
92
+ new_diff = self.new(new_diff_props)
93
+
94
+ self.transaction do
95
+ ActiveRecord::Base.connection.create_savepoint("savepoint_before_insert_diff")
96
+
97
+ # insert_diff should not use skipping valudatuons methods
98
+ # because we don't want to check for continuity on every push
99
+ unless new_diff.save
100
+ Rails.logger.error("Unable to create new_diff with props '#{new_diff_props}'")
101
+ ActiveRecord::Base.connection.release_savepoint("savepoint_before_init")
102
+ return nil
103
+ end
104
+
105
+ last_diff.next_id = new_diff.id
106
+ unless last_diff.save
107
+ Rails.logger.error("Unable to save last_diff with 'next_id' = '#{new_diff.id}'")
108
+ ActiveRecord::Base.connection.exec_rollback_to_savepoint("savepoint_before_insert_diff")
109
+ ActiveRecord::Base.connection.release_savepoint("savepoint_before_init")
110
+ return nil
111
+ end
112
+
113
+ head.previous_id = new_diff.id
114
+ unless head.save
115
+ Rails.logger.error("Unable to save head with 'previous_id' = '#{new_diff.id}'")
116
+ ActiveRecord::Base.connection.exec_rollback_to_savepoint("savepoint_before_insert_diff")
117
+ ActiveRecord::Base.connection.release_savepoint("savepoint_before_init")
118
+ return nil
119
+ end
120
+
121
+ head.entity = hash.to_s
122
+ unless head.save
123
+ Rails.logger.error("Unable to save head with 'entity' = '#{hash}'")
124
+ ActiveRecord::Base.connection.exec_rollback_to_savepoint("savepoint_before_insert_diff")
125
+ ActiveRecord::Base.connection.release_savepoint("savepoint_before_init")
126
+ return nil
127
+ end
128
+ end
129
+
130
+ new_diff
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,53 @@
1
+ module GarlandRails
2
+ class Base < Garland
3
+ def snapshot(patch_direction = :backward)
4
+ case patch_direction
5
+ when :forward
6
+ approach_nearest_snapshot_method = :previous
7
+ back_method = :next
8
+ patch_method = :patch!
9
+ when :backward
10
+ approach_nearest_snapshot_method = :next
11
+ back_method = :previous
12
+ patch_method = :unpatch!
13
+ end
14
+
15
+ if self.entity_type == SNAPSHOT
16
+ snapshot = self.safe_eval_entity
17
+ else
18
+ nearest_snapshot = self
19
+ while nearest_snapshot.entity_type != SNAPSHOT do
20
+ nearest_snapshot = nearest_snapshot.send(approach_nearest_snapshot_method)
21
+ end
22
+
23
+ snapshot = nearest_snapshot.safe_eval_entity
24
+ current_bulb = nearest_snapshot.send(back_method)
25
+ loop do
26
+ break if current_bulb == self
27
+ HashDiffSym.send(patch_method, snapshot, current_bulb.safe_eval_entity)
28
+ current_bulb = current_bulb.send(back_method)
29
+ end
30
+
31
+ # this comes from asymmetry of Garland model
32
+ #
33
+ # entity => producing snapshot:
34
+ #
35
+ # tail => {}
36
+ # diff1 => hash1
37
+ # diff2 => hash2
38
+ # diff3 => hash3
39
+ # head => hash3
40
+ if patch_direction == :forward
41
+ HashDiffSym.send(patch_method, snapshot, current_bulb.safe_eval_entity)
42
+ end
43
+ end
44
+
45
+ Garland.new(
46
+ entity_type: SNAPSHOT,
47
+ entity: snapshot.to_s,
48
+ created_at: self.created_at,
49
+ type: self.type,
50
+ )
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,86 @@
1
+ module GarlandRails
2
+ class Base < Garland
3
+ # REVIEW: shouldn't thread(), tail() and head() have the same args as push()?
4
+ def self.thread(belongs_to = nil)
5
+ if belongs_to
6
+ return self.where(
7
+ "belongs_to_id = ? AND belongs_to_type = ?",
8
+ belongs_to.id, table_type(belongs_to)
9
+ )
10
+ else
11
+ return self.where("belongs_to_id is null AND belongs_to_type is null")
12
+ end
13
+ end
14
+
15
+ def self.tail(belongs_to = nil)
16
+ self.thread(belongs_to).find_by(previous_id: nil)
17
+ end
18
+
19
+ def self.head(belongs_to = nil)
20
+ self.thread(belongs_to).find_by(next_id: nil)
21
+ end
22
+
23
+ def self.last_diff(belongs_to = nil)
24
+ head = self.head(belongs_to)
25
+ return nil unless head
26
+
27
+ head.previous
28
+ end
29
+
30
+ def self.continuous?(belongs_to = nil)
31
+ tail = self.tail(belongs_to)
32
+ head = self.head(belongs_to)
33
+ return false unless tail && head
34
+
35
+ current_bulb = tail
36
+ current_hash = tail.safe_eval_entity
37
+ items_counted = 1
38
+ while current_bulb.next_id do
39
+ items_counted += 1
40
+ current_bulb = current_bulb.next
41
+ if current_bulb.entity_type == DIFF
42
+ current_hash = HashDiffSym.patch!(current_hash, current_bulb.safe_eval_entity)
43
+ else
44
+ break
45
+ end
46
+ end
47
+
48
+ items_counted == self.thread(belongs_to).size && current_hash == head.safe_eval_entity
49
+ end
50
+
51
+ def self.table_type(record)
52
+ record.class.name
53
+ end
54
+
55
+ def self.any?(belongs_to = nil)
56
+ self.thread(belongs_to).any?
57
+ end
58
+
59
+ def next
60
+ Garland.find(self.next_id) if self.next_id
61
+ end
62
+
63
+ def previous
64
+ Garland.find(self.previous_id) if self.previous_id
65
+ end
66
+
67
+ def safe_eval_entity
68
+ return nil unless self.entity =~ /\[.*\]/ || self.entity =~ /{.*}/
69
+
70
+ eval(self.entity)
71
+ end
72
+
73
+ private
74
+ def self._split_belongs_to(belongs_to)
75
+ if belongs_to
76
+ belongs_to_id = belongs_to.id
77
+ belongs_to_type = table_type(belongs_to)
78
+ else
79
+ belongs_to_id = nil
80
+ belongs_to_type = nil
81
+ end
82
+
83
+ { belongs_to_id: belongs_to_id, belongs_to_type: belongs_to_type }
84
+ end
85
+ end
86
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: garland
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Morozov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-24 00:00:00.000000000 Z
11
+ date: 2017-01-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashdiff_sym
@@ -33,6 +33,11 @@ extra_rdoc_files: []
33
33
  files:
34
34
  - lib/garland.rb
35
35
  - lib/garland_rails.rb
36
+ - lib/garland_rails/base.rb
37
+ - lib/garland_rails/extend.rb
38
+ - lib/garland_rails/push.rb
39
+ - lib/garland_rails/snapshot.rb
40
+ - lib/garland_rails/utils.rb
36
41
  - lib/generators/garland_rails/install_generator.rb
37
42
  - lib/generators/garland_rails/templates/install_migration.rb
38
43
  - lib/generators/garland_rails/templates/uninstall_migration.rb
@@ -59,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
59
64
  version: '0'
60
65
  requirements: []
61
66
  rubyforge_project:
62
- rubygems_version: 2.6.6
67
+ rubygems_version: 2.5.2
63
68
  signing_key:
64
69
  specification_version: 4
65
70
  summary: HashDiff Rails storage