activeresource 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activeresource might be problematic. Click here for more details.
- data/CHANGELOG +216 -0
- data/README +165 -0
- data/Rakefile +133 -0
- data/lib/active_resource.rb +47 -0
- data/lib/active_resource/base.rb +872 -0
- data/lib/active_resource/connection.rb +157 -0
- data/lib/active_resource/custom_methods.rb +105 -0
- data/lib/active_resource/formats.rb +14 -0
- data/lib/active_resource/formats/json_format.rb +23 -0
- data/lib/active_resource/formats/xml_format.rb +34 -0
- data/lib/active_resource/http_mock.rb +136 -0
- data/lib/active_resource/validations.rb +288 -0
- data/lib/active_resource/version.rb +9 -0
- data/lib/activeresource.rb +1 -0
- data/test/abstract_unit.rb +10 -0
- data/test/authorization_test.rb +82 -0
- data/test/base/custom_methods_test.rb +96 -0
- data/test/base/equality_test.rb +43 -0
- data/test/base/load_test.rb +111 -0
- data/test/base_errors_test.rb +48 -0
- data/test/base_test.rb +454 -0
- data/test/base_test.rb.rej +17 -0
- data/test/connection_test.rb +161 -0
- data/test/debug.log +5477 -0
- data/test/fixtures/beast.rb +14 -0
- data/test/fixtures/person.rb +3 -0
- data/test/fixtures/street_address.rb +4 -0
- data/test/format_test.rb +42 -0
- data/test/setter_trap.rb +27 -0
- metadata +87 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../abstract_unit"
|
2
|
+
require "fixtures/person"
|
3
|
+
require "fixtures/street_address"
|
4
|
+
|
5
|
+
class BaseEqualityTest < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@new = Person.new
|
8
|
+
@one = Person.new(:id => 1)
|
9
|
+
@two = Person.new(:id => 2)
|
10
|
+
@street = StreetAddress.new(:id => 2)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_should_equal_self
|
14
|
+
assert @new == @new, '@new == @new'
|
15
|
+
assert @one == @one, '@one == @one'
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_shouldnt_equal_new_resource
|
19
|
+
assert @new != @one, '@new != @one'
|
20
|
+
assert @one != @new, '@one != @new'
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_shouldnt_equal_different_class
|
24
|
+
assert @two != @street, 'person != street_address with same id'
|
25
|
+
assert @street != @two, 'street_address != person with same id'
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_eql_should_alias_equals_operator
|
29
|
+
assert_equal @new == @new, @new.eql?(@new)
|
30
|
+
assert_equal @new == @one, @new.eql?(@one)
|
31
|
+
|
32
|
+
assert_equal @one == @one, @one.eql?(@one)
|
33
|
+
assert_equal @one == @new, @one.eql?(@new)
|
34
|
+
|
35
|
+
assert_equal @one == @street, @one.eql?(@street)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_hash_should_be_id_hash
|
39
|
+
[@new, @one, @two, @street].each do |resource|
|
40
|
+
assert_equal resource.id.hash, resource.hash
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../abstract_unit"
|
2
|
+
require "fixtures/person"
|
3
|
+
require "fixtures/street_address"
|
4
|
+
|
5
|
+
module Highrise
|
6
|
+
class Note < ActiveResource::Base
|
7
|
+
self.site = "http://37s.sunrise.i:3000"
|
8
|
+
end
|
9
|
+
|
10
|
+
class Comment < ActiveResource::Base
|
11
|
+
self.site = "http://37s.sunrise.i:3000"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
class BaseLoadTest < Test::Unit::TestCase
|
17
|
+
def setup
|
18
|
+
@matz = { :id => 1, :name => 'Matz' }
|
19
|
+
|
20
|
+
@first_address = { :id => 1, :street => '12345 Street' }
|
21
|
+
@addresses = [@first_address, { :id => 2, :street => '67890 Street' }]
|
22
|
+
@addresses_from_xml = { :street_addresses => @addresses }
|
23
|
+
@addresses_from_xml_single = { :street_addresses => [ @first_address ] }
|
24
|
+
|
25
|
+
@deep = { :id => 1, :street => {
|
26
|
+
:id => 1, :state => { :id => 1, :name => 'Oregon',
|
27
|
+
:notable_rivers => [
|
28
|
+
{ :id => 1, :name => 'Willamette' },
|
29
|
+
{ :id => 2, :name => 'Columbia', :rafted_by => @matz }] }}}
|
30
|
+
|
31
|
+
@person = Person.new
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_load_expects_hash
|
35
|
+
assert_raise(ArgumentError) { @person.load nil }
|
36
|
+
assert_raise(ArgumentError) { @person.load '<person id="1"/>' }
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_load_simple_hash
|
40
|
+
assert_equal Hash.new, @person.attributes
|
41
|
+
assert_equal @matz.stringify_keys, @person.load(@matz).attributes
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_load_one_with_existing_resource
|
45
|
+
address = @person.load(:street_address => @first_address).street_address
|
46
|
+
assert_kind_of StreetAddress, address
|
47
|
+
assert_equal @first_address.stringify_keys, address.attributes
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_load_one_with_unknown_resource
|
51
|
+
address = silence_warnings { @person.load(:address => @first_address).address }
|
52
|
+
assert_kind_of Person::Address, address
|
53
|
+
assert_equal @first_address.stringify_keys, address.attributes
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_load_collection_with_existing_resource
|
57
|
+
addresses = @person.load(@addresses_from_xml).street_addresses
|
58
|
+
assert_kind_of Array, addresses
|
59
|
+
addresses.each { |address| assert_kind_of StreetAddress, address }
|
60
|
+
assert_equal @addresses.map(&:stringify_keys), addresses.map(&:attributes)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_load_collection_with_unknown_resource
|
64
|
+
Person.send!(:remove_const, :Address) if Person.const_defined?(:Address)
|
65
|
+
assert !Person.const_defined?(:Address), "Address shouldn't exist until autocreated"
|
66
|
+
addresses = silence_warnings { @person.load(:addresses => @addresses).addresses }
|
67
|
+
assert Person.const_defined?(:Address), "Address should have been autocreated"
|
68
|
+
addresses.each { |address| assert_kind_of Person::Address, address }
|
69
|
+
assert_equal @addresses.map(&:stringify_keys), addresses.map(&:attributes)
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_load_collection_with_single_existing_resource
|
73
|
+
addresses = @person.load(@addresses_from_xml_single).street_addresses
|
74
|
+
assert_kind_of Array, addresses
|
75
|
+
addresses.each { |address| assert_kind_of StreetAddress, address }
|
76
|
+
assert_equal [ @first_address ].map(&:stringify_keys), addresses.map(&:attributes)
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_load_collection_with_single_unknown_resource
|
80
|
+
Person.send!(:remove_const, :Address) if Person.const_defined?(:Address)
|
81
|
+
assert !Person.const_defined?(:Address), "Address shouldn't exist until autocreated"
|
82
|
+
addresses = silence_warnings { @person.load(:addresses => [ @first_address ]).addresses }
|
83
|
+
assert Person.const_defined?(:Address), "Address should have been autocreated"
|
84
|
+
addresses.each { |address| assert_kind_of Person::Address, address }
|
85
|
+
assert_equal [ @first_address ].map(&:stringify_keys), addresses.map(&:attributes)
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_recursively_loaded_collections
|
89
|
+
person = @person.load(@deep)
|
90
|
+
assert_equal @deep[:id], person.id
|
91
|
+
|
92
|
+
street = person.street
|
93
|
+
assert_kind_of Person::Street, street
|
94
|
+
assert_equal @deep[:street][:id], street.id
|
95
|
+
|
96
|
+
state = street.state
|
97
|
+
assert_kind_of Person::Street::State, state
|
98
|
+
assert_equal @deep[:street][:state][:id], state.id
|
99
|
+
|
100
|
+
rivers = state.notable_rivers
|
101
|
+
assert_kind_of Array, rivers
|
102
|
+
assert_kind_of Person::Street::State::NotableRiver, rivers.first
|
103
|
+
assert_equal @deep[:street][:state][:notable_rivers].first[:id], rivers.first.id
|
104
|
+
assert_equal @matz[:id], rivers.last.rafted_by.id
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_nested_collections_within_the_same_namespace
|
108
|
+
n = Highrise::Note.new(:comments => [{ :name => "1" }])
|
109
|
+
assert_kind_of Highrise::Comment, n.comments.first
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/abstract_unit"
|
2
|
+
require "fixtures/person"
|
3
|
+
|
4
|
+
class BaseErrorsTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
7
|
+
mock.post "/people.xml", {}, "<?xml version=\"1.0\" encoding=\"UTF-8\"?><errors><error>Age can't be blank</error><error>Name can't be blank</error><error>Name must start with a letter</error><error>Person quota full for today.</error></errors>", 422
|
8
|
+
end
|
9
|
+
@person = Person.new(:name => '', :age => '')
|
10
|
+
assert_equal @person.save, false
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_should_mark_as_invalid
|
14
|
+
assert !@person.valid?
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_should_parse_xml_errors
|
18
|
+
assert_kind_of ActiveResource::Errors, @person.errors
|
19
|
+
assert_equal 4, @person.errors.size
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_should_parse_errors_to_individual_attributes
|
23
|
+
assert @person.errors.invalid?(:name)
|
24
|
+
assert_equal "can't be blank", @person.errors.on(:age)
|
25
|
+
assert_equal ["can't be blank", "must start with a letter"], @person.errors[:name]
|
26
|
+
assert_equal "Person quota full for today.", @person.errors.on_base
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_should_iterate_over_errors
|
30
|
+
errors = []
|
31
|
+
@person.errors.each { |attribute, message| errors << [attribute, message] }
|
32
|
+
assert errors.include?(["name", "can't be blank"])
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_should_iterate_over_full_errors
|
36
|
+
errors = []
|
37
|
+
@person.errors.each_full { |message| errors << message }
|
38
|
+
assert errors.include?("Name can't be blank")
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_should_format_full_errors
|
42
|
+
full = @person.errors.full_messages
|
43
|
+
assert full.include?("Age can't be blank")
|
44
|
+
assert full.include?("Name can't be blank")
|
45
|
+
assert full.include?("Name must start with a letter")
|
46
|
+
assert full.include?("Person quota full for today.")
|
47
|
+
end
|
48
|
+
end
|
data/test/base_test.rb
ADDED
@@ -0,0 +1,454 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/abstract_unit"
|
2
|
+
require "fixtures/person"
|
3
|
+
require "fixtures/street_address"
|
4
|
+
require "fixtures/beast"
|
5
|
+
|
6
|
+
class BaseTest < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
@matz = { :id => 1, :name => 'Matz' }.to_xml(:root => 'person')
|
9
|
+
@david = { :id => 2, :name => 'David' }.to_xml(:root => 'person')
|
10
|
+
@addy = { :id => 1, :street => '12345 Street' }.to_xml(:root => 'address')
|
11
|
+
@default_request_headers = { 'Content-Type' => 'application/xml' }
|
12
|
+
@rick = { :name => "Rick", :age => 25 }.to_xml(:root => "person")
|
13
|
+
@people = [{ :id => 1, :name => 'Matz' }, { :id => 2, :name => 'David' }].to_xml(:root => 'people')
|
14
|
+
@people_david = [{ :id => 2, :name => 'David' }].to_xml(:root => 'people')
|
15
|
+
@addresses = [{ :id => 1, :street => '12345 Street' }].to_xml(:root => 'addresses')
|
16
|
+
|
17
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
18
|
+
mock.get "/people/1.xml", {}, @matz
|
19
|
+
mock.get "/people/2.xml", {}, @david
|
20
|
+
mock.get "/people/3.xml", {'key' => 'value'}, nil, 404
|
21
|
+
mock.put "/people/1.xml", {}, nil, 204
|
22
|
+
mock.delete "/people/1.xml", {}, nil, 200
|
23
|
+
mock.delete "/people/2.xml", {}, nil, 400
|
24
|
+
mock.get "/people/99.xml", {}, nil, 404
|
25
|
+
mock.post "/people.xml", {}, @rick, 201, 'Location' => '/people/5.xml'
|
26
|
+
mock.get "/people.xml", {}, @people
|
27
|
+
mock.get "/people/1/addresses.xml", {}, @addresses
|
28
|
+
mock.get "/people/1/addresses/1.xml", {}, @addy
|
29
|
+
mock.get "/people/1/addresses/2.xml", {}, nil, 404
|
30
|
+
mock.get "/people/2/addresses/1.xml", {}, nil, 404
|
31
|
+
mock.put "/people/1/addresses/1.xml", {}, nil, 204
|
32
|
+
mock.delete "/people/1/addresses/1.xml", {}, nil, 200
|
33
|
+
mock.post "/people/1/addresses.xml", {}, nil, 201, 'Location' => '/people/1/addresses/5'
|
34
|
+
mock.get "/people//addresses.xml", {}, nil, 404
|
35
|
+
mock.get "/people//addresses/1.xml", {}, nil, 404
|
36
|
+
mock.put "/people//addresses/1.xml", {}, nil, 404
|
37
|
+
mock.delete "/people//addresses/1.xml", {}, nil, 404
|
38
|
+
mock.post "/people//addresses.xml", {}, nil, 404
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def test_site_accessor_accepts_uri_or_string_argument
|
44
|
+
site = URI.parse('http://localhost')
|
45
|
+
|
46
|
+
assert_nothing_raised { Person.site = 'http://localhost' }
|
47
|
+
assert_equal site, Person.site
|
48
|
+
|
49
|
+
assert_nothing_raised { Person.site = site }
|
50
|
+
assert_equal site, Person.site
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_should_use_site_prefix_and_credentials
|
54
|
+
assert_equal 'http://foo:bar@beast.caboo.se', Forum.site.to_s
|
55
|
+
assert_equal 'http://foo:bar@beast.caboo.se/forums/:forum_id', Topic.site.to_s
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_site_variable_can_be_reset
|
59
|
+
actor = Class.new(ActiveResource::Base)
|
60
|
+
assert_nil actor.site
|
61
|
+
actor.site = 'http://localhost:31337'
|
62
|
+
actor.site = nil
|
63
|
+
assert_nil actor.site
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_site_reader_uses_superclass_site_until_written
|
67
|
+
# Superclass is Object so returns nil.
|
68
|
+
assert_nil ActiveResource::Base.site
|
69
|
+
assert_nil Class.new(ActiveResource::Base).site
|
70
|
+
|
71
|
+
# Subclass uses superclass site.
|
72
|
+
actor = Class.new(Person)
|
73
|
+
assert_equal Person.site, actor.site
|
74
|
+
|
75
|
+
# Subclass returns frozen superclass copy.
|
76
|
+
assert !Person.site.frozen?
|
77
|
+
assert actor.site.frozen?
|
78
|
+
|
79
|
+
# Changing subclass site doesn't change superclass site.
|
80
|
+
actor.site = 'http://localhost:31337'
|
81
|
+
assert_not_equal Person.site, actor.site
|
82
|
+
|
83
|
+
# Changed subclass site is not frozen.
|
84
|
+
assert !actor.site.frozen?
|
85
|
+
|
86
|
+
# Changing superclass site doesn't overwrite subclass site.
|
87
|
+
Person.site = 'http://somewhere.else'
|
88
|
+
assert_not_equal Person.site, actor.site
|
89
|
+
|
90
|
+
# Changing superclass site after subclassing changes subclass site.
|
91
|
+
jester = Class.new(actor)
|
92
|
+
actor.site = 'http://nomad'
|
93
|
+
assert_equal actor.site, jester.site
|
94
|
+
assert jester.site.frozen?
|
95
|
+
|
96
|
+
# Subclasses are always equal to superclass site when not overridden
|
97
|
+
fruit = Class.new(ActiveResource::Base)
|
98
|
+
apple = Class.new(fruit)
|
99
|
+
|
100
|
+
fruit.site = 'http://market'
|
101
|
+
assert_equal fruit.site, apple.site, 'subclass did not adopt changes to parent class'
|
102
|
+
|
103
|
+
fruit.site = 'http://supermarket'
|
104
|
+
assert_equal fruit.site, apple.site, 'subclass did not adopt changes to parent class'
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_updating_baseclass_site_object_wipes_descendent_cached_connection_objects
|
108
|
+
# Subclasses are always equal to superclass site when not overridden
|
109
|
+
fruit = Class.new(ActiveResource::Base)
|
110
|
+
apple = Class.new(fruit)
|
111
|
+
|
112
|
+
fruit.site = 'http://market'
|
113
|
+
assert_equal fruit.connection.site, apple.connection.site
|
114
|
+
|
115
|
+
fruit.site = 'http://supermarket'
|
116
|
+
assert_equal fruit.connection.site, apple.connection.site
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_collection_name
|
120
|
+
assert_equal "people", Person.collection_name
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_collection_path
|
124
|
+
assert_equal '/people.xml', Person.collection_path
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_collection_path_with_parameters
|
128
|
+
assert_equal '/people.xml?gender=male', Person.collection_path(:gender => 'male')
|
129
|
+
assert_equal '/people.xml?gender=false', Person.collection_path(:gender => false)
|
130
|
+
assert_equal '/people.xml?gender=', Person.collection_path(:gender => nil)
|
131
|
+
|
132
|
+
assert_equal '/people.xml?gender=male', Person.collection_path('gender' => 'male')
|
133
|
+
|
134
|
+
# Use includes? because ordering of param hash is not guaranteed
|
135
|
+
assert Person.collection_path(:gender => 'male', :student => true).include?('/people.xml?')
|
136
|
+
assert Person.collection_path(:gender => 'male', :student => true).include?('gender=male')
|
137
|
+
assert Person.collection_path(:gender => 'male', :student => true).include?('student=true')
|
138
|
+
|
139
|
+
assert_equal '/people.xml?name%5B%5D=bob&name%5B%5D=your+uncle%2Bme&name%5B%5D=&name%5B%5D=false', Person.collection_path(:name => ['bob', 'your uncle+me', nil, false])
|
140
|
+
|
141
|
+
assert_equal '/people.xml?struct%5Ba%5D%5B%5D=2&struct%5Ba%5D%5B%5D=1&struct%5Bb%5D=fred', Person.collection_path(:struct => {:a => [2,1], 'b' => 'fred'})
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_custom_element_path
|
145
|
+
assert_equal '/people/1/addresses/1.xml', StreetAddress.element_path(1, :person_id => 1)
|
146
|
+
assert_equal '/people/1/addresses/1.xml', StreetAddress.element_path(1, 'person_id' => 1)
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_custom_element_path_with_parameters
|
150
|
+
assert_equal '/people/1/addresses/1.xml?type=work', StreetAddress.element_path(1, :person_id => 1, :type => 'work')
|
151
|
+
assert_equal '/people/1/addresses/1.xml?type=work', StreetAddress.element_path(1, 'person_id' => 1, :type => 'work')
|
152
|
+
assert_equal '/people/1/addresses/1.xml?type=work', StreetAddress.element_path(1, :type => 'work', :person_id => 1)
|
153
|
+
assert_equal '/people/1/addresses/1.xml?type%5B%5D=work&type%5B%5D=play+time', StreetAddress.element_path(1, :person_id => 1, :type => ['work', 'play time'])
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_custom_element_path_with_prefix_and_parameters
|
157
|
+
assert_equal '/people/1/addresses/1.xml?type=work', StreetAddress.element_path(1, {:person_id => 1}, {:type => 'work'})
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_custom_collection_path
|
161
|
+
assert_equal '/people/1/addresses.xml', StreetAddress.collection_path(:person_id => 1)
|
162
|
+
assert_equal '/people/1/addresses.xml', StreetAddress.collection_path('person_id' => 1)
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_custom_collection_path_with_parameters
|
166
|
+
assert_equal '/people/1/addresses.xml?type=work', StreetAddress.collection_path(:person_id => 1, :type => 'work')
|
167
|
+
assert_equal '/people/1/addresses.xml?type=work', StreetAddress.collection_path('person_id' => 1, :type => 'work')
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_custom_collection_path_with_prefix_and_parameters
|
171
|
+
assert_equal '/people/1/addresses.xml?type=work', StreetAddress.collection_path({:person_id => 1}, {:type => 'work'})
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_custom_element_name
|
175
|
+
assert_equal 'address', StreetAddress.element_name
|
176
|
+
end
|
177
|
+
|
178
|
+
def test_custom_collection_name
|
179
|
+
assert_equal 'addresses', StreetAddress.collection_name
|
180
|
+
end
|
181
|
+
|
182
|
+
def test_prefix
|
183
|
+
assert_equal "/", Person.prefix
|
184
|
+
assert_equal Set.new, Person.send!(:prefix_parameters)
|
185
|
+
end
|
186
|
+
|
187
|
+
def test_set_prefix
|
188
|
+
SetterTrap.rollback_sets(Person) do |person_class|
|
189
|
+
person_class.prefix = "the_prefix"
|
190
|
+
assert_equal "the_prefix", person_class.prefix
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def test_set_prefix_with_inline_keys
|
195
|
+
SetterTrap.rollback_sets(Person) do |person_class|
|
196
|
+
person_class.prefix = "the_prefix:the_param"
|
197
|
+
assert_equal "the_prefixthe_param_value", person_class.prefix(:the_param => "the_param_value")
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_set_prefix_with_default_value
|
202
|
+
SetterTrap.rollback_sets(Person) do |person_class|
|
203
|
+
person_class.set_prefix
|
204
|
+
assert_equal "/", person_class.prefix
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def test_custom_prefix
|
209
|
+
assert_equal '/people//', StreetAddress.prefix
|
210
|
+
assert_equal '/people/1/', StreetAddress.prefix(:person_id => 1)
|
211
|
+
assert_equal [:person_id].to_set, StreetAddress.send!(:prefix_parameters)
|
212
|
+
end
|
213
|
+
|
214
|
+
def test_find_by_id
|
215
|
+
matz = Person.find(1)
|
216
|
+
assert_kind_of Person, matz
|
217
|
+
assert_equal "Matz", matz.name
|
218
|
+
assert matz.name?
|
219
|
+
end
|
220
|
+
|
221
|
+
def test_respond_to
|
222
|
+
matz = Person.find(1)
|
223
|
+
assert matz.respond_to?(:name)
|
224
|
+
assert matz.respond_to?(:name=)
|
225
|
+
assert matz.respond_to?(:name?)
|
226
|
+
assert !matz.respond_to?(:super_scalable_stuff)
|
227
|
+
end
|
228
|
+
|
229
|
+
def test_find_by_id_with_custom_prefix
|
230
|
+
addy = StreetAddress.find(1, :params => { :person_id => 1 })
|
231
|
+
assert_kind_of StreetAddress, addy
|
232
|
+
assert_equal '12345 Street', addy.street
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_find_all
|
236
|
+
all = Person.find(:all)
|
237
|
+
assert_equal 2, all.size
|
238
|
+
assert_kind_of Person, all.first
|
239
|
+
assert_equal "Matz", all.first.name
|
240
|
+
assert_equal "David", all.last.name
|
241
|
+
end
|
242
|
+
|
243
|
+
def test_find_first
|
244
|
+
matz = Person.find(:first)
|
245
|
+
assert_kind_of Person, matz
|
246
|
+
assert_equal "Matz", matz.name
|
247
|
+
end
|
248
|
+
|
249
|
+
def test_custom_header
|
250
|
+
Person.headers['key'] = 'value'
|
251
|
+
assert_raises(ActiveResource::ResourceNotFound) { Person.find(3) }
|
252
|
+
ensure
|
253
|
+
Person.headers.delete('key')
|
254
|
+
end
|
255
|
+
|
256
|
+
def test_find_by_id_not_found
|
257
|
+
assert_raises(ActiveResource::ResourceNotFound) { Person.find(99) }
|
258
|
+
assert_raises(ActiveResource::ResourceNotFound) { StreetAddress.find(1) }
|
259
|
+
end
|
260
|
+
|
261
|
+
def test_find_all_by_from
|
262
|
+
ActiveResource::HttpMock.respond_to { |m| m.get "/companies/1/people.xml", {}, @people_david }
|
263
|
+
|
264
|
+
people = Person.find(:all, :from => "/companies/1/people.xml")
|
265
|
+
assert_equal 1, people.size
|
266
|
+
assert_equal "David", people.first.name
|
267
|
+
end
|
268
|
+
|
269
|
+
def test_find_all_by_from_with_options
|
270
|
+
ActiveResource::HttpMock.respond_to { |m| m.get "/companies/1/people.xml", {}, @people_david }
|
271
|
+
|
272
|
+
people = Person.find(:all, :from => "/companies/1/people.xml")
|
273
|
+
assert_equal 1, people.size
|
274
|
+
assert_equal "David", people.first.name
|
275
|
+
end
|
276
|
+
|
277
|
+
def test_find_all_by_symbol_from
|
278
|
+
ActiveResource::HttpMock.respond_to { |m| m.get "/people/managers.xml", {}, @people_david }
|
279
|
+
|
280
|
+
people = Person.find(:all, :from => :managers)
|
281
|
+
assert_equal 1, people.size
|
282
|
+
assert_equal "David", people.first.name
|
283
|
+
end
|
284
|
+
|
285
|
+
def test_find_single_by_from
|
286
|
+
ActiveResource::HttpMock.respond_to { |m| m.get "/companies/1/manager.xml", {}, @david }
|
287
|
+
|
288
|
+
david = Person.find(:one, :from => "/companies/1/manager.xml")
|
289
|
+
assert_equal "David", david.name
|
290
|
+
end
|
291
|
+
|
292
|
+
def test_find_single_by_symbol_from
|
293
|
+
ActiveResource::HttpMock.respond_to { |m| m.get "/people/leader.xml", {}, @david }
|
294
|
+
|
295
|
+
david = Person.find(:one, :from => :leader)
|
296
|
+
assert_equal "David", david.name
|
297
|
+
end
|
298
|
+
|
299
|
+
def test_save
|
300
|
+
rick = Person.new
|
301
|
+
assert_equal true, rick.save
|
302
|
+
assert_equal '5', rick.id
|
303
|
+
end
|
304
|
+
|
305
|
+
def test_id_from_response
|
306
|
+
p = Person.new
|
307
|
+
resp = {'Location' => '/foo/bar/1'}
|
308
|
+
assert_equal '1', p.send!(:id_from_response, resp)
|
309
|
+
|
310
|
+
resp['Location'] << '.xml'
|
311
|
+
assert_equal '1', p.send!(:id_from_response, resp)
|
312
|
+
end
|
313
|
+
|
314
|
+
def test_create_with_custom_prefix
|
315
|
+
matzs_house = StreetAddress.new(:person_id => 1)
|
316
|
+
matzs_house.save
|
317
|
+
assert_equal '5', matzs_house.id
|
318
|
+
end
|
319
|
+
|
320
|
+
# Test that loading a resource preserves its prefix_options.
|
321
|
+
def test_load_preserves_prefix_options
|
322
|
+
address = StreetAddress.find(1, :params => { :person_id => 1 })
|
323
|
+
ryan = Person.new(:id => 1, :name => 'Ryan', :address => address)
|
324
|
+
assert_equal address.prefix_options, ryan.address.prefix_options
|
325
|
+
end
|
326
|
+
|
327
|
+
def test_reload_works_with_prefix_options
|
328
|
+
address = StreetAddress.find(1, :params => { :person_id => 1 })
|
329
|
+
assert_equal address, address.reload
|
330
|
+
end
|
331
|
+
|
332
|
+
def test_reload_works_without_prefix_options
|
333
|
+
person = Person.find(:first)
|
334
|
+
assert_equal person, person.reload
|
335
|
+
end
|
336
|
+
|
337
|
+
|
338
|
+
def test_create
|
339
|
+
rick = Person.create(:name => 'Rick')
|
340
|
+
assert rick.valid?
|
341
|
+
assert !rick.new?
|
342
|
+
assert_equal '5', rick.id
|
343
|
+
|
344
|
+
# test additional attribute returned on create
|
345
|
+
assert_equal 25, rick.age
|
346
|
+
|
347
|
+
# Test that save exceptions get bubbled up too
|
348
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
349
|
+
mock.post "/people.xml", {}, nil, 409
|
350
|
+
end
|
351
|
+
assert_raises(ActiveResource::ResourceConflict) { Person.create(:name => 'Rick') }
|
352
|
+
end
|
353
|
+
|
354
|
+
def test_update
|
355
|
+
matz = Person.find(:first)
|
356
|
+
matz.name = "David"
|
357
|
+
assert_kind_of Person, matz
|
358
|
+
assert_equal "David", matz.name
|
359
|
+
assert_equal true, matz.save
|
360
|
+
end
|
361
|
+
|
362
|
+
def test_update_with_custom_prefix_with_specific_id
|
363
|
+
addy = StreetAddress.find(1, :params => { :person_id => 1 })
|
364
|
+
addy.street = "54321 Street"
|
365
|
+
assert_kind_of StreetAddress, addy
|
366
|
+
assert_equal "54321 Street", addy.street
|
367
|
+
addy.save
|
368
|
+
end
|
369
|
+
|
370
|
+
def test_update_with_custom_prefix_without_specific_id
|
371
|
+
addy = StreetAddress.find(:first, :params => { :person_id => 1 })
|
372
|
+
addy.street = "54321 Lane"
|
373
|
+
assert_kind_of StreetAddress, addy
|
374
|
+
assert_equal "54321 Lane", addy.street
|
375
|
+
addy.save
|
376
|
+
end
|
377
|
+
|
378
|
+
def test_update_conflict
|
379
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
380
|
+
mock.get "/people/2.xml", {}, @david
|
381
|
+
mock.put "/people/2.xml", @default_request_headers, nil, 409
|
382
|
+
end
|
383
|
+
assert_raises(ActiveResource::ResourceConflict) { Person.find(2).save }
|
384
|
+
end
|
385
|
+
|
386
|
+
def test_destroy
|
387
|
+
assert Person.find(1).destroy
|
388
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
389
|
+
mock.get "/people/1.xml", {}, nil, 404
|
390
|
+
end
|
391
|
+
assert_raises(ActiveResource::ResourceNotFound) { Person.find(1).destroy }
|
392
|
+
end
|
393
|
+
|
394
|
+
def test_destroy_with_custom_prefix
|
395
|
+
assert StreetAddress.find(1, :params => { :person_id => 1 }).destroy
|
396
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
397
|
+
mock.get "/people/1/addresses/1.xml", {}, nil, 404
|
398
|
+
end
|
399
|
+
assert_raises(ActiveResource::ResourceNotFound) { StreetAddress.find(1, :params => { :person_id => 1 }) }
|
400
|
+
end
|
401
|
+
|
402
|
+
def test_delete
|
403
|
+
assert Person.delete(1)
|
404
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
405
|
+
mock.get "/people/1.xml", {}, nil, 404
|
406
|
+
end
|
407
|
+
assert_raises(ActiveResource::ResourceNotFound) { Person.find(1) }
|
408
|
+
end
|
409
|
+
|
410
|
+
def test_delete_with_custom_prefix
|
411
|
+
assert StreetAddress.delete(1, :person_id => 1)
|
412
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
413
|
+
mock.get "/people/1/addresses/1.xml", {}, nil, 404
|
414
|
+
end
|
415
|
+
assert_raises(ActiveResource::ResourceNotFound) { StreetAddress.find(1, :params => { :person_id => 1 }) }
|
416
|
+
end
|
417
|
+
|
418
|
+
def test_exists
|
419
|
+
# Class method.
|
420
|
+
assert !Person.exists?(nil)
|
421
|
+
assert Person.exists?(1)
|
422
|
+
assert !Person.exists?(99)
|
423
|
+
|
424
|
+
# Instance method.
|
425
|
+
assert !Person.new.exists?
|
426
|
+
assert Person.find(1).exists?
|
427
|
+
assert !Person.new(:id => 99).exists?
|
428
|
+
|
429
|
+
# Nested class method.
|
430
|
+
assert StreetAddress.exists?(1, :params => { :person_id => 1 })
|
431
|
+
assert !StreetAddress.exists?(1, :params => { :person_id => 2 })
|
432
|
+
assert !StreetAddress.exists?(2, :params => { :person_id => 1 })
|
433
|
+
|
434
|
+
# Nested instance method.
|
435
|
+
assert StreetAddress.find(1, :params => { :person_id => 1 }).exists?
|
436
|
+
assert !StreetAddress.new({:id => 1, :person_id => 2}).exists?
|
437
|
+
assert !StreetAddress.new({:id => 2, :person_id => 1}).exists?
|
438
|
+
end
|
439
|
+
|
440
|
+
def test_to_xml
|
441
|
+
matz = Person.find(1)
|
442
|
+
xml = matz.to_xml
|
443
|
+
assert xml.starts_with?('<?xml version="1.0" encoding="UTF-8"?>')
|
444
|
+
assert xml.include?('<name>Matz</name>')
|
445
|
+
assert xml.include?('<id type="integer">1</id>')
|
446
|
+
end
|
447
|
+
|
448
|
+
def test_to_param_quacks_like_active_record
|
449
|
+
new_person = Person.new
|
450
|
+
assert_nil new_person.to_param
|
451
|
+
matz = Person.find(1)
|
452
|
+
assert_equal '1', matz.to_param
|
453
|
+
end
|
454
|
+
end
|