ohm 2.0.1 → 2.1.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: 6d404b17a73aaa3f8e44ef1973cc2c2281bfdeb7
4
- data.tar.gz: 5e59ffee49a2bee96c3417cc0763f31552bf06ff
3
+ metadata.gz: 879b753fd8424a547c5cf83753b2f4d7dd817a14
4
+ data.tar.gz: fab1f4b6971328047ed17e37d589ebc47c32d082
5
5
  SHA512:
6
- metadata.gz: 849b95d5ebfc61b136be8351b6c0887e6c2961c78bb086204c39a1110524efd02fe94d48c5ed05c123c326567aa70ffbb2292e70a10d9f875307dd33e82f72e9
7
- data.tar.gz: db2213eff5791aa09f02e2d79c9059d9ed4d3619f6206257bf3a69c227a2481361f179fd620ec6b07d4c21f7cb89965d6e52e7b90ab08494ef8ed067e637aa31
6
+ metadata.gz: 3538cccef143743083a6a31c672e4e5bacec42f743196fbcf52f1c68ca4ca3bcc3169f9633a40cdfc1633d48428c60e53e999641e252b640767d85b6b8db3117
7
+ data.tar.gz: b51d4ad91623b2357492837a37d1f0f03928e4a2e526849afe4cd558987089fab2a930233065d1230e6dd82c70c6c0341435c0fbbf7f9a467953480e09ec99c4
data/README.md CHANGED
@@ -23,6 +23,7 @@ These are libraries in other languages that were inspired by Ohm.
23
23
 
24
24
  * [JOhm](https://github.com/xetorthio/johm) for Java, created by xetorthio
25
25
  * [Lohm](https://github.com/slact/lua-ohm) for Lua, created by slact
26
+ * [ohm.lua](https://github.com/amakawa/ohm.lua) for Lua, created by amakawa
26
27
  * [Nohm](https://github.com/maritz/nohm) for Node.js, created by maritz
27
28
  * [Redisco](https://github.com/iamteem/redisco) for Python, created by iamteem
28
29
  * [redis3m](https://github.com/luca3m/redis3m) for C++, created by luca3m
@@ -164,11 +165,17 @@ querying. Keep reading to find out what you can do with models.
164
165
  Attribute types
165
166
  ---------------
166
167
 
167
- Ohm::Model provides four attribute types: {Ohm::Model.attribute
168
- attribute}, {Ohm::Model.set set}, {Ohm::Model.list list}
169
- and {Ohm::Model.counter counter}; and two meta types:
170
- {Ohm::Model.reference reference} and {Ohm::Model.collection
171
- collection}.
168
+ Ohm::Model provides 4 attribute types:
169
+
170
+ * {Ohm::Model.attribute attribute},
171
+ * {Ohm::Model.set set}
172
+ * {Ohm::Model.list list}
173
+ * {Ohm::Model.counter counter}
174
+
175
+ and 2 meta types:
176
+
177
+ * {Ohm::Model.reference reference}
178
+ * {Ohm::Model.collection collection}.
172
179
 
173
180
  ### attribute
174
181
 
@@ -439,8 +446,11 @@ User.find(username: "Albert")
439
446
  # Find all users from Argentina
440
447
  User.find(country: "Argentina")
441
448
 
442
- # Find all activated users from Argentina
443
- User.find(country: "Argentina", status: "activated")
449
+ # Find all active users from Argentina
450
+ User.find(country: "Argentina", status: "active")
451
+
452
+ # Find all active users from Argentina and Uruguay
453
+ User.find(status: "active").combine(country: ["Argentina", "Uruguay"])
444
454
 
445
455
  # Find all users from Argentina, except those with a suspended account.
446
456
  User.find(country: "Argentina").except(status: "suspended")
data/examples/chaining.rb CHANGED
@@ -16,12 +16,12 @@ require "ohm"
16
16
  # A `User` has a `collection` of *orders*. Note that a collection
17
17
  # is actually just a convenience, which implemented simply will look like:
18
18
  #
19
- # def orders
20
- # Order.find(:user_id => self.id)
21
- # end
19
+ # def orders
20
+ # Order.find(user_id: self.id)
21
+ # end
22
22
  #
23
23
  class User < Ohm::Model
24
- collection :orders, Order
24
+ collection :orders, :Order
25
25
  end
26
26
 
27
27
  # The product for our purposes will only contain a name.
@@ -29,7 +29,7 @@ class Product < Ohm::Model
29
29
  attribute :name
30
30
  end
31
31
 
32
- # We define an `Order` with just a single `attribute` called state, and
32
+ # We define an `Order` with just a single `attribute` called `state`, and
33
33
  # also add an `index` so we can search an order given its state.
34
34
  #
35
35
  # The `reference` to the `User` is actually required for the `collection`
@@ -58,15 +58,15 @@ prepare { Ohm.flush }
58
58
  setup do
59
59
  @user = User.create
60
60
 
61
- @ipod = Product.create(:name => "iPod")
62
- @ipad = Product.create(:name => "iPad")
61
+ @ipod = Product.create(name: "iPod")
62
+ @ipad = Product.create(name: "iPad")
63
63
 
64
- @pending = Order.create(:user => @user, :state => "pending",
65
- :product => @ipod)
66
- @authorized = Order.create(:user => @user, :state => "authorized",
67
- :product => @ipad)
68
- @captured = Order.create(:user => @user, :state => "captured",
69
- :product => @ipad)
64
+ @pending = Order.create(user: @user, state: "pending",
65
+ product: @ipod)
66
+ @authorized = Order.create(user: @user, state: "authorized",
67
+ product: @ipad)
68
+ @captured = Order.create(user: @user, state: "captured",
69
+ product: @ipad)
70
70
  end
71
71
 
72
72
  # Now let's try and grab all pending orders, and also pending
@@ -74,31 +74,22 @@ end
74
74
  test "finding pending orders" do
75
75
  assert @user.orders.find(state: "pending").include?(@pending)
76
76
 
77
- assert @user.orders.find(:state => "pending",
78
- :product_id => @ipod.id).include?(@pending)
77
+ assert @user.orders.find(state: "pending",
78
+ product_id: @ipod.id).include?(@pending)
79
79
 
80
- assert @user.orders.find(:state => "pending",
81
- :product_id => @ipad.id).empty?
80
+ assert @user.orders.find(state: "pending",
81
+ product_id: @ipad.id).empty?
82
82
  end
83
83
 
84
- # Now we try and find captured and authorized orders. The tricky part
85
- # is trying to find an order that is either *captured* or *authorized*,
86
- # since `Ohm` as of this writing doesn't support unions in its
87
- # finder syntax.
84
+ # Now we try and find captured and/or authorized orders.
88
85
  test "finding authorized and/or captured orders" do
89
- assert @user.orders.find(:state => "authorized").include?(@authorized)
90
- assert @user.orders.find(:state => "captured").include?(@captured)
86
+ assert @user.orders.find(state: "authorized").include?(@authorized)
87
+ assert @user.orders.find(state: "captured").include?(@captured)
91
88
 
92
- assert @user.orders.find(:state => ["authorized", "captured"]).empty?
89
+ results = @user.orders.find(state: "authorized").union(state: "captured")
93
90
 
94
- auth_or_capt = @user.orders.key.volatile[:auth_or_capt]
95
- auth_or_capt.sunionstore(
96
- @user.orders.find(:state => "authorized").key,
97
- @user.orders.find(:state => "captured").key
98
- )
99
-
100
- assert auth_or_capt.smembers.include?(@authorized.id)
101
- assert auth_or_capt.smembers.include?(@captured.id)
91
+ assert results.include?(@authorized)
92
+ assert results.include?(@captured)
102
93
  end
103
94
 
104
95
  #### Creating shortcuts
@@ -106,11 +97,11 @@ end
106
97
  # You can of course define methods to make that code more readable.
107
98
  class User < Ohm::Model
108
99
  def authorized_orders
109
- orders.find(:state => "authorized")
100
+ orders.find(state: "authorized")
110
101
  end
111
102
 
112
103
  def captured_orders
113
- orders.find(:state => "captured")
104
+ orders.find(state: "captured")
114
105
  end
115
106
  end
116
107
 
@@ -121,62 +112,40 @@ test "finding authorized and/or captured orders" do
121
112
  end
122
113
 
123
114
  # In most cases this is fine, but if you want to have a little fun,
124
- # then we can play around with some chainability.
115
+ # then we can play around with some chainability using scopes.
125
116
 
126
- #### Chaining Kung-Fu
117
+ # Let's require `ohm-contrib`, which we will be using for scopes.
118
+ require "ohm/contrib"
127
119
 
128
- # The `Ohm::Model::Set` takes a *Redis* key and a *class monad*
129
- # for its arguments.
130
- #
131
- # We can simply subclass it and define the monad to always be an
132
- # `Order` so we don't have to manually set it everytime.
133
- class UserOrders < Ohm::Model::Set
134
- def initialize(key)
135
- super key, Ohm::Model::Wrapper.wrap(Order)
136
- end
120
+ # Include `Ohm::Scope` module and desired scopes.
121
+ class Order
122
+ include Ohm::Scope
137
123
 
138
- # Here is the crux of the chaining pattern. Instead of
139
- # just doing a straight up `find(:state => "pending")`, we return
140
- # `UserOrders` again.
141
- def pending
142
- self.class.new(model.index_key_for(:state, "pending"))
143
- end
124
+ scope do
125
+ def pending
126
+ find(state: "pending")
127
+ end
144
128
 
145
- def authorized
146
- self.class.new(model.index_key_for(:state, "authorized"))
147
- end
129
+ def authorized
130
+ find(state: "authorized")
131
+ end
148
132
 
149
- def captured
150
- self.class.new(model.index_key_for(:state, "captured"))
151
- end
133
+ def captured
134
+ find(state: "captured")
135
+ end
152
136
 
153
- # Now we wrap the implementation of doing an `SUNIONSTORE` and also
154
- # make it return a `UserOrders` object.
155
- #
156
- # NOTE: `volatile` just returns the key prepended with a `~:`, so in
157
- # this case it would be `~:Order:accepted`.
158
- def accepted
159
- model.key.volatile[:accepted].sunionstore(
160
- authorized.key, captured.key
161
- )
162
-
163
- self.class.new(model.key.volatile[:accepted])
164
- end
165
- end
166
-
167
- # Now let's re-open the `User` class and add a customized `orders` method.
168
- class User < Ohm::Model
169
- def orders
170
- UserOrders.new(Order.index_key_for(:user_id, id))
137
+ def accepted
138
+ find(state: "authorized").union(state: "captured")
139
+ end
171
140
  end
172
141
  end
173
142
 
174
143
  # Ok! Let's put all of that chaining code to good use.
175
144
  test "finding pending orders using a chainable style" do
176
145
  assert @user.orders.pending.include?(@pending)
177
- assert @user.orders.pending.find(:product_id => @ipod.id).include?(@pending)
146
+ assert @user.orders.pending.find(product_id: @ipod.id).include?(@pending)
178
147
 
179
- assert @user.orders.pending.find(:product_id => @ipad.id).empty?
148
+ assert @user.orders.pending.find(product_id: @ipad.id).empty?
180
149
  end
181
150
 
182
151
  test "finding authorized and/or captured orders using a chainable style" do
@@ -188,16 +157,6 @@ test "finding authorized and/or captured orders using a chainable style" do
188
157
 
189
158
  accepted = @user.orders.accepted
190
159
 
191
- assert accepted.find(:product_id => @ipad.id).include?(@authorized)
192
- assert accepted.find(:product_id => @ipad.id).include?(@captured)
160
+ assert accepted.find(product_id: @ipad.id).include?(@authorized)
161
+ assert accepted.find(product_id: @ipad.id).include?(@captured)
193
162
  end
194
-
195
- #### Conclusion
196
-
197
- # This design pattern is something that really depends upon the situation. In
198
- # the example above, you can add more complicated querying on the `UserOrders`
199
- # class.
200
- #
201
- # The most important takeaway here is the ease of which we can weild the
202
- # different components of Ohm, and mold it accordingly to our preferences,
203
- # without having to monkey-patch anything.
data/examples/tagging.rb CHANGED
@@ -156,11 +156,13 @@ class Post
156
156
 
157
157
  # For our scenario, we only need a `before_update` and `after_save`.
158
158
  # The idea for our `before_update` is to decrement the `total` of
159
- # all existing tags. We use `read_remote(:tags)` to make sure that
160
- # we actually get the original `tags` for a particular record.
159
+ # all existing tags. We use `get(:tags)` the original tags for the
160
+ # record and use assigned one on save.
161
161
  protected
162
162
  def before_update
163
- tag(read_remote(:tags)).map(&Tag).each { |t| t.decr :total }
163
+ assigned_tags = tags
164
+ tag(get(:tags)).map(&Tag).each { |t| t.decr :total }
165
+ self.tags = assigned_tags
164
166
  end
165
167
 
166
168
  # And of course, we increment all new tags for a particular record
@@ -186,7 +188,8 @@ class Tag < Ohm::Model
186
188
  # though is that we need to encode the tag name, so special characters
187
189
  # and spaces won't produce an invalid key.
188
190
  def self.[](id)
189
- super(encode(id)) || create(:id => encode(id))
191
+ encoded_id = id.encode
192
+ super(encoded_id) || create(:id => encoded_id)
190
193
  end
191
194
  end
192
195
 
data/lib/ohm.rb CHANGED
@@ -528,6 +528,20 @@ module Ohm
528
528
  MultiSet.new(namespace, model, key).except(dict)
529
529
  end
530
530
 
531
+ # Perform an intersection between the existent set and
532
+ # the new set created by the union of the passed filters.
533
+ #
534
+ # Example:
535
+ #
536
+ # set = User.find(:status => "active")
537
+ # set.combine(:name => ["John", "Jane"])
538
+ #
539
+ # # The result will include all users with active status
540
+ # # and with names "John" or "Jane".
541
+ def combine(dict)
542
+ MultiSet.new(namespace, model, key).combine(dict)
543
+ end
544
+
531
545
  # Do a union to the existing set using any number of filters.
532
546
  #
533
547
  # Example:
@@ -666,6 +680,22 @@ module Ohm
666
680
  )
667
681
  end
668
682
 
683
+ # Perform an intersection between the existent set and
684
+ # the new set created by the union of the passed filters.
685
+ #
686
+ # Example:
687
+ #
688
+ # set = User.find(:status => "active")
689
+ # set.combine(:name => ["John", "Jane"])
690
+ #
691
+ # # The result will include all users with active status
692
+ # # and with names "John" or "Jane".
693
+ def combine(dict)
694
+ MultiSet.new(
695
+ namespace, model, Command[:sinterstore, command, unioned(dict)]
696
+ )
697
+ end
698
+
669
699
  # Do a union to the existing set using any number of filters.
670
700
  #
671
701
  # Example:
data/ohm.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "ohm"
3
- s.version = "2.0.1"
3
+ s.version = "2.1.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"]
data/test/filtering.rb CHANGED
@@ -111,6 +111,14 @@ test "#union" do |john, jane|
111
111
  assert res.any? { |e| e.status == "inactive" }
112
112
  end
113
113
 
114
+ test "#combine" do |john, jane|
115
+ res = User.find(:status => "active").combine(fname: ["John", "Jane"])
116
+
117
+ assert_equal 2, res.size
118
+ assert res.include?(john)
119
+ assert res.include?(jane)
120
+ end
121
+
114
122
  # book author thing via @myobie
115
123
  scope do
116
124
  class Book < Ohm::Model
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.0.1
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michel Martens
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2014-06-26 00:00:00.000000000 Z
13
+ date: 2015-01-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: redic
@@ -138,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
138
  version: '0'
139
139
  requirements: []
140
140
  rubyforge_project: ohm
141
- rubygems_version: 2.0.3
141
+ rubygems_version: 2.0.14
142
142
  signing_key:
143
143
  specification_version: 4
144
144
  summary: Object-hash mapping library for Redis.