ohm 0.1.0.rc2 → 0.1.0.rc4
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.
- data/README.markdown +12 -5
- data/Rakefile +10 -2
- data/lib/ohm.rb +76 -9
- data/lib/ohm/version.rb +1 -1
- data/test/1.8.6_test.rb +1 -1
- data/test/connection_test.rb +1 -1
- data/test/errors_test.rb +1 -1
- data/test/hash_key_test.rb +36 -0
- data/test/indices_test.rb +2 -2
- data/test/model_module_test.rb +1 -1
- data/test/model_test.rb +123 -1
- data/test/mutex_test.rb +1 -1
- data/test/upgrade_script_test.rb +1 -1
- data/test/validations_test.rb +1 -1
- data/test/wrapper_test.rb +20 -0
- metadata +11 -4
data/README.markdown
CHANGED
@@ -228,7 +228,7 @@ An index is a set that's handled automatically by Ohm. For any index declared,
|
|
228
228
|
Ohm maintains different sets of objects IDs for quick lookups.
|
229
229
|
|
230
230
|
In the `Event` example, the index on the name attribute will
|
231
|
-
allow for searches like `Event.find(name
|
231
|
+
allow for searches like `Event.find(:name => "some value")`.
|
232
232
|
|
233
233
|
Note that the `assert_unique` validation and the methods `find` and `except` need a
|
234
234
|
corresponding index in order to work.
|
@@ -238,18 +238,18 @@ corresponding index in order to work.
|
|
238
238
|
You can find a collection of records with the `find` method:
|
239
239
|
|
240
240
|
# This returns a collection of users with the username "Albert"
|
241
|
-
User.find(username
|
241
|
+
User.find(:username => "Albert")
|
242
242
|
|
243
243
|
### Filtering results
|
244
244
|
|
245
245
|
# Find all users from Argentina
|
246
|
-
User.find(country
|
246
|
+
User.find(:country => "Argentina")
|
247
247
|
|
248
248
|
# Find all activated users from Argentina
|
249
|
-
User.find(country
|
249
|
+
User.find(:country => "Argentina", :status => "activated")
|
250
250
|
|
251
251
|
# Find all users from Argentina, except those with a suspended account.
|
252
|
-
User.find(country
|
252
|
+
User.find(:country => "Argentina").except(:status => "suspended")
|
253
253
|
|
254
254
|
Note that calling these methods results in new sets being created
|
255
255
|
on the fly. This is important so that you can perform further operations
|
@@ -365,6 +365,13 @@ values. The result of the block is used as the error message:
|
|
365
365
|
error_messages
|
366
366
|
# => ["The email foo@example.com is already registered."]
|
367
367
|
|
368
|
+
Ohm Extensions
|
369
|
+
==============
|
370
|
+
|
371
|
+
Ohm is rather small and can be extended in many ways.
|
372
|
+
|
373
|
+
A lot of amazing contributions are available at [Ohm Contrib](http://labs.sinefunc.com/ohm-contrib/doc/), make sure to check them if you need to extend Ohm's functionality.
|
374
|
+
|
368
375
|
Versions
|
369
376
|
========
|
370
377
|
|
data/Rakefile
CHANGED
@@ -24,6 +24,14 @@ task :stop do
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
|
28
|
-
|
27
|
+
task :test do
|
28
|
+
Dir["test/**/*_test.rb"].each do |file|
|
29
|
+
fork do
|
30
|
+
load file
|
31
|
+
end
|
32
|
+
|
33
|
+
Process.wait
|
34
|
+
|
35
|
+
exit $?.exitstatus unless $?.success?
|
36
|
+
end
|
29
37
|
end
|
data/lib/ohm.rb
CHANGED
@@ -518,7 +518,7 @@ module Ohm
|
|
518
518
|
end
|
519
519
|
|
520
520
|
def self.all
|
521
|
-
|
521
|
+
Ohm::Model::Index.new(key(:all), Wrapper.wrap(self))
|
522
522
|
end
|
523
523
|
|
524
524
|
def self.attributes
|
@@ -623,6 +623,48 @@ module Ohm
|
|
623
623
|
incr(att, -count)
|
624
624
|
end
|
625
625
|
|
626
|
+
# Export the id and errors of the object. The `to_hash` takes the opposite
|
627
|
+
# approach of providing all the attributes and instead favors a
|
628
|
+
# white listed approach.
|
629
|
+
#
|
630
|
+
# @example
|
631
|
+
#
|
632
|
+
# person = Person.create(:name => "John Doe")
|
633
|
+
# person.to_hash == { :id => '1' }
|
634
|
+
# # => true
|
635
|
+
#
|
636
|
+
# # if the person asserts presence of name, the errors will be included
|
637
|
+
# person = Person.create(:name => "John Doe")
|
638
|
+
# person.name = nil
|
639
|
+
# person.valid?
|
640
|
+
# # => false
|
641
|
+
#
|
642
|
+
# person.to_hash == { :id => '1', :errors => [[:name, :not_present]] }
|
643
|
+
# # => true
|
644
|
+
#
|
645
|
+
# # for cases where you want to provide white listed attributes just do:
|
646
|
+
#
|
647
|
+
# class Person < Ohm::Model
|
648
|
+
# def to_hash
|
649
|
+
# super.merge(:name => name)
|
650
|
+
# end
|
651
|
+
# end
|
652
|
+
#
|
653
|
+
# # now we have the name when doing a to_hash
|
654
|
+
# person = Person.create(:name => "John Doe")
|
655
|
+
# person.to_hash == { :id => '1', :name => "John Doe" }
|
656
|
+
# # => true
|
657
|
+
def to_hash
|
658
|
+
attrs = {}
|
659
|
+
attrs[:id] = id unless new?
|
660
|
+
attrs[:errors] = errors unless errors.empty?
|
661
|
+
attrs
|
662
|
+
end
|
663
|
+
|
664
|
+
def to_json(*args)
|
665
|
+
to_hash.to_json(*args)
|
666
|
+
end
|
667
|
+
|
626
668
|
def attributes
|
627
669
|
self.class.attributes
|
628
670
|
end
|
@@ -644,6 +686,11 @@ module Ohm
|
|
644
686
|
rescue MissingID
|
645
687
|
false
|
646
688
|
end
|
689
|
+
alias :eql? :==
|
690
|
+
|
691
|
+
def hash
|
692
|
+
new? ? super : key.hash
|
693
|
+
end
|
647
694
|
|
648
695
|
# Lock the object before executing the block, and release it once the block is done.
|
649
696
|
def mutex
|
@@ -694,21 +741,41 @@ module Ohm
|
|
694
741
|
end
|
695
742
|
|
696
743
|
def write
|
697
|
-
unless attributes.empty?
|
698
|
-
attributes.
|
744
|
+
unless (attributes + counters).empty?
|
745
|
+
atts = (attributes + counters).inject([]) { |ret, att|
|
699
746
|
value = send(att).to_s
|
700
747
|
|
701
|
-
if value.empty?
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
748
|
+
ret.push(att, value) if not value.empty?
|
749
|
+
ret
|
750
|
+
}
|
751
|
+
|
752
|
+
db.multi do
|
753
|
+
db.del(key)
|
754
|
+
db.hmset(key, *atts.flatten) if atts.any?
|
706
755
|
end
|
707
756
|
end
|
708
757
|
end
|
709
758
|
|
759
|
+
def write_remote(att, value)
|
760
|
+
write_local(att, value)
|
761
|
+
|
762
|
+
if value.to_s.empty?
|
763
|
+
db.hdel(key, att)
|
764
|
+
else
|
765
|
+
db.hset(key, att, value)
|
766
|
+
end
|
767
|
+
end
|
768
|
+
|
710
769
|
def self.const_missing(name)
|
711
|
-
Wrapper.new(name) { const_get(name) }
|
770
|
+
wrapper = Wrapper.new(name) { const_get(name) }
|
771
|
+
|
772
|
+
# Allow others to hook to const_missing.
|
773
|
+
begin
|
774
|
+
super(name)
|
775
|
+
rescue NameError
|
776
|
+
end
|
777
|
+
|
778
|
+
wrapper
|
712
779
|
end
|
713
780
|
|
714
781
|
private
|
data/lib/ohm/version.rb
CHANGED
data/test/1.8.6_test.rb
CHANGED
data/test/connection_test.rb
CHANGED
data/test/errors_test.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
4
|
+
|
5
|
+
class Tag < Ohm::Model
|
6
|
+
attribute :name
|
7
|
+
end
|
8
|
+
|
9
|
+
class HashKeyTest < Test::Unit::TestCase
|
10
|
+
setup do
|
11
|
+
Ohm.flush
|
12
|
+
end
|
13
|
+
|
14
|
+
test "using a new record as a hash key" do
|
15
|
+
tag = Tag.new
|
16
|
+
hash = { tag => "Ruby" }
|
17
|
+
|
18
|
+
assert_equal "Ruby", hash[tag]
|
19
|
+
assert_nil hash[Tag.new]
|
20
|
+
end
|
21
|
+
|
22
|
+
test "on a persisted model" do
|
23
|
+
tag = Tag.create(:name => "Ruby")
|
24
|
+
|
25
|
+
assert_equal "Ruby", { tag => "Ruby" }[tag]
|
26
|
+
end
|
27
|
+
|
28
|
+
test "on a reloaded model" do
|
29
|
+
tag = Tag.create(:name => "Ruby")
|
30
|
+
hash = { tag => "Ruby" }
|
31
|
+
|
32
|
+
tag = Tag[tag.id]
|
33
|
+
assert_equal "Ruby", hash[tag]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
data/test/indices_test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), "test_helper")
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
2
|
|
3
3
|
class IndicesTest < Test::Unit::TestCase
|
4
4
|
setup do
|
@@ -43,7 +43,7 @@ class IndicesTest < Test::Unit::TestCase
|
|
43
43
|
end
|
44
44
|
|
45
45
|
should "raise an error if the parameter supplied is not a hash" do
|
46
|
-
assert_raises ArgumentError
|
46
|
+
assert_raises ArgumentError, "You need to supply a hash with filters. If you want to find by ID, use IndicesTest::User[id] instead." do
|
47
47
|
User.find(1)
|
48
48
|
end
|
49
49
|
end
|
data/test/model_module_test.rb
CHANGED
data/test/model_test.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
-
require File.join(File.dirname(__FILE__), "test_helper")
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
4
4
|
require "ostruct"
|
5
|
+
require "json"
|
5
6
|
|
6
7
|
class Post < Ohm::Model
|
7
8
|
attribute :body
|
@@ -256,6 +257,16 @@ class ModelTest < Test::Unit::TestCase
|
|
256
257
|
|
257
258
|
assert_equal "foo", event.slug
|
258
259
|
end
|
260
|
+
|
261
|
+
should "save counters" do
|
262
|
+
event = Event.create(:name => "Foo")
|
263
|
+
|
264
|
+
event.incr(:votes)
|
265
|
+
event.save
|
266
|
+
|
267
|
+
assert_equal 1, Event[event.id].votes
|
268
|
+
end
|
269
|
+
|
259
270
|
end
|
260
271
|
|
261
272
|
context "Delete" do
|
@@ -942,6 +953,18 @@ class ModelTest < Test::Unit::TestCase
|
|
942
953
|
assert_equal car, Car[1]
|
943
954
|
assert_nil Make[1]
|
944
955
|
end
|
956
|
+
|
957
|
+
should "allow changing the database" do
|
958
|
+
Car.create(:name => "Twingo")
|
959
|
+
|
960
|
+
assert_equal ["1"], Car.all.raw
|
961
|
+
|
962
|
+
Car.connect :db => 15
|
963
|
+
assert_equal [], Car.all.raw
|
964
|
+
|
965
|
+
Car.connect :db => 14
|
966
|
+
assert_equal ["1"], Car.all.raw
|
967
|
+
end
|
945
968
|
end
|
946
969
|
|
947
970
|
context "Persistence" do
|
@@ -959,4 +982,103 @@ class ModelTest < Test::Unit::TestCase
|
|
959
982
|
assert_equal 1, Event[1].votes
|
960
983
|
end
|
961
984
|
end
|
985
|
+
|
986
|
+
context "Exporting" do
|
987
|
+
class Venue < Ohm::Model
|
988
|
+
attribute :name
|
989
|
+
|
990
|
+
def validate
|
991
|
+
assert_present :name
|
992
|
+
end
|
993
|
+
end
|
994
|
+
|
995
|
+
context "a new model without errors" do
|
996
|
+
should "export an empty hash via to_hash" do
|
997
|
+
person = Venue.new
|
998
|
+
assert_equal({}, person.to_hash)
|
999
|
+
end
|
1000
|
+
end
|
1001
|
+
|
1002
|
+
context "a new model with some errors" do
|
1003
|
+
should "export a hash with the errors" do
|
1004
|
+
person = Venue.new
|
1005
|
+
person.valid?
|
1006
|
+
|
1007
|
+
assert_equal({ :errors => [[:name, :not_present]] }, person.to_hash)
|
1008
|
+
end
|
1009
|
+
end
|
1010
|
+
|
1011
|
+
context "an existing model" do
|
1012
|
+
should "export a hash with the its id" do
|
1013
|
+
person = Venue.create(:name => "John Doe")
|
1014
|
+
assert_equal({ :id => '1' }, person.to_hash)
|
1015
|
+
end
|
1016
|
+
end
|
1017
|
+
|
1018
|
+
context "an existing model with validation errors" do
|
1019
|
+
should "export a hash with its id and the errors" do
|
1020
|
+
person = Venue.create(:name => "John Doe")
|
1021
|
+
person.name = nil
|
1022
|
+
person.valid?
|
1023
|
+
|
1024
|
+
expected_hash = { :id => '1', :errors => [[:name, :not_present]] }
|
1025
|
+
|
1026
|
+
assert_equal expected_hash, person.to_hash
|
1027
|
+
end
|
1028
|
+
end
|
1029
|
+
|
1030
|
+
class Programmer < Ohm::Model
|
1031
|
+
attribute :language
|
1032
|
+
|
1033
|
+
def validate
|
1034
|
+
assert_present :language
|
1035
|
+
end
|
1036
|
+
|
1037
|
+
def to_hash
|
1038
|
+
super.merge(:language => language)
|
1039
|
+
end
|
1040
|
+
end
|
1041
|
+
|
1042
|
+
context "a subclassed to_hash" do
|
1043
|
+
should "return the merged attributes" do
|
1044
|
+
programmer = Programmer.create(:language => "Ruby")
|
1045
|
+
expected_hash = { :id => '1', :language => 'Ruby' }
|
1046
|
+
|
1047
|
+
assert_equal expected_hash, programmer.to_hash
|
1048
|
+
end
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
context "the JSON representation of an object" do
|
1052
|
+
should "just be the to_hash of a model" do
|
1053
|
+
json = JSON.parse(Programmer.create(:language => "Ruby").to_json)
|
1054
|
+
|
1055
|
+
assert_equal ["id", "language"], json.keys.sort
|
1056
|
+
assert_equal "1", json["id"]
|
1057
|
+
assert_equal "Ruby", json["language"]
|
1058
|
+
end
|
1059
|
+
end
|
1060
|
+
end
|
1061
|
+
|
1062
|
+
describe "a Model with individual attribute writing needs" do
|
1063
|
+
class Order < Ohm::Model
|
1064
|
+
attribute :state
|
1065
|
+
|
1066
|
+
def authorize!
|
1067
|
+
write_remote :state, 'authorized'
|
1068
|
+
end
|
1069
|
+
end
|
1070
|
+
|
1071
|
+
test "writes locally" do
|
1072
|
+
order = Order.create(:state => "pending")
|
1073
|
+
order.authorize!
|
1074
|
+
assert_equal 'authorized', order.state
|
1075
|
+
end
|
1076
|
+
|
1077
|
+
test "writes remotely" do
|
1078
|
+
order = Order.create(:state => "pending")
|
1079
|
+
order.authorize!
|
1080
|
+
order = Order[order.id]
|
1081
|
+
assert_equal 'authorized', order.state
|
1082
|
+
end
|
1083
|
+
end
|
962
1084
|
end
|
data/test/mutex_test.rb
CHANGED
data/test/upgrade_script_test.rb
CHANGED
data/test/validations_test.rb
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
|
+
|
3
|
+
$missing_constants = []
|
4
|
+
|
5
|
+
class Object
|
6
|
+
def self.const_missing(name)
|
7
|
+
$missing_constants << name
|
8
|
+
super(name)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Foo < Ohm::Model
|
13
|
+
set :bars, Bar
|
14
|
+
end
|
15
|
+
|
16
|
+
class Tests < Test::Unit::TestCase
|
17
|
+
test "calls other const_missing hooks" do
|
18
|
+
assert_equal [:Bar], $missing_constants
|
19
|
+
end
|
20
|
+
end
|
metadata
CHANGED
@@ -6,8 +6,8 @@ version: !ruby/object:Gem::Version
|
|
6
6
|
- 0
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.1.0.
|
9
|
+
- rc4
|
10
|
+
version: 0.1.0.rc4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Michel Martens
|
@@ -16,13 +16,14 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2010-
|
19
|
+
date: 2010-07-02 00:00:00 -03:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
23
23
|
name: redis
|
24
24
|
prerelease: false
|
25
25
|
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
26
27
|
requirements:
|
27
28
|
- - ">="
|
28
29
|
- !ruby/object:Gem::Version
|
@@ -38,6 +39,7 @@ dependencies:
|
|
38
39
|
name: contest
|
39
40
|
prerelease: false
|
40
41
|
requirement: &id002 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
41
43
|
requirements:
|
42
44
|
- - ~>
|
43
45
|
- !ruby/object:Gem::Version
|
@@ -51,6 +53,7 @@ dependencies:
|
|
51
53
|
name: batch
|
52
54
|
prerelease: false
|
53
55
|
requirement: &id003 !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
54
57
|
requirements:
|
55
58
|
- - ~>
|
56
59
|
- !ruby/object:Gem::Version
|
@@ -86,6 +89,7 @@ files:
|
|
86
89
|
- test/all_tests.rb
|
87
90
|
- test/connection_test.rb
|
88
91
|
- test/errors_test.rb
|
92
|
+
- test/hash_key_test.rb
|
89
93
|
- test/indices_test.rb
|
90
94
|
- test/model_module_test.rb
|
91
95
|
- test/model_test.rb
|
@@ -93,6 +97,7 @@ files:
|
|
93
97
|
- test/test_helper.rb
|
94
98
|
- test/upgrade_script_test.rb
|
95
99
|
- test/validations_test.rb
|
100
|
+
- test/wrapper_test.rb
|
96
101
|
- test/test.conf
|
97
102
|
has_rdoc: true
|
98
103
|
homepage: http://github.com/soveran/ohm
|
@@ -104,6 +109,7 @@ rdoc_options: []
|
|
104
109
|
require_paths:
|
105
110
|
- lib
|
106
111
|
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
+
none: false
|
107
113
|
requirements:
|
108
114
|
- - ">="
|
109
115
|
- !ruby/object:Gem::Version
|
@@ -111,6 +117,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
111
117
|
- 0
|
112
118
|
version: "0"
|
113
119
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
|
+
none: false
|
114
121
|
requirements:
|
115
122
|
- - ">"
|
116
123
|
- !ruby/object:Gem::Version
|
@@ -122,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
129
|
requirements: []
|
123
130
|
|
124
131
|
rubyforge_project: ohm
|
125
|
-
rubygems_version: 1.3.
|
132
|
+
rubygems_version: 1.3.7
|
126
133
|
signing_key:
|
127
134
|
specification_version: 3
|
128
135
|
summary: Object-hash mapping library for Redis.
|