ohm 2.3.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ed9503debac38501951e7e6847229e79e1289626
4
- data.tar.gz: a754d5fef582a8c80dc1ad3b51b006820d03006a
3
+ metadata.gz: 4ecea4a8e9a9d11936a4dd250c91171ae3a47530
4
+ data.tar.gz: ad07199ffc7506ab69d7193d439cbd5373e41cac
5
5
  SHA512:
6
- metadata.gz: cad32b03019a2c5f2e058446cb44947e0f3261e8d9c6dd30ff780eb21c7382e4384da950e057d0762307682f25fde152dda8b8f1f59f991642315c8cbf254ef0
7
- data.tar.gz: 3e2ecb21022c7fb91441077a6d2566e344c61cba242a93b9675a9a41c0271448321c0ab2e2b9daa2b3110d97856d7d6d30a1675be2ae77362d927b8a313e852f
6
+ metadata.gz: b36d7473878642e18e827de61079b5fd36f083abba8aea39265927f0ad2370b1702bab376b37297d3b0bbb8d487ada008c6f98818cd82de84d9d4698405ec21e
7
+ data.tar.gz: 8ad17db1d2c0e6d9c4a2c661a75dac9b571cca89f7b542751826852512406a6aebeca58c38838ceb69904920fc63e08be55ab696d34618f23536237d7da7be0c
@@ -1,3 +1,38 @@
1
+ ## 3.0.0
2
+
3
+ - Use JSON instead of msgpack for internal encoding.
4
+
5
+ When Ohm started using Lua internally for saving, updating and
6
+ deleting objects, it used msgpack for serializing. Redis supports
7
+ both msgpack and JSON, and we picked msgpack because it produces
8
+ a more compact representation. At some point, the Ruby msgpack
9
+ library and the internal msgpack support in Redis diverged, and
10
+ we were forced to lock the dependency to a specific gem version.
11
+ Recently, some people complained about encoding issues originating
12
+ from msgpack inside Redis, and once they tried a modified Ohm
13
+ that uses JSON instead of msgpack, all their issues disappeared.
14
+ That's why we think it's time for removing msgpack altogether and
15
+ use JSON instead.
16
+
17
+ - Move the raise of MissingID to Ohm::Model#key.
18
+
19
+ In previous versions, trying to access an instance's `id` would
20
+ raise a `MissingID` error. The reason why raising that error is
21
+ convenient is because it allows Ohm to fail as early as possible
22
+ when you try to use an object that hasn't been saved yet. The
23
+ error can arise from comparisons, from direct calls to `id`, and
24
+ also from any call to methods that need `object.key` to return a
25
+ proper value, as `key` in turn calls the `id` method. But it turns
26
+ out that many form builders rely on the fact that sending the
27
+ `id` message to most ORMs results in either a valid ID or `nil`,
28
+ and here Ohm was the exception. By moving the check from `id` to
29
+ `key`, we can keep most of the previous behavior and we can return
30
+ `nil` when sending the `id` message to a new instance, thus making
31
+ Ohm compatible with most form builders.
32
+
33
+ - Add `Ohm::Model#increment` and `Ohm::Model#decrement`. These methods
34
+ are aliases of `incr` and `decr` respectively.
35
+
1
36
  ## 2.3.0
2
37
 
3
38
  - Retry save and delete if scripts were flushed in the server.
data/README.md CHANGED
@@ -28,6 +28,7 @@ These are libraries in other languages that were inspired by Ohm.
28
28
  * [Redisco](https://github.com/iamteem/redisco) for Python, created by iamteem
29
29
  * [redis3m](https://github.com/luca3m/redis3m) for C++, created by luca3m
30
30
  * [Ohmoc](https://github.com/seppo0010/ohmoc) for Objective-C, created by seppo0010
31
+ * [Sohm](https://github.com/xxuejie/sohm.lua) for Lua, compatible with Twemproxy
31
32
 
32
33
  Articles and Presentations
33
34
  --------------------------
@@ -162,7 +163,7 @@ Event[2]
162
163
 
163
164
  # Finding all the events
164
165
  Event.all.to_a
165
- # => [<Event:1 name='Ohm Worldwide Conference 2031'>]
166
+ # => [<Event:1 name='Ohm Worldwide Conference 2032'>]
166
167
  ```
167
168
 
168
169
  This example shows some basic features, like attribute declarations and
@@ -171,9 +172,9 @@ querying. Keep reading to find out what you can do with models.
171
172
  Attribute types
172
173
  ---------------
173
174
 
174
- Ohm::Model provides 4 attribute types:
175
+ Ohm::Model provides 4 attribute types:
175
176
 
176
- * {Ohm::Model.attribute attribute},
177
+ * {Ohm::Model.attribute attribute},
177
178
  * {Ohm::Model.set set}
178
179
  * {Ohm::Model.list list}
179
180
  * {Ohm::Model.counter counter}
@@ -207,8 +208,8 @@ and for keeping elements in order.
207
208
  A `counter` is like a regular attribute, but the direct manipulation
208
209
  of the value is not allowed. You can retrieve, increase or decrease
209
210
  the value, but you can not assign it. In the example above, we used a
210
- counter attribute for tracking votes. As the incr and decr operations
211
- are atomic, you can rest assured a vote won't be counted twice.
211
+ counter attribute for tracking votes. As the `increment` and `decrement`
212
+ operations are atomic, you can rest assured a vote won't be counted twice.
212
213
 
213
214
  ### reference
214
215
 
@@ -10,11 +10,6 @@ class Event < Ohm::Model
10
10
 
11
11
  index :name
12
12
  index :location
13
-
14
- def validate
15
- assert_present :name
16
- assert_present :location
17
- end
18
13
  end
19
14
 
20
15
  class Sequence
@@ -161,14 +161,14 @@ class Post
161
161
  protected
162
162
  def before_update
163
163
  assigned_tags = tags
164
- tag(get(:tags)).map(&Tag).each { |t| t.decr :total }
164
+ tag(get(:tags)).map(&Tag).each { |t| t.decrement :total }
165
165
  self.tags = assigned_tags
166
166
  end
167
167
 
168
168
  # And of course, we increment all new tags for a particular record
169
169
  # after successfully saving it.
170
170
  def after_save
171
- tag.map(&Tag).each { |t| t.incr :total }
171
+ tag.map(&Tag).each { |t| t.increment :total }
172
172
  end
173
173
  end
174
174
 
data/lib/ohm.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require "msgpack"
3
+ require "json"
4
4
  require "nido"
5
5
  require "redic"
6
6
  require "stal"
@@ -477,16 +477,28 @@ module Ohm
477
477
  sort(options.merge(:by => to_key(att)))
478
478
  end
479
479
 
480
- # Syntactic sugar for `sort_by` or `sort` when you only need the
481
- # first element.
480
+ # Returns the first record of the set. Internally uses `sort` or
481
+ # `sort_by` if a `:by` option is given. Accepts all options supported
482
+ # by `sort`.
482
483
  #
483
- # Example:
484
+ # class User < Ohm::Model
485
+ # attribute :name
486
+ # end
487
+ #
488
+ # User.create(name: "alice")
489
+ # User.create(name: "bob")
490
+ # User.create(name: "eve")
491
+ #
492
+ # User.all.first.name # => "alice"
493
+ # User.all.first(by: :name).name # => "alice"
494
+ #
495
+ # User.all.first(order: "ASC") # => "alice"
496
+ # User.all.first(order: "DESC") # => "eve"
484
497
  #
485
- # User.all.first ==
486
- # User.all.sort(:limit => [0, 1]).first
498
+ # You can use the `:order` option to bring the last record:
487
499
  #
488
- # User.all.first(:by => :name, "ALPHA") ==
489
- # User.all.sort_by(:name, :order => "ALPHA", :limit => [0, 1]).first
500
+ # User.all.first(order: "DESC").name # => "eve"
501
+ # User.all.first(by: :name, order: "ALPHA DESC") # => "eve"
490
502
  #
491
503
  def first(options = {})
492
504
  opts = options.dup
@@ -535,9 +547,10 @@ module Ohm
535
547
  #
536
548
  # set = User.find(:status => "active")
537
549
  # set.combine(:name => ["John", "Jane"])
538
- #
550
+ #
539
551
  # # The result will include all users with active status
540
552
  # # and with names "John" or "Jane".
553
+ #
541
554
  def combine(dict)
542
555
  Ohm::Set.new(
543
556
  model, namespace, [:SINTER, key, [:SUNION, *model.filters(dict)]]
@@ -652,7 +665,7 @@ module Ohm
652
665
  # end
653
666
  #
654
667
  # u = User.create(:name => "John", :email => "foo@bar.com")
655
- # u.incr :points
668
+ # u.increment :points
656
669
  # u.posts.add(Post.create)
657
670
  #
658
671
  # When you execute `User.create(...)`, you run the following Redis
@@ -1041,9 +1054,9 @@ module Ohm
1041
1054
 
1042
1055
  # Declare a counter. All the counters are internally stored in
1043
1056
  # a different Redis hash, independent from the one that stores
1044
- # the model attributes. Counters are updated with the `incr` and
1045
- # `decr` methods, which interact directly with Redis. Their value
1046
- # can't be assigned as with regular attributes.
1057
+ # the model attributes. Counters are updated with the `increment`
1058
+ # and `decrement` methods, which interact directly with Redis. Their
1059
+ # value can't be assigned as with regular attributes.
1047
1060
  #
1048
1061
  # Example:
1049
1062
  #
@@ -1052,7 +1065,7 @@ module Ohm
1052
1065
  # end
1053
1066
  #
1054
1067
  # u = User.create
1055
- # u.incr :points
1068
+ # u.increment :points
1056
1069
  #
1057
1070
  # u.points
1058
1071
  # # => 1
@@ -1088,6 +1101,7 @@ module Ohm
1088
1101
  # Returns the namespace for the keys generated using this model.
1089
1102
  # Check `Ohm::Model.key` documentation for more details.
1090
1103
  def key
1104
+ raise MissingID if not defined?(@id)
1091
1105
  model.key[id]
1092
1106
  end
1093
1107
 
@@ -1118,7 +1132,6 @@ module Ohm
1118
1132
  # # => User:1
1119
1133
  #
1120
1134
  def id
1121
- raise MissingID if not defined?(@id)
1122
1135
  @id
1123
1136
  end
1124
1137
 
@@ -1191,20 +1204,50 @@ module Ohm
1191
1204
  # u.save
1192
1205
  # u.new?
1193
1206
  # # => false
1207
+ #
1194
1208
  def new?
1195
1209
  !defined?(@id)
1196
1210
  end
1197
1211
 
1198
- # Increment a counter atomically. Internally uses HINCRBY.
1199
- def incr(att, count = 1)
1212
+ # Increments a counter atomically. Internally uses `HINCRBY`.
1213
+ #
1214
+ # class Ad
1215
+ # counter :hits
1216
+ # end
1217
+ #
1218
+ # ad = Ad.create
1219
+ #
1220
+ # ad.increment(:hits)
1221
+ # ad.hits # => 1
1222
+ #
1223
+ # ad.increment(:hits, 2)
1224
+ # ad.hits # => 3
1225
+ #
1226
+ def increment(att, count = 1)
1200
1227
  redis.call("HINCRBY", key[:counters], att, count)
1201
1228
  end
1202
1229
 
1203
- # Decrement a counter atomically. Internally uses HINCRBY.
1204
- def decr(att, count = 1)
1205
- incr(att, -count)
1230
+ # Decrements a counter atomically. Internally uses `HINCRBY`.
1231
+ #
1232
+ # class Post
1233
+ # counter :score
1234
+ # end
1235
+ #
1236
+ # post = Post.create
1237
+ #
1238
+ # post.decrement(:score)
1239
+ # post.score # => -1
1240
+ #
1241
+ # post.decrement(:hits, 2)
1242
+ # post.score # => -3
1243
+ #
1244
+ def decrement(att, count = 1)
1245
+ increment(att, -count)
1206
1246
  end
1207
1247
 
1248
+ alias_method(:incr, :increment)
1249
+ alias_method(:decr, :decrement)
1250
+
1208
1251
  # Return a value that allows the use of models as hash keys.
1209
1252
  #
1210
1253
  # Example:
@@ -1305,10 +1348,10 @@ module Ohm
1305
1348
  end
1306
1349
 
1307
1350
  @id = script(LUA_SAVE, 0,
1308
- features.to_msgpack,
1309
- _sanitized_attributes.to_msgpack,
1310
- indices.to_msgpack,
1311
- uniques.to_msgpack
1351
+ features.to_json,
1352
+ _sanitized_attributes.to_json,
1353
+ indices.to_json,
1354
+ uniques.to_json
1312
1355
  )
1313
1356
 
1314
1357
  return self
@@ -1330,9 +1373,9 @@ module Ohm
1330
1373
  { "name" => model.name,
1331
1374
  "id" => id,
1332
1375
  "key" => key
1333
- }.to_msgpack,
1334
- uniques.to_msgpack,
1335
- model.tracked.to_msgpack
1376
+ }.to_json,
1377
+ uniques.to_json,
1378
+ model.tracked.to_json
1336
1379
  )
1337
1380
 
1338
1381
  return self
@@ -1,5 +1,3 @@
1
- require "json"
2
-
3
1
  module Ohm
4
2
  class Model
5
3
  # Export a JSON representation of the model by encoding `to_hash`.
@@ -1,5 +1,5 @@
1
1
  -- This script receives three parameters, all encoded with
2
- -- MessagePack. The decoded values are used for deleting a model
2
+ -- JSON. The decoded values are used for deleting a model
3
3
  -- instance in Redis and removing any reference to it in sets
4
4
  -- (indices) and hashes (unique indices).
5
5
  --
@@ -19,9 +19,9 @@
19
19
  -- Keys that share the lifecycle of this model instance, that
20
20
  -- should be removed as this object is deleted.
21
21
  --
22
- local model = cmsgpack.unpack(ARGV[1])
23
- local uniques = cmsgpack.unpack(ARGV[2])
24
- local tracked = cmsgpack.unpack(ARGV[3])
22
+ local model = cjson.decode(ARGV[1])
23
+ local uniques = cjson.decode(ARGV[2])
24
+ local tracked = cjson.decode(ARGV[3])
25
25
 
26
26
  local function remove_indices(model)
27
27
  local memo = model.key .. ":_indices"
@@ -1,5 +1,5 @@
1
1
  -- This script receives four parameters, all encoded with
2
- -- MessagePack. The decoded values are used for saving a model
2
+ -- JSON. The decoded values are used for saving a model
3
3
  -- instance in Redis, creating or updating a hash as needed and
4
4
  -- updating zero or more sets (indices) and zero or more hashes
5
5
  -- (unique indices).
@@ -30,10 +30,10 @@
30
30
  -- value), an error is returned with the UniqueIndexViolation
31
31
  -- message and the field that triggered the error.
32
32
  --
33
- local model = cmsgpack.unpack(ARGV[1])
34
- local attrs = cmsgpack.unpack(ARGV[2])
35
- local indices = cmsgpack.unpack(ARGV[3])
36
- local uniques = cmsgpack.unpack(ARGV[4])
33
+ local model = cjson.decode(ARGV[1])
34
+ local attrs = cjson.decode(ARGV[2])
35
+ local indices = cjson.decode(ARGV[3])
36
+ local uniques = cjson.decode(ARGV[4])
37
37
 
38
38
  local function save(model, attrs)
39
39
  if model.id == nil then
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "ohm"
3
- s.version = "2.3.0"
3
+ s.version = "3.0.0"
4
4
  s.summary = %{Object-hash mapping library for Redis.}
5
5
  s.description = %Q{Ohm is a library that allows to store an object in Redis, a persistent key-value database. It has very good performance.}
6
6
  s.authors = ["Michel Martens", "Damian Janowski", "Cyril David"]
@@ -15,7 +15,6 @@ Gem::Specification.new do |s|
15
15
  s.add_dependency "redic", "~> 1.5.0"
16
16
  s.add_dependency "nido"
17
17
  s.add_dependency "stal"
18
- s.add_dependency "msgpack", "~> 0.5.0"
19
18
 
20
19
  s.add_development_dependency "cutest"
21
20
  end
@@ -19,6 +19,6 @@ test "assign an ID and save the object" do
19
19
  end
20
20
 
21
21
  test "save the attributes in UTF8" do
22
- event = Event.create(name: "32° Kisei-sen")
23
- assert_equal "32° Kisei-sen", Event[event.id].name
22
+ event = Event.create(name: "32° Kisei-sen")
23
+ assert_equal "32° Kisei-sen", Event[event.id].name
24
24
  end
@@ -9,12 +9,12 @@ test "counters aren't overwritten by competing saves" do
9
9
  Ad.counter :hits
10
10
 
11
11
  instance1 = Ad.create
12
- instance1.incr :hits
12
+ instance1.increment :hits
13
13
 
14
14
  instance2 = Ad[instance1.id]
15
15
 
16
- instance1.incr :hits
17
- instance1.incr :hits
16
+ instance1.increment :hits
17
+ instance1.increment :hits
18
18
 
19
19
  instance2.save
20
20
 
@@ -31,7 +31,7 @@ test "you can increment counters even when attributes is empty" do
31
31
  ex = nil
32
32
 
33
33
  begin
34
- ad.incr :hits
34
+ ad.increment :hits
35
35
  rescue ArgumentError => e
36
36
  ex = e
37
37
  end
@@ -44,7 +44,7 @@ test "an attribute gets saved properly" do
44
44
  Ad.counter :hits
45
45
 
46
46
  ad = Ad.create(:name => "foo")
47
- ad.incr :hits, 10
47
+ ad.increment :hits, 10
48
48
  assert_equal 10, ad.hits
49
49
 
50
50
  # Now let's just load and save it.
@@ -59,7 +59,7 @@ test "an attribute gets saved properly" do
59
59
  # If we load and save again while we incr behind the scenes,
60
60
  # the latest counter values should be respected.
61
61
  ad = Ad[ad.id]
62
- ad.incr :hits, 5
62
+ ad.increment :hits, 5
63
63
  ad.save
64
64
 
65
65
  ad = Ad[ad.id]
@@ -73,7 +73,7 @@ end
73
73
 
74
74
  test "counters are cleaned up during deletion" do
75
75
  e = Event.create(:name => "Foo")
76
- e.incr :votes, 10
76
+ e.increment :votes, 10
77
77
 
78
78
  assert_equal 10, e.votes
79
79
 
@@ -286,7 +286,7 @@ end
286
286
  test "save counters" do
287
287
  event = Event.create(:name => "Foo")
288
288
 
289
- event.incr(:votes)
289
+ event.increment(:votes)
290
290
  event.save
291
291
 
292
292
  assert_equal 1, Event[event.id].votes
@@ -561,7 +561,7 @@ setup do
561
561
  @event = Event.create(:name => "Ruby Tuesday")
562
562
  {'D' => 4, 'C' => 2, 'B' => 5, 'A' => 3}.each_pair do |name, logins|
563
563
  person = Person.create(:name => name)
564
- person.incr :logins, logins
564
+ person.increment :logins, logins
565
565
  @event.attendees.add(person)
566
566
  end
567
567
  end
@@ -630,18 +630,18 @@ test "be zero if not initialized" do
630
630
  end
631
631
 
632
632
  test "be able to increment a counter" do
633
- @event.incr(:votes)
633
+ @event.increment(:votes)
634
634
  assert 1 == @event.votes
635
635
 
636
- @event.incr(:votes, 2)
636
+ @event.increment(:votes, 2)
637
637
  assert 3 == @event.votes
638
638
  end
639
639
 
640
640
  test "be able to decrement a counter" do
641
- @event.decr(:votes)
641
+ @event.decrement(:votes)
642
642
  assert @event.votes == -1
643
643
 
644
- @event.decr(:votes, 2)
644
+ @event.decrement(:votes, 2)
645
645
  assert @event.votes == -3
646
646
  end
647
647
 
@@ -739,7 +739,7 @@ end
739
739
  # Persistence
740
740
  test "persist attributes to a hash" do
741
741
  event = Event.create(:name => "Redis Meetup")
742
- event.incr(:votes)
742
+ event.increment(:votes)
743
743
 
744
744
  assert "hash" == Ohm.redis.call("TYPE", "Event:1")
745
745
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ohm
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michel Martens
@@ -10,76 +10,62 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-08-06 00:00:00.000000000 Z
13
+ date: 2016-04-13 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: redic
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
- - - ~>
19
+ - - "~>"
20
20
  - !ruby/object:Gem::Version
21
21
  version: 1.5.0
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
- - - ~>
26
+ - - "~>"
27
27
  - !ruby/object:Gem::Version
28
28
  version: 1.5.0
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: nido
31
31
  requirement: !ruby/object:Gem::Requirement
32
32
  requirements:
33
- - - '>='
33
+ - - ">="
34
34
  - !ruby/object:Gem::Version
35
35
  version: '0'
36
36
  type: :runtime
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
- - - '>='
40
+ - - ">="
41
41
  - !ruby/object:Gem::Version
42
42
  version: '0'
43
43
  - !ruby/object:Gem::Dependency
44
44
  name: stal
45
45
  requirement: !ruby/object:Gem::Requirement
46
46
  requirements:
47
- - - '>='
47
+ - - ">="
48
48
  - !ruby/object:Gem::Version
49
49
  version: '0'
50
50
  type: :runtime
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
- - - '>='
54
+ - - ">="
55
55
  - !ruby/object:Gem::Version
56
56
  version: '0'
57
- - !ruby/object:Gem::Dependency
58
- name: msgpack
59
- requirement: !ruby/object:Gem::Requirement
60
- requirements:
61
- - - ~>
62
- - !ruby/object:Gem::Version
63
- version: 0.5.0
64
- type: :runtime
65
- prerelease: false
66
- version_requirements: !ruby/object:Gem::Requirement
67
- requirements:
68
- - - ~>
69
- - !ruby/object:Gem::Version
70
- version: 0.5.0
71
57
  - !ruby/object:Gem::Dependency
72
58
  name: cutest
73
59
  requirement: !ruby/object:Gem::Requirement
74
60
  requirements:
75
- - - '>='
61
+ - - ">="
76
62
  - !ruby/object:Gem::Version
77
63
  version: '0'
78
64
  type: :development
79
65
  prerelease: false
80
66
  version_requirements: !ruby/object:Gem::Requirement
81
67
  requirements:
82
- - - '>='
68
+ - - ">="
83
69
  - !ruby/object:Gem::Version
84
70
  version: '0'
85
71
  description: Ohm is a library that allows to store an object in Redis, a persistent
@@ -92,8 +78,8 @@ executables: []
92
78
  extensions: []
93
79
  extra_rdoc_files: []
94
80
  files:
95
- - .gems
96
- - .gitignore
81
+ - ".gems"
82
+ - ".gitignore"
97
83
  - CHANGELOG.md
98
84
  - CONTRIBUTING
99
85
  - LICENSE
@@ -141,17 +127,17 @@ require_paths:
141
127
  - lib
142
128
  required_ruby_version: !ruby/object:Gem::Requirement
143
129
  requirements:
144
- - - '>='
130
+ - - ">="
145
131
  - !ruby/object:Gem::Version
146
132
  version: '0'
147
133
  required_rubygems_version: !ruby/object:Gem::Requirement
148
134
  requirements:
149
- - - '>='
135
+ - - ">="
150
136
  - !ruby/object:Gem::Version
151
137
  version: '0'
152
138
  requirements: []
153
139
  rubyforge_project: ohm
154
- rubygems_version: 2.0.14
140
+ rubygems_version: 2.4.5.1
155
141
  signing_key:
156
142
  specification_version: 4
157
143
  summary: Object-hash mapping library for Redis.