redis_object 1.0 → 1.1
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/.coveralls.yml +1 -0
- data/.gitignore +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/README.markdown +24 -15
- data/Rakefile +8 -0
- data/lib/redis_object.rb +11 -1
- data/lib/redis_object/base.rb +210 -60
- data/lib/redis_object/collection.rb +130 -100
- data/lib/redis_object/defaults.rb +21 -8
- data/lib/redis_object/{history.rb → experimental/history.rb} +0 -0
- data/lib/redis_object/ext/filters.rb +34 -16
- data/lib/redis_object/ext/script_cache.rb +92 -0
- data/lib/redis_object/ext/shardable.rb +18 -0
- data/lib/redis_object/ext/triggers.rb +75 -13
- data/lib/redis_object/ext/view_caching.rb +258 -0
- data/lib/redis_object/ext/views.rb +102 -0
- data/lib/redis_object/indices.rb +44 -39
- data/lib/redis_object/inheritance_tracking.rb +23 -0
- data/lib/redis_object/keys.rb +4 -4
- data/lib/redis_object/storage.rb +30 -1
- data/lib/redis_object/storage/adapter.rb +6 -3
- data/lib/redis_object/storage/redis.rb +98 -3
- data/lib/redis_object/timestamps.rb +42 -21
- data/lib/redis_object/types.rb +172 -30
- data/lib/redis_object/version.rb +1 -1
- data/redis_object.gemspec +1 -0
- data/spec/adapter_spec.rb +43 -0
- data/spec/base_spec.rb +41 -6
- data/spec/benchmark_spec.rb +46 -0
- data/spec/collections_spec.rb +144 -0
- data/spec/defaults_spec.rb +56 -0
- data/spec/filters_spec.rb +29 -0
- data/spec/indices_spec.rb +45 -0
- data/spec/rename_class_spec.rb +96 -0
- data/spec/spec_helper.rb +32 -1
- data/spec/timestamp_spec.rb +28 -0
- data/spec/trigger_spec.rb +51 -0
- data/spec/types_spec.rb +103 -0
- data/spec/view_caching_spec.rb +130 -0
- data/spec/views_spec.rb +72 -0
- metadata +111 -116
- data/doc/Object.html +0 -185
- data/doc/Seabright.html +0 -181
- data/doc/Seabright/Adapter.html +0 -442
- data/doc/Seabright/Collection.html +0 -797
- data/doc/Seabright/Collections.html +0 -635
- data/doc/Seabright/Collections/ClassMethods.html +0 -212
- data/doc/Seabright/ExternalIndex.html +0 -217
- data/doc/Seabright/History.html +0 -382
- data/doc/Seabright/History/ClassMethods.html +0 -276
- data/doc/Seabright/Indices.html +0 -324
- data/doc/Seabright/Indices/ClassMethods.html +0 -348
- data/doc/Seabright/Keys.html +0 -314
- data/doc/Seabright/Keys/ClassMethods.html +0 -276
- data/doc/Seabright/ObjectBase.html +0 -852
- data/doc/Seabright/ObjectBase/ClassMethods.html +0 -677
- data/doc/Seabright/RedisObject.html +0 -230
- data/doc/Seabright/References.html +0 -280
- data/doc/Seabright/Storage.html +0 -252
- data/doc/Seabright/Storage/ClassMethods.html +0 -276
- data/doc/Seabright/Storage/MySQL.html +0 -442
- data/doc/Seabright/Storage/Redis.html +0 -218
- data/doc/Seabright/Template.html +0 -212
- data/doc/Seabright/Template/ClassMethods.html +0 -166
- data/doc/Seabright/Timestamps.html +0 -292
- data/doc/Seabright/Timestamps/ClassMethods.html +0 -214
- data/doc/Seabright/Types.html +0 -410
- data/doc/Seabright/Types/ClassMethods.html +0 -308
- data/doc/created.rid +0 -17
- data/doc/images/add.png +0 -0
- data/doc/images/brick.png +0 -0
- data/doc/images/brick_link.png +0 -0
- data/doc/images/bug.png +0 -0
- data/doc/images/bullet_black.png +0 -0
- data/doc/images/bullet_toggle_minus.png +0 -0
- data/doc/images/bullet_toggle_plus.png +0 -0
- data/doc/images/date.png +0 -0
- data/doc/images/delete.png +0 -0
- data/doc/images/find.png +0 -0
- data/doc/images/loadingAnimation.gif +0 -0
- data/doc/images/macFFBgHack.png +0 -0
- data/doc/images/package.png +0 -0
- data/doc/images/page_green.png +0 -0
- data/doc/images/page_white_text.png +0 -0
- data/doc/images/page_white_width.png +0 -0
- data/doc/images/plugin.png +0 -0
- data/doc/images/ruby.png +0 -0
- data/doc/images/tag_blue.png +0 -0
- data/doc/images/tag_green.png +0 -0
- data/doc/images/transparent.png +0 -0
- data/doc/images/wrench.png +0 -0
- data/doc/images/wrench_orange.png +0 -0
- data/doc/images/zoom.png +0 -0
- data/doc/index.html +0 -125
- data/doc/js/darkfish.js +0 -153
- data/doc/js/jquery.js +0 -18
- data/doc/js/navigation.js +0 -142
- data/doc/js/search.js +0 -94
- data/doc/js/search_index.js +0 -1
- data/doc/js/searcher.js +0 -228
- data/doc/rdoc.css +0 -543
- data/doc/table_of_contents.html +0 -394
@@ -2,34 +2,54 @@ module Seabright
|
|
2
2
|
module Timestamps
|
3
3
|
|
4
4
|
def update_timestamps
|
5
|
-
return
|
5
|
+
# return unless self.class.time_matters?
|
6
6
|
set(:created_at, Time.now) if !is_set?(:created_at)
|
7
7
|
set(:updated_at, Time.now)
|
8
8
|
end
|
9
9
|
|
10
|
-
def mset(dat)
|
11
|
-
super(dat)
|
12
|
-
set(:updated_at, Time.now)
|
13
|
-
end
|
14
|
-
|
15
|
-
def set(k,v)
|
16
|
-
super(k,v)
|
17
|
-
set(:updated_at, Time.now) unless k.to_sym == :updated_at
|
18
|
-
end
|
19
|
-
|
20
|
-
def save
|
21
|
-
super
|
22
|
-
update_timestamps
|
23
|
-
end
|
24
|
-
|
25
10
|
module ClassMethods
|
26
11
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
30
|
-
|
12
|
+
def intercept_sets_for_timestamps!
|
13
|
+
return if @intercepted_sets_for_timestamps
|
14
|
+
self.class_eval do
|
15
|
+
alias_method :untimestamped_set, :set unless method_defined?(:untimestamped_set)
|
16
|
+
def set(k,v)
|
17
|
+
ret = untimestamped_set(k,v)
|
18
|
+
set(:updated_at, Time.now) unless k.to_sym == :updated_at
|
19
|
+
ret
|
20
|
+
end
|
21
|
+
alias_method :untimestamped_mset, :mset unless method_defined?(:untimestamped_mset)
|
22
|
+
def mset(dat)
|
23
|
+
ret = untimestamped_mset(dat)
|
24
|
+
set(:updated_at, Time.now)
|
25
|
+
ret
|
26
|
+
end
|
27
|
+
alias_method :untimestamped_setnx, :setnx unless method_defined?(:untimestamped_setnx)
|
28
|
+
def setnx(k,v)
|
29
|
+
ret = untimestamped_setnx(k,v)
|
30
|
+
set(:updated_at, Time.now) unless k.to_sym == :updated_at
|
31
|
+
ret
|
32
|
+
end
|
33
|
+
alias_method :untimestamped_save, :save unless method_defined?(:untimestamped_save)
|
34
|
+
def save
|
35
|
+
ret = untimestamped_save()
|
36
|
+
update_timestamps
|
37
|
+
ret
|
38
|
+
end
|
39
|
+
end
|
40
|
+
@intercepted_sets_for_timestamps = true
|
31
41
|
end
|
32
42
|
|
43
|
+
# def time_matters?
|
44
|
+
# @time_irrelevant != true
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# def time_matters_not!
|
48
|
+
# @time_irrelevant = true
|
49
|
+
# sort_indices.delete(:created_at)
|
50
|
+
# sort_indices.delete(:updated_at)
|
51
|
+
# end
|
52
|
+
#
|
33
53
|
def recently_created(num=5)
|
34
54
|
self.indexed(:created_at,num,true)
|
35
55
|
end
|
@@ -41,12 +61,13 @@ module Seabright
|
|
41
61
|
end
|
42
62
|
|
43
63
|
def self.included(base)
|
44
|
-
|
64
|
+
# @time_irrelevant = false
|
45
65
|
base.send(:sort_by,:created_at)
|
46
66
|
base.send(:sort_by,:updated_at)
|
47
67
|
base.send(:register_format,:created_at, :date)
|
48
68
|
base.send(:register_format,:updated_at, :date)
|
49
69
|
base.extend(ClassMethods)
|
70
|
+
base.intercept_sets_for_timestamps!
|
50
71
|
end
|
51
72
|
|
52
73
|
end
|
data/lib/redis_object/types.rb
CHANGED
@@ -22,7 +22,12 @@ module Seabright
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def format_date(val)
|
25
|
-
|
25
|
+
begin
|
26
|
+
val.is_a?(DateTime) || val.is_a?(Date) || val.is_a?(Time) ? val : ( val.is_a?(String) ? DateTime.parse(val) : nil )
|
27
|
+
rescue StandardError => e
|
28
|
+
puts "Could not parse value as date using Date.parse. Returning nil instead. Value: #{val.inspect}\nError: #{e.inspect}" if DEBUG
|
29
|
+
nil
|
30
|
+
end
|
26
31
|
end
|
27
32
|
|
28
33
|
def score_date(val)
|
@@ -30,7 +35,11 @@ module Seabright
|
|
30
35
|
end
|
31
36
|
|
32
37
|
def format_array(val)
|
33
|
-
|
38
|
+
Yajl::Parser.new(:symbolize_keys => true).parse(val)
|
39
|
+
end
|
40
|
+
|
41
|
+
def save_array(val)
|
42
|
+
Yajl::Encoder.encode(val)
|
34
43
|
end
|
35
44
|
|
36
45
|
def format_number(val)
|
@@ -58,72 +67,205 @@ module Seabright
|
|
58
67
|
val=="true"
|
59
68
|
end
|
60
69
|
|
61
|
-
def
|
62
|
-
val ?
|
63
|
-
end
|
64
|
-
|
65
|
-
def get(k)
|
66
|
-
enforce_format(k,super(k))
|
70
|
+
def save_boolean(val)
|
71
|
+
val === true ? "true" : "false"
|
67
72
|
end
|
68
73
|
|
69
|
-
def
|
70
|
-
|
71
|
-
super(dat)
|
72
|
-
end
|
73
|
-
|
74
|
-
def set(k,v)
|
75
|
-
super(k,save_format(k,v))
|
74
|
+
def score_boolean(val)
|
75
|
+
val ? 1 : 0
|
76
76
|
end
|
77
77
|
|
78
78
|
module ClassMethods
|
79
79
|
|
80
80
|
def date(k)
|
81
|
-
|
82
|
-
|
81
|
+
set_field_format(k, :format_date)
|
82
|
+
set_score_format(k, :score_date)
|
83
83
|
end
|
84
84
|
|
85
85
|
def number(k)
|
86
|
-
|
87
|
-
|
86
|
+
set_field_format(k, :format_number)
|
87
|
+
set_score_format(k, :score_number)
|
88
88
|
end
|
89
89
|
alias_method :int, :number
|
90
90
|
|
91
91
|
def float(k)
|
92
|
-
|
93
|
-
|
92
|
+
set_field_format(k, :format_float)
|
93
|
+
set_score_format(k, :score_float)
|
94
94
|
end
|
95
95
|
|
96
96
|
def bool(k)
|
97
|
-
|
98
|
-
|
97
|
+
set_field_format(k, :format_boolean)
|
98
|
+
set_score_format(k, :score_boolean)
|
99
|
+
set_save_format(k, :save_boolean)
|
99
100
|
end
|
100
101
|
alias_method :boolean, :bool
|
101
102
|
|
102
103
|
def array(k)
|
103
|
-
|
104
|
+
set_field_format(k, :format_array)
|
105
|
+
set_save_format(k, :save_array)
|
104
106
|
end
|
105
107
|
|
106
108
|
def json(k)
|
107
|
-
|
108
|
-
|
109
|
+
set_field_format(k, :format_json)
|
110
|
+
set_save_format(k, :save_json)
|
109
111
|
end
|
110
112
|
|
111
113
|
def field_formats
|
112
|
-
|
114
|
+
@field_formats_hash ||= (defined?(superclass.field_formats) ? superclass.field_formats.clone : {})
|
113
115
|
end
|
114
116
|
|
115
117
|
def score_formats
|
116
|
-
|
118
|
+
@score_formats_hash ||= (defined?(superclass.score_formats) ? superclass.score_formats.clone : {})
|
117
119
|
end
|
118
120
|
|
119
121
|
def save_formats
|
120
|
-
|
122
|
+
@save_formats_hash ||= (defined?(superclass.save_formats) ? superclass.save_formats.clone : {})
|
123
|
+
end
|
124
|
+
|
125
|
+
def set_field_format(k, v)
|
126
|
+
field_formats_set_locally.add(k)
|
127
|
+
field_formats[k] = v
|
128
|
+
update_child_class_field_formats(k, v)
|
129
|
+
intercept_for_typing!
|
130
|
+
end
|
131
|
+
|
132
|
+
def field_formats_set_locally
|
133
|
+
@field_formats_set_locally_set ||= Set.new
|
134
|
+
end
|
135
|
+
|
136
|
+
def inherit_field_format(k, v)
|
137
|
+
unless fields_formats_set_locally.include? k
|
138
|
+
field_formats[k] = v
|
139
|
+
update_child_class_field_formats(k, v)
|
140
|
+
end
|
141
|
+
intercept_for_typing!
|
142
|
+
end
|
143
|
+
|
144
|
+
def update_child_class_field_formats(k, v)
|
145
|
+
child_classes.each do |child_class|
|
146
|
+
child_class.inherit_field_format(k, v)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def set_score_format(k, v)
|
151
|
+
score_formats_set_locally.add(k)
|
152
|
+
score_formats[k] = v
|
153
|
+
update_child_class_score_formats(k, v)
|
154
|
+
intercept_for_typing!
|
155
|
+
end
|
156
|
+
|
157
|
+
def score_formats_set_locally
|
158
|
+
@score_formats_set_locally_set ||= Set.new
|
159
|
+
end
|
160
|
+
|
161
|
+
def inherit_score_format(k, v)
|
162
|
+
unless scores_formats_set_locally.include? k
|
163
|
+
score_formats[k] = v
|
164
|
+
update_child_class_score_formats(k, v)
|
165
|
+
end
|
166
|
+
intercept_for_typing!
|
167
|
+
end
|
168
|
+
|
169
|
+
def update_child_class_score_formats(k, v)
|
170
|
+
child_classes.each do |child_class|
|
171
|
+
child_class.inherit_score_format(k, v)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def set_save_format(k, v)
|
176
|
+
save_formats_set_locally.add(k)
|
177
|
+
save_formats[k] = v
|
178
|
+
update_child_class_save_formats(k, v)
|
179
|
+
intercept_for_typing!
|
180
|
+
end
|
181
|
+
|
182
|
+
def save_formats_set_locally
|
183
|
+
@save_formats_set_locally_set ||= Set.new
|
184
|
+
end
|
185
|
+
|
186
|
+
def inherit_save_format(k, v)
|
187
|
+
unless save_formats_set_locally.include? k
|
188
|
+
save_formats[k] = v
|
189
|
+
update_child_class_save_formats(k, v)
|
190
|
+
end
|
191
|
+
intercept_for_typing!
|
192
|
+
end
|
193
|
+
|
194
|
+
def update_child_class_save_formats(k, v)
|
195
|
+
child_classes.each do |child_class|
|
196
|
+
child_class.inherit_save_format(k, v)
|
197
|
+
end
|
121
198
|
end
|
122
199
|
|
123
200
|
def register_format(k,fmt)
|
124
201
|
send(fmt, k)
|
125
202
|
end
|
126
203
|
|
204
|
+
def describe
|
205
|
+
all_keys.inject({}) do |acc,(k,v)|
|
206
|
+
if field_formats[k.to_sym]
|
207
|
+
acc[k.to_sym] ||= [field_formats[k.to_sym].to_s.gsub(/^format_/,'').to_sym, 0]
|
208
|
+
else
|
209
|
+
acc[k.to_sym] ||= [:string, 0]
|
210
|
+
end
|
211
|
+
acc[k.to_sym][1] += 1
|
212
|
+
acc
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def dump_schema(file)
|
217
|
+
child_classes_set.sort {|a,b| a.name <=> b.name}.each do |child|
|
218
|
+
file.puts "# #{child.name}"
|
219
|
+
# sort fields by number of instances found
|
220
|
+
child.describe.sort {|a,b| b[1][1] <=> a[1][1]}.each do |field,(type, count)|
|
221
|
+
file.puts "#{field}: #{type} (#{count})"
|
222
|
+
end
|
223
|
+
file.puts
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def intercept_for_typing!
|
228
|
+
return if @intercepted_for_typing
|
229
|
+
self.class_eval do
|
230
|
+
|
231
|
+
alias_method :untyped_get, :get unless method_defined?(:untyped_get)
|
232
|
+
def get(k)
|
233
|
+
enforce_format(k,untyped_get(k))
|
234
|
+
end
|
235
|
+
|
236
|
+
alias_method :untyped_mset, :mset unless method_defined?(:untyped_mset)
|
237
|
+
def mset(dat)
|
238
|
+
dat.merge!(dat) {|k,v1,v2| save_format(k,v1) }
|
239
|
+
untyped_mset(dat)
|
240
|
+
end
|
241
|
+
|
242
|
+
alias_method :untyped_set, :set unless method_defined?(:untyped_set)
|
243
|
+
def set(k,v)
|
244
|
+
untyped_set(k,save_format(k,v))
|
245
|
+
end
|
246
|
+
|
247
|
+
alias_method :untyped_setnx, :setnx unless method_defined?(:untyped_setnx)
|
248
|
+
def setnx(k,v)
|
249
|
+
untyped_setnx(k,save_format(k,v))
|
250
|
+
end
|
251
|
+
|
252
|
+
end
|
253
|
+
@intercepted_for_typing = true
|
254
|
+
end
|
255
|
+
|
256
|
+
private
|
257
|
+
|
258
|
+
def all_keys(limit=100)
|
259
|
+
steps = 0
|
260
|
+
all.inject([]) do |acc,obj|
|
261
|
+
store.hkeys(obj.hkey).each do |k|
|
262
|
+
acc << k.to_sym
|
263
|
+
end
|
264
|
+
steps += 1
|
265
|
+
return acc if steps >= limit
|
266
|
+
acc
|
267
|
+
end
|
268
|
+
end
|
127
269
|
end
|
128
270
|
|
129
271
|
def self.included(base)
|
@@ -131,4 +273,4 @@ module Seabright
|
|
131
273
|
end
|
132
274
|
|
133
275
|
end
|
134
|
-
end
|
276
|
+
end
|
data/lib/redis_object/version.rb
CHANGED
data/redis_object.gemspec
CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
s.required_ruby_version = '>= 1.9.2'
|
22
|
+
s.add_dependency "utf8_utils"
|
22
23
|
s.add_dependency "redis"
|
23
24
|
s.add_dependency "yajl-ruby"
|
24
25
|
s.add_dependency "activesupport"
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
module ObjectTests
|
4
|
+
class User < RedisObject
|
5
|
+
use_store :global
|
6
|
+
end
|
7
|
+
class Thingy < RedisObject
|
8
|
+
|
9
|
+
end
|
10
|
+
class Doodad < RedisObject
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe RedisObject do
|
16
|
+
|
17
|
+
it "can reconnect to redis" do
|
18
|
+
RedisObject.reconnect!
|
19
|
+
RedisObject.store.reconnect!
|
20
|
+
end
|
21
|
+
|
22
|
+
it "can dump to a file" do
|
23
|
+
obj = ObjectTests::User.create("test")
|
24
|
+
RedisObject.dump_stores_to_files("/tmp")
|
25
|
+
RedisObject.store.flushdb
|
26
|
+
end
|
27
|
+
|
28
|
+
it "can restore from a file" do
|
29
|
+
RedisObject.restore_stores_from_files("/tmp")
|
30
|
+
ObjectTests::User.find("test").should be_a(ObjectTests::User)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "can get all stores" do
|
34
|
+
RedisObject.stores.count.should eq(1)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "can reset stores" do
|
38
|
+
RedisObject.stores.each do |(name,store)|
|
39
|
+
store.reset
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
data/spec/base_spec.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
2
|
|
3
|
-
DEBUG = false
|
4
|
-
|
5
3
|
module ObjectTests
|
6
4
|
class User < RedisObject
|
7
|
-
|
5
|
+
use_store :global
|
8
6
|
end
|
9
7
|
class Thingy < RedisObject
|
10
8
|
|
@@ -15,41 +13,78 @@ module ObjectTests
|
|
15
13
|
end
|
16
14
|
|
17
15
|
describe RedisObject do
|
16
|
+
|
18
17
|
it "can be created" do
|
19
18
|
obj = ObjectTests::User.new
|
20
19
|
end
|
20
|
+
|
21
21
|
it "can be created with an id" do
|
22
22
|
obj = ObjectTests::User.new("test")
|
23
23
|
obj.save
|
24
24
|
end
|
25
|
+
|
26
|
+
it "can create an id" do
|
27
|
+
obj = ObjectTests::User.new("test")
|
28
|
+
obj.new_id
|
29
|
+
end
|
30
|
+
|
31
|
+
it "can reserve an id" do
|
32
|
+
obj = ObjectTests::User.new("test")
|
33
|
+
obj.reserve("test")
|
34
|
+
end
|
35
|
+
|
25
36
|
it "should be found by id" do
|
26
37
|
obj = ObjectTests::User.find("test")
|
27
38
|
obj.should_not be_nil
|
28
39
|
end
|
40
|
+
|
41
|
+
it "can recollect objects" do
|
42
|
+
ObjectTests::User.recollect!
|
43
|
+
end
|
44
|
+
|
45
|
+
it "get get the first object (random)" do
|
46
|
+
obj = ObjectTests::User.first
|
47
|
+
obj.should be_a(ObjectTests::User)
|
48
|
+
end
|
49
|
+
|
29
50
|
it "should save stuff" do
|
30
51
|
obj = ObjectTests::User.find("test")
|
31
52
|
obj.stuff = "yay!"
|
32
|
-
obj
|
53
|
+
obj[:stuff].should eq("yay!")
|
54
|
+
obj[:stuff] = "yayyay!"
|
55
|
+
obj.stuff.should eq("yayyay!")
|
56
|
+
obj.stuff = "yay!"
|
57
|
+
obj.stuff.should eq("yay!")
|
33
58
|
end
|
59
|
+
|
34
60
|
it "should retrieve stuff" do
|
35
61
|
obj = ObjectTests::User.find("test")
|
36
|
-
obj.stuff.should
|
62
|
+
obj.stuff.should eq("yay!")
|
37
63
|
end
|
64
|
+
|
38
65
|
it "can collect other objects" do
|
39
66
|
obj = ObjectTests::User.find("test")
|
40
67
|
obj2 = ObjectTests::Thingy.new("yay")
|
41
68
|
obj << obj2
|
42
69
|
obj.should have_collection(:thingies)
|
43
70
|
end
|
71
|
+
|
44
72
|
it "can reference other objects" do
|
45
73
|
obj = ObjectTests::User.find("test")
|
46
74
|
obj3 = ObjectTests::Doodad.new("woo")
|
47
75
|
obj.reference obj3
|
48
76
|
obj.should have_collection(:doodads)
|
49
77
|
end
|
78
|
+
|
79
|
+
it "can convert raw to json" do
|
80
|
+
obj = ObjectTests::User.find("test")
|
81
|
+
obj.to_json.length.should > 0
|
82
|
+
end
|
83
|
+
|
50
84
|
it "should be deletable" do
|
51
85
|
obj = ObjectTests::User.find("test")
|
52
86
|
obj.delete!
|
53
87
|
ObjectTests::User.find("test").should be_nil
|
54
88
|
end
|
55
|
-
|
89
|
+
|
90
|
+
end
|