public
Description: Ruby interface to CouchDB
Homepage: http://code.google.com/p/activecouch/
Clone URL: git://github.com/JackDanger/active_couch.git
- Fully functional id/rev attributes
- Improved documentation for all methods
- #save, #find, #create methods all work as intended (including setting id 
and rev based on the actual document persisted in CouchDB)

git-svn-id: http://activecouch.googlecode.com/svn/trunk@58 
e44de9e2-1e40-0410-bb6c-c9d70e891a3e
arun.thampi (author)
Mon Jan 21 08:40:00 -0800 2008
commit  76ebaf1d8674a1d621434c3eb26de9802ebdf19b
tree    5b74803feff8a37a338a62fbdf00d4209b99e4b7
parent  ec5e09e815b9221f4fa7498850726fa35d3980eb
...
18
19
20
21
 
22
23
24
...
27
28
29
30
 
31
32
33
...
37
38
39
 
 
 
 
 
40
41
...
18
19
20
 
21
22
23
24
...
27
28
29
 
30
31
32
33
...
37
38
39
40
41
42
43
44
45
46
0
@@ -18,7 +18,7 @@ module ActiveCouch
0
       # Check if default value provided matches the type provided
0
       if options.has_key?(:with_default_value)
0
         value = options[:with_default_value]
0
- unless value.is_a?(klass)
0
+ unless value.is_a?(klass) || value.is_a?(NilClass)
0
           raise InvalidCouchTypeError, "Default value provided does not match the type of #{klass.to_s}"
0
         end
0
       end
0
@@ -27,7 +27,7 @@ module ActiveCouch
0
     end
0
     
0
     def value=(val)
0
- unless val.is_a?(@klass)
0
+ unless val.is_a?(@klass) || val.is_a?(NilClass)
0
         raise InvalidCouchTypeError, "Default value provided does not match the type of #{@klass.to_s}"
0
       end
0
       # Set the value if value matches type
0
@@ -37,5 +37,10 @@ module ActiveCouch
0
     def to_hash
0
       { @name => @value }
0
     end
0
+
0
+ def nil?
0
+ @value.nil?
0
+ end
0
+
0
   end # End class CouchAttribute
0
 end # End module ActiveCouch
...
1
2
3
 
 
4
5
6
7
8
9
10
11
 
 
12
13
14
...
17
18
19
 
 
 
 
 
20
21
22
...
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
57
58
59
60
 
 
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
89
90
 
 
 
 
 
 
 
 
 
91
92
93
94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
96
97
98
99
100
101
102
 
 
 
 
 
 
 
 
103
104
105
...
156
157
158
 
 
 
 
 
 
 
 
 
159
160
161
162
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
164
165
...
167
168
169
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
171
172
...
174
175
176
 
 
 
 
 
 
 
 
 
 
177
178
179
180
181
182
183
184
185
186
187
 
 
 
 
 
 
 
 
 
 
188
189
190
...
198
199
200
 
 
 
 
 
 
 
 
 
201
202
203
...
273
274
275
 
 
 
 
 
276
277
278
279
280
281
282
283
284
285
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
287
288
...
1
2
 
3
4
5
6
7
8
9
10
 
 
11
12
13
14
15
...
18
19
20
21
22
23
24
25
26
27
28
...
34
35
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
 
 
 
57
58
59
60
61
62
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
 
 
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
 
 
112
 
 
 
113
114
115
116
117
118
119
120
121
122
123
...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
...
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
...
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
 
 
 
 
 
258
259
260
261
262
263
264
265
266
267
268
269
270
...
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
...
362
363
364
365
366
367
368
369
370
 
371
 
 
 
 
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
0
@@ -1,14 +1,15 @@
0
 module ActiveCouch
0
   class Base
0
- SPECIAL_MEMBERS = %w(attributes associations connection)
0
+ SPECIAL_MEMBERS = %w(attributes associations connection)
0
+ DEFAULT_ATTRIBUTES = %w(id rev)
0
 
0
     def initialize(params = {})
0
       # Object instance variable
0
       @attributes, @associations, @connection, klass_atts, klass_assocs = {}, {}, self.class.connection, self.class.attributes, self.class.associations
0
       # ActiveCouch::Connection object will be readable in every
0
       # object instantiated from a subclass of ActiveCouch::Base
0
- SPECIAL_MEMBERS.each do |m|
0
- self.instance_eval "def #{m}; @#{m}; end"
0
+ SPECIAL_MEMBERS.each do |k|
0
+ self.instance_eval "def #{k}; @#{k}; end"
0
       end
0
       
0
       klass_atts.each_key do |k|
0
@@ -17,6 +18,11 @@ module ActiveCouch
0
         self.instance_eval "def #{k}=(val); attributes[:#{k}].value = val; end"
0
       end
0
       
0
+ DEFAULT_ATTRIBUTES.each do |x|
0
+ self.instance_eval "def #{x}; _#{x}; end"
0
+ self.instance_eval "def #{x}=(val); self._#{x}=(val); end"
0
+ end
0
+
0
       klass_assocs.each_key do |k|
0
         @associations[k] = HasManyAssociation.new(klass_assocs[k].name, :class => klass_assocs[k].klass)
0
         self.instance_eval "def #{k}; associations[:#{k}].container; end"
0
@@ -28,78 +34,90 @@ module ActiveCouch
0
       from_hash(params)
0
     end
0
 
0
- # Returns the "_id" of the CouchDB document represented by this instance.
0
- def id
0
- @id ||= attributes[:_id]
0
- end
0
-
0
- # Sets the "_id" of the CouchDB document represented by this instance.
0
- # This doesn't do anything unless this is a new document.
0
- def id=(new_id)
0
- if new?
0
- attributes[:_id] = @id = new_id
0
- else
0
- nil
0
- end
0
- end
0
-
0
- # Returns the "_rev" of the CouchDB document represented by this instance.
0
- def rev
0
- @rev ||= attributes[:_rev]
0
- end
0
-
0
- # Returns true if this is a new CouchDB document.
0
- def new?
0
- @rev.nil?
0
- end
0
-
0
+ # Generates a JSON representation of an instance of a subclass of ActiveCouch::Base.
0
+ # Ignores attributes which have a nil value.
0
+ #
0
+ # Examples:
0
+ # class Person < ActiveCouch::Base
0
+ # has :name, :which_is => :text, :with_default_value => "McLovin"
0
+ # end
0
+ #
0
+ # person = Person.new
0
+ # person.to_json # {"name":"McLovin"}
0
+ #
0
+ # class AgedPerson < ActiveCouch::Base
0
+ # has :age, :which_is => :decimal, :with_default_value => 3.5
0
+ # end
0
+ #
0
+ # aged_person = AgedPerson.new
0
+ # aged_person.id = 'abc-def'
0
+ # aged_person.to_json # {"age":3.5, "_id":"abc-def"}
0
     def to_json
0
       hash = {}
0
- # @attributes and @associations are hashes. Get all
0
- # attributes/associations and merge them into a single hash
0
- attributes.each_value { |v| hash.merge!(v.to_hash) }
0
+
0
+ attributes.each_value { |v| hash.merge!(v.to_hash) unless v.nil? }
0
       associations.each_value { |v| hash.merge!(v.to_hash) }
0
       # and by the Power of Grayskull, convert the hash to json
0
       hash.to_json
0
     end
0
 
0
- def from_hash(hash)
0
- # TODO:
0
- # - Clean this up. Doesn't look very nice
0
- # - Raise errors if attribute/association is not present
0
- hash.each do |k,v|
0
- k = k.to_sym rescue k
0
- if v.is_a?(Array) # This means this is a has_many association
0
- unless (assoc = @associations[k]).nil?
0
- name, child_klass = assoc.name, assoc.klass
0
- v.each do |child|
0
- child.is_a?(Hash) ? child_obj = child_klass.new(child) : child_obj = child
0
- self.send "add_#{Inflector.singularize(name)}", child_obj
0
- end
0
- end
0
- elsif v.is_a?(Hash) # This means this is a has_one association (which we might add later)
0
- # Do nothing for now. More later
0
- else # This means this is a normal attribute
0
- self.send("#{k}=", v) if @attributes.has_key?(k)
0
- end
0
- end
0
- end
0
-
0
+ # Saves a document into a CouchDB database. A document can be saved in two ways.
0
+ # One if it has been set an ID by the user, in which case the connection object
0
+ # needs to use an HTTP PUT request to the URL /database/user_generated_id.
0
+ # For the document needs a CouchDB-generated ID, the connection object needs
0
+ # to use an HTTP POST request to the URL /database.
0
+ #
0
+ # Examples:
0
+ # class Person < ActiveCouch::Base
0
+ # has :name, :which_is => :text
0
+ # end
0
+ #
0
+ # person = Person.new(:name => 'McLovin')
0
+ # person.id = 'abc'
0
+ # person.save # true
0
+ # person.new? # false
0
     def save
0
- # POST to database with a JSON representation of the object
0
- response = connection.post("/#{self.class.database_name}", self.to_json)
0
+ if id
0
+ response = connection.put("/#{self.class.database_name}/#{id}", to_json)
0
+ else
0
+ response = connection.post("/#{self.class.database_name}", to_json)
0
+ end
0
+ # Parse the JSON obtained from the body...
0
+ results = JSON.parse(response.body)
0
+ # ...and set the default id and rev attributes
0
+ DEFAULT_ATTRIBUTES.each { |a| self.__send__("#{a}=", results[a]) }
0
       # Response sent will be 201, if the save was successful [201 corresponds to 'created']
0
       return response.code == '201'
0
     end
0
 
0
+ # Checks to see if a document has been persisted in a CouchDB database.
0
+ # If a document has been retrieved from CouchDB, or has been persisted in
0
+ # a CouchDB database, the attribute _rev would not be nil.
0
+ #
0
+ # Examples:
0
+ # class Person < ActiveCouch::Base
0
+ # has :name, :which_is => :text
0
+ # end
0
+ #
0
+ # person = Person.new(:name => 'McLovin')
0
+ # person.id = 'abc'
0
+ # person.save # true
0
+ # person.new? # false
0
+ def new?
0
+ rev.nil?
0
+ end
0
+
0
     class << self # Class methods
0
 
0
- # All classes inheriting from ActiveCouch::Base will have
0
- # class instance variables in SPECIAL_MEMBERS.
0
       def inherited(subklass)
0
- SPECIAL_MEMBERS.each do |x|
0
- subklass.instance_variable_set "@#{x}", {}
0
- subklass.instance_eval "def #{x}; @#{x}; end"
0
+ # TODO: Need a cleaner way to do this
0
+ subklass.instance_variable_set "@attributes", { :_id => Attribute.new(:_id, :with_default_value => nil),
0
+ :_rev => Attribute.new(:_rev, :with_default_value => nil) }
0
+ subklass.instance_variable_set "@associations", {}
0
+ subklass.instance_variable_set "@connections", nil
0
+
0
+ SPECIAL_MEMBERS.each do |k|
0
+ subklass.instance_eval "def #{k}; @#{k}; end"
0
         end
0
       end
0
 
0
@@ -156,10 +174,43 @@ module ActiveCouch
0
       end
0
       alias :database_name= :set_database_name
0
 
0
+ # Sets the site which the ActiveCouch object has to connect to, which
0
+ # initializes an ActiveCouch::Connection object.
0
+ #
0
+ # Example:
0
+ # class Person < ActiveCouch::Base
0
+ # site 'localhost:5984'
0
+ # end
0
+ #
0
+ # Person.connection.nil? # false
0
       def site(site)
0
         @connection = Connection.new(site)
0
       end
0
 
0
+ # Defines an attribute for a subclass of ActiveCouch::Base. The parameters
0
+ # for this method include name, which is the name of the attribute as well as
0
+ # an options hash.
0
+ #
0
+ # The options hash can contain the key 'which_is' which can
0
+ # have possible values :text, :decimal, :number. It can also contain the key
0
+ # 'with_default_value' which can set a default value for each attribute defined
0
+ # in the subclass of ActiveCouch::Base
0
+ #
0
+ # Examples:
0
+ # class Person < ActiveCouch::Base
0
+ # has :name
0
+ # end
0
+ #
0
+ # person = Person.new
0
+ # p.name.methods.include?(:name) # true
0
+ # p.name.methods.include?(:name=) # false
0
+ #
0
+ # class AgedPerson < ActiveCouch::Base
0
+ # has :age, :which_is => :number, :with_default_value = 18
0
+ # end
0
+ #
0
+ # person = AgedPerson.new
0
+ # person.age # 18
0
       def has(name, options = {})
0
         unless name.is_a?(String) || name.is_a?(Symbol)
0
           raise ArgumentError, "#{name} is neither a String nor a Symbol"
0
@@ -167,6 +218,20 @@ module ActiveCouch
0
         @attributes[name] = Attribute.new(name, options)
0
       end
0
 
0
+ # Defines an array of objects which are 'children' of this class. The has_many
0
+ # function guesses the class of the child, based on the name of the association,
0
+ # but can be over-ridden by the :class key in the options hash.
0
+ #
0
+ # Examples:
0
+ #
0
+ # class Person < ActiveCouch::Base
0
+ # has :name
0
+ # end
0
+ #
0
+ # class GrandPerson < ActiveCouch::Base
0
+ # has_many :people # which will create an empty array which can contain
0
+ # # Person objects
0
+ # end
0
       def has_many(name, options = {})
0
         unless name.is_a?(String) || name.is_a?(Symbol)
0
           raise ArgumentError, "#{name} is neither a String nor a Symbol"
0
@@ -174,17 +239,32 @@ module ActiveCouch
0
         @associations[name] = HasManyAssociation.new(name, options)
0
       end
0
 
0
+ # Initializes an object of a subclass of ActiveCouch::Base based on a JSON
0
+ # representation of the object.
0
+ #
0
+ # Example:
0
+ # class Person < ActiveCouch::Base
0
+ # has :name
0
+ # end
0
+ #
0
+ # person = Person.from_json('{"name":"McLovin"}')
0
+ # person.name # "McLovin"
0
       def from_json(json)
0
         hash = JSON.parse(json)
0
         # Create new based on parsed
0
         self.new(hash)
0
       end
0
 
0
- # Similar to ActiveResource convention, find operates with two different
0
- # retrieval approaches:
0
- # * Find :first
0
- # * Find :all
0
- # This method is stolen from ActiveResource::Base
0
+ # Retrieves one or more object(s) from a CouchDB database, based on the search
0
+ # parameters given.
0
+ #
0
+ # Example:
0
+ # class Person < ActiveCouch::Base
0
+ # has :name
0
+ # end
0
+ #
0
+ # people = Person.find(:first, :params => {:name => "McLovin"})
0
+ # person = Person.find(:all, :params => {:name => "McLovin"})
0
       def find(*arguments)
0
         scope = arguments.slice!(0)
0
         options = arguments.slice!(0) || {}
0
@@ -198,6 +278,15 @@ module ActiveCouch
0
 
0
       # Initializes a new subclass of ActiveCouch::Base and saves in the CouchDB database
0
       # as a new document
0
+ #
0
+ # Example:
0
+ # class Person < ActiveCouch::Base
0
+ # has :name
0
+ # end
0
+ #
0
+ # person = Person.create(:name => "McLovin")
0
+ # person.id.nil? # false
0
+ # person.new? # false
0
       def create(arguments)
0
         unless arguments.is_a?(Hash)
0
           raise ArgumentError, "The arguments must be a Hash"
0
@@ -273,15 +362,38 @@ module ActiveCouch
0
           end
0
         end
0
         
0
+ # First parse the JSON.
0
+ # As per the CouchDB Permanent View API, the result set will be contained
0
+ # within a JSON hash as an array, with the key 'rows'
0
+ # The actual CouchDB object which needs to be initialized is obtained with
0
+ # the key 'value'
0
         def instantiate_collection(result)
0
- # First parse the JSON
0
           hash = JSON.parse(result)
0
- # As per the CouchDB Permanent View API, the result set will be contained
0
- # within a JSON hash as an array, with the key 'rows'
0
- # The actual CouchDB object which needs to be initialized is obtained with
0
- # the key 'value'
0
           hash['rows'].collect { |row| self.new(row['value']) }
0
         end
0
     end # End class methods
0
+
0
+ private
0
+ def from_hash(hash)
0
+ # TODO:
0
+ # - Clean this up. Doesn't look very nice
0
+ # - Raise errors if attribute/association is not present
0
+ hash.each do |k,v|
0
+ k = k.to_sym rescue k
0
+ if v.is_a?(Array) # This means this is a has_many association
0
+ unless (assoc = @associations[k]).nil?
0
+ name, child_klass = assoc.name, assoc.klass
0
+ v.each do |child|
0
+ child.is_a?(Hash) ? child_obj = child_klass.new(child) : child_obj = child
0
+ self.send "add_#{Inflector.singularize(name)}", child_obj
0
+ end
0
+ end
0
+ elsif v.is_a?(Hash) # This means this is a has_one association (which we might add later)
0
+ # Do nothing for now. More later
0
+ else # This means this is a normal attribute
0
+ self.send("#{k}=", v) if @attributes.has_key?(k)
0
+ end
0
+ end
0
+ end
0
   end # End class Base
0
 end # End module ActiveCouch
0
\ No newline at end of file
...
1
2
 
3
4
5
...
47
48
49
 
50
51
...
1
 
2
3
4
5
...
47
48
49
50
51
52
0
@@ -1,5 +1,5 @@
0
 module ActiveCouch
0
-
0
+
0
   String.class_eval do
0
     require 'cgi'
0
     def url_encode
0
@@ -47,4 +47,5 @@ module ActiveCouch
0
       parent_name.empty? ? Object : Inflector.constantize(parent_name)
0
     end
0
   end
0
+
0
 end
0
\ No newline at end of file
...
35
36
37
 
38
39
 
 
 
40
41
42
43
44
45
 
 
 
46
47
48
...
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
0
@@ -35,14 +35,21 @@ describe "ActiveCouch::Base #find method with just simple attributes" do
0
     people.class.should == Array
0
     # Size of people
0
     people.size.should == 1
0
+
0
     people.first.class.should == Person
0
     people.first.name.should == 'McLovin'
0
+ # Check if id and rev are set
0
+ people.first.id.should_not == nil
0
+ people.first.rev.should_not == nil
0
   end
0
 
0
   it "should return one Person object when sent method find with parameter :one" do
0
     person = Person.find(:first, :params => {:name => 'McLovin'})
0
     person.class.should == Person
0
     person.name.should == 'McLovin'
0
+ # Check if id and rev are set
0
+ person.id.should_not == nil
0
+ person.rev.should_not == nil
0
   end
0
 
0
   it "should return an empty array when sent method find with parameter :all and is not able to find any" do
...
9
10
11
12
13
14
15
16
17
18
19
...
35
36
37
38
39
40
41
42
43
44
45
...
9
10
11
 
 
 
 
 
12
13
14
...
30
31
32
 
 
 
 
 
33
34
35
0
@@ -9,11 +9,6 @@ describe "A class which is a subclass of ActiveCouch::Base" do
0
     @p = Person.new
0
   end
0
   
0
- it "should have an instance variable called attributes which is a Hash with the key being :name" do
0
- Person.attributes.class.should == Hash
0
- Person.attributes.keys.should == [:name]
0
- end
0
-
0
   it "should have a method called name which returns the value of the variable name" do
0
     @p.should respond_to(:name)
0
     @p.name.should == ""
0
@@ -35,11 +30,6 @@ describe "A class which is a subclass of ActiveCouch::Base with a default value
0
     @n = NamedPerson.new
0
   end
0
   
0
- it "should have an instance variable called attributes which is a Hash with the key being :name" do
0
- NamedPerson.attributes.class.should == Hash
0
- NamedPerson.attributes.keys.should == [:name]
0
- end
0
-
0
   it "should have a method called name which returns the value of the variable name" do
0
     @n.should respond_to(:name)
0
     @n.name.should == "McLovin"
...
14
15
16
17
18
 
 
 
19
 
20
21
...
14
15
16
 
 
17
18
19
20
21
22
23
0
@@ -14,7 +14,9 @@ describe "An object instantiated from the subclass of ActiveCouch::Base" do
0
     @person.should respond_to(:id=)
0
   end
0
 
0
- it "should have a reader for the rev attribute" do
0
- @person.should respond_to(:rev)
0
+ it "should be able to set and retrieve the id variable" do
0
+ @person.id = 'abc-def'
0
+ @person.id.should == 'abc-def'
0
   end
0
+
0
 end
0
\ No newline at end of file
...
9
10
11
12
 
13
 
14
15
16
...
9
10
11
 
12
13
14
15
16
17
0
@@ -9,7 +9,8 @@ describe "An object instantiated from the subclass of ActiveCouch::Base" do
0
     @person = Person.new
0
   end
0
 
0
- it "should have a reader for the rev attribute" do
0
+ it "should have reader/writer for the rev attribute" do
0
     @person.should respond_to(:rev)
0
+ @person.should respond_to(:rev=)
0
   end
0
 end
0
\ No newline at end of file
...
28
29
30
 
31
32
33
34
 
 
 
 
 
 
 
 
35
36
37
38
39
40
41
42
43
 
 
 
 
 
 
 
44
45
 
 
 
 
 
 
 
 
46
47
...
28
29
30
31
32
33
34
 
35
36
37
38
39
40
41
42
43
44
45
46
47
48
 
 
 
49
50
51
52
53
54
55
56
 
57
58
59
60
61
62
63
64
65
66
0
@@ -28,19 +28,38 @@ end
0
 describe "A new ActiveCouch::Base instance" do
0
   before(:each) do
0
     class Person < ActiveCouch::Base
0
+ site 'http://localhost:5984/'
0
       has :name, :which_is => :text
0
     end
0
     
0
- @person = Person.new
0
+ @person = Person.new(:name => 'Seth')
0
+ # Create a database called people
0
+ ActiveCouch::Migrator.create_database('http://localhost:5984/', 'people')
0
+ end
0
+
0
+ after(:each) do
0
+ # Delete after we're done
0
+ ActiveCouch::Migrator.delete_database('http://localhost:5984/', 'people')
0
   end
0
 
0
   it "should be new" do
0
     @person.should be_new
0
   end
0
 
0
- it "should not be new once it has been saved"
0
-
0
- it "should allow you to set the id attribute"
0
+ it "should set the id and rev attributes after being saved" do
0
+ @person.save
0
+
0
+ @person.id.should_not == nil
0
+ @person.rev.should_not == nil
0
+ @person.should_not be_new
0
+ end
0
 
0
- it "should set the id and rev attributes after being saved"
0
+ it "should allow you to set the id attribute, and the id must be reflected in the object after saving" do
0
+ @person.id = 'abc_def'
0
+ puts @person.to_json
0
+
0
+ @person.save
0
+ @person.id.should == 'abc_def'
0
+ end
0
+
0
 end
0
\ No newline at end of file
...
16
17
18
19
 
 
 
 
 
20
21
22
23
24
 
 
 
 
 
25
26
27
...
46
47
48
49
 
 
 
 
 
 
50
51
52
...
16
17
18
 
19
20
21
22
23
24
25
26
27
 
28
29
30
31
32
33
34
35
...
54
55
56
 
57
58
59
60
61
62
63
64
65
0
@@ -16,12 +16,20 @@ describe "ActiveCouch::Base #to_json method with just simple attributes" do
0
   end
0
 
0
   it "should produce valid JSON output when sent the to_json method" do
0
- @h.to_json.should == '{"name":"Swissotel The Stamford","rooms":100,"star_rating":5.0}'
0
+ json_output = @h.to_json
0
+ # Check for JSON regex, since attributes can appear in any order
0
+ (json_output =~ /"name":"Swissotel The Stamford"/).should_not == nil
0
+ (json_output =~ /"rooms":100/).should_not == nil
0
+ (json_output =~ /"star_rating":5.0/).should_not == nil
0
   end
0
   
0
   it "should produce valid JSON output when an attribute has been changed and the to_json method is sent" do
0
     @h.rooms = 200
0
- @h.to_json.should == '{"name":"Swissotel The Stamford","rooms":200,"star_rating":5.0}'
0
+ json_output = @h.to_json
0
+ # Check for JSON regex, since attributes can appear in any order
0
+ (json_output =~ /"name":"Swissotel The Stamford"/).should_not == nil
0
+ (json_output =~ /"rooms":200/).should_not == nil
0
+ (json_output =~ /"star_rating":5.0/).should_not == nil
0
   end
0
 end
0
 
0
@@ -46,6 +54,11 @@ describe "ActiveCouch::Base #to_json with associations" do
0
   end
0
 
0
   it "should produce valid JSON when sent the to_json method" do
0
- @c.to_json.should == '{"name":"Crazed McLovin","hospitals":[{"name":"Crazy Hospital 1"},{"name":"Crazy Hospital 2"}]}'
0
+ json_output = @c.to_json
0
+ # Check for JSON regex, since attributes can appear in any order
0
+ (json_output =~ /"name":"Crazed McLovin"/).should_not == nil
0
+ (json_output =~ /"hospitals":\[.*?\]/).should_not == nil
0
+ (json_output =~ /\{.*?"name":"Crazy Hospital 1".*?\}/).should_not == nil
0
+ (json_output =~ /\{.*?"name":"Crazy Hospital 2".*?\}/).should_not == nil
0
   end
0
 end
0
\ No newline at end of file

Comments

    No one has commented yet.