resource_full 0.7.6

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.
Files changed (35) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +100 -0
  3. data/Rakefile +19 -0
  4. data/lib/resource_full/base.rb +140 -0
  5. data/lib/resource_full/controllers/resources.rb +16 -0
  6. data/lib/resource_full/controllers/resources_controller.rb +26 -0
  7. data/lib/resource_full/controllers/routes_controller.rb +16 -0
  8. data/lib/resource_full/core_extensions/api.rb +26 -0
  9. data/lib/resource_full/core_extensions/exception.rb +25 -0
  10. data/lib/resource_full/core_extensions/from_json.rb +13 -0
  11. data/lib/resource_full/core_extensions/module.rb +13 -0
  12. data/lib/resource_full/dispatch.rb +196 -0
  13. data/lib/resource_full/models/resourced_route.rb +84 -0
  14. data/lib/resource_full/query.rb +337 -0
  15. data/lib/resource_full/render/html.rb +74 -0
  16. data/lib/resource_full/render/json.rb +107 -0
  17. data/lib/resource_full/render/xml.rb +106 -0
  18. data/lib/resource_full/render.rb +63 -0
  19. data/lib/resource_full/retrieve.rb +87 -0
  20. data/lib/resource_full/version.rb +9 -0
  21. data/lib/resource_full.rb +31 -0
  22. data/spec/resource_full/base_spec.rb +88 -0
  23. data/spec/resource_full/controllers/resources_spec.rb +30 -0
  24. data/spec/resource_full/dispatch_spec.rb +274 -0
  25. data/spec/resource_full/models/resourced_route_spec.rb +62 -0
  26. data/spec/resource_full/query/parameter_spec.rb +61 -0
  27. data/spec/resource_full/query_spec.rb +462 -0
  28. data/spec/resource_full/render/html_spec.rb +4 -0
  29. data/spec/resource_full/render/json_spec.rb +258 -0
  30. data/spec/resource_full/render/xml_spec.rb +378 -0
  31. data/spec/resource_full/render_spec.rb +5 -0
  32. data/spec/resource_full/retrieve_spec.rb +184 -0
  33. data/spec/spec.opts +4 -0
  34. data/spec/spec_helper.rb +134 -0
  35. metadata +156 -0
@@ -0,0 +1,63 @@
1
+ module ResourceFull
2
+ module Render
3
+ include ResourceFull::Render::HTML
4
+ include ResourceFull::Render::JSON
5
+ include ResourceFull::Render::XML
6
+
7
+ def self.included(controller)
8
+ controller.rescue_from Exception, :with => :handle_generic_exception_with_correct_response_format
9
+ end
10
+
11
+ private
12
+
13
+ CONFLICT_MESSAGE = if defined?(ActiveRecord::Errors)
14
+ if ([Rails::VERSION::MAJOR, Rails::VERSION::MINOR] <=> [2,1]) >= 0 # if the rails version is 2.1 or greater...Í
15
+ (I18n.translate 'activerecord.errors.messages')[:taken]
16
+ else
17
+ ActiveRecord::Errors.default_error_messages[:taken]
18
+ end
19
+ else
20
+ "has already been taken"
21
+ end
22
+
23
+ def status_for(errors)
24
+ if errors.any? { |message| message.include? CONFLICT_MESSAGE }
25
+ :conflict
26
+ else :unprocessable_entity end
27
+ end
28
+
29
+ def handle_generic_exception_with_correct_response_format(exception)
30
+ if request.format.xml?
31
+ if defined?(ExceptionNotifiable) && defined?(ExceptionNotifier) && self.is_a?(ExceptionNotifiable) && !(consider_all_requests_local || local_request?)
32
+ deliverer = self.class.exception_data
33
+ data = case deliverer
34
+ when nil then {}
35
+ when Symbol then send(deliverer)
36
+ when Proc then deliverer.call(self)
37
+ end
38
+
39
+ ExceptionNotifier.deliver_exception_notification(exception, self,
40
+ request, data)
41
+ end
42
+ logger.error exception.message + "\n" + exception.clean_backtrace.collect {|s| "\t#{s}\n"}.join
43
+ render :xml => exception.to_xml, :status => :server_error
44
+ elsif request.format.json?
45
+ if defined?(ExceptionNotifiable) && defined?(ExceptionNotifier) && self.is_a?(ExceptionNotifiable) && !(consider_all_requests_local || local_request?)
46
+ deliverer = self.class.exception_data
47
+ data = case deliverer
48
+ when nil then {}
49
+ when Symbol then send(deliverer)
50
+ when Proc then deliverer.call(self)
51
+ end
52
+
53
+ ExceptionNotifier.deliver_exception_notification(exception, self,
54
+ request, data)
55
+ end
56
+ logger.error exception.message + "\n" + exception.clean_backtrace.collect {|s| "\t#{s}\n"}.join
57
+ render :json => exception.to_json, :status => :server_error
58
+ else
59
+ raise exception
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,87 @@
1
+ module ResourceFull
2
+ module Retrieve
3
+ class << self
4
+ def included(base)
5
+ super(base)
6
+ # Define new_person, update_person, etc.
7
+ base.before_filter :move_queryable_params_into_model_params_on_create, :only => [:create]
8
+ end
9
+ end
10
+
11
+ protected
12
+
13
+ def find_model_object
14
+ # TODO I am not sure what the correct behavior should be here, but I'm artifically
15
+ # generating the exception in order to avoid altering the render methods for the time being.
16
+ returning(model_class.find(:first, :conditions => { resource_identifier => params[:id] })) do |o|
17
+ raise ActiveRecord::RecordNotFound, "Couldn't find #{model_class} with #{resource_identifier}=#{params[:id]}" if o.nil?
18
+ end
19
+ end
20
+
21
+ def new_model_object
22
+ model_class.new
23
+ end
24
+
25
+ def edit_model_object
26
+ find_model_object
27
+ end
28
+
29
+ # Decorate the method with this - so that even if the user has overridden this method, it will get decorated within a transaction!
30
+ [:create, :update, :destroy].each do |action|
31
+ send(:define_method, "transactional_#{action}_model_object") do
32
+ result = nil
33
+ ActiveRecord::Base.transaction do
34
+ result = send("#{action}_#{model_name}")
35
+ raise ActiveRecord::Rollback unless result.errors.empty?
36
+ end
37
+ result
38
+ end
39
+ end
40
+
41
+ def update_model_object
42
+ object = find_model_object
43
+ object.update_attributes(params[model_name])
44
+ object
45
+ end
46
+
47
+ def create_model_object
48
+ model_class.create(params[model_name])
49
+ end
50
+
51
+ def destroy_model_object
52
+ object = find_model_object
53
+ object.destroy
54
+ object
55
+ end
56
+
57
+ def find_all_model_objects
58
+ completed_query.find(:all)
59
+ end
60
+
61
+ def count_all_model_objects
62
+ completed_query.count
63
+ end
64
+
65
+ def move_queryable_params_into_model_params_on_create
66
+ params.except(model_name).each do |param_name, value|
67
+ if self.class.queryable_params.collect(&:name).include?(param_name.to_sym)
68
+ params[model_name][param_name] = params.delete(param_name)
69
+ end
70
+ end
71
+ end
72
+
73
+ private
74
+
75
+ def completed_query
76
+ self.class.queryable_params.inject(model_class) do |finder, queryer|
77
+ queryer.find finder, params
78
+ end
79
+ end
80
+
81
+ def resource_identifier
82
+ returning(self.class.resource_identifier) do |column|
83
+ return column.call(params[:id]) if column.is_a?(Proc)
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,9 @@
1
+ module ResourceFull #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 7
5
+ TINY = 6
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,31 @@
1
+ # Dependencies
2
+ require 'active_record'
3
+ require 'action_controller'
4
+ require 'action_pack'
5
+
6
+ # Extensions
7
+ Dir[File.dirname(__FILE__) + "/resource_full/core_extensions/*.rb"].each do |extension|
8
+ require extension
9
+ end
10
+
11
+ # Core library
12
+ require File.dirname(__FILE__) + '/resource_full/dispatch'
13
+ require File.dirname(__FILE__) + '/resource_full/query'
14
+
15
+ require File.dirname(__FILE__) + '/resource_full/render/html'
16
+ require File.dirname(__FILE__) + '/resource_full/render/json'
17
+ require File.dirname(__FILE__) + '/resource_full/render/xml'
18
+
19
+ require File.dirname(__FILE__) + '/resource_full/render'
20
+ require File.dirname(__FILE__) + '/resource_full/retrieve'
21
+ require File.dirname(__FILE__) + '/resource_full/version'
22
+ require File.dirname(__FILE__) + '/resource_full/base'
23
+
24
+ # REST API
25
+ require File.dirname(__FILE__) + '/resource_full/models/resourced_route.rb'
26
+ require File.dirname(__FILE__) + '/resource_full/controllers/resources_controller'
27
+ require File.dirname(__FILE__) + '/resource_full/controllers/routes_controller'
28
+
29
+ if ActiveRecord::VERSION::STRING >= '2.1.0' && !ActiveRecord::Base.include_root_in_json
30
+ puts "WARNING: Please set ActiveRecord::Base.include_root_in_json = true to enable ResourceFull's JSON support."
31
+ end
@@ -0,0 +1,88 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe ResourceFull::Base, :type => :controller do
4
+ controller_name "resource_full_mocks"
5
+
6
+ it "infers the name of its resource model from its class name" do
7
+ controller.model_name.should == "resource_full_mock"
8
+ end
9
+
10
+ it "infers the class of its resource model from its class name" do
11
+ controller.model_class.should == ResourceFullMock
12
+ end
13
+
14
+ class ResourceFullFake; end
15
+
16
+ it "exposes a particular resource model given a symbol" do
17
+ controller.class.exposes :resource_full_fake
18
+ controller.model_class.should == ResourceFullFake
19
+ controller.class.exposes :resource_full_mock # cleanup
20
+ end
21
+
22
+ it "exposes a particular resource model given a pluralized symbol" do
23
+ controller.class.exposes :resource_full_fakes
24
+ controller.model_class.should == ResourceFullFake
25
+ controller.class.exposes :resource_full_mock # cleanup
26
+ end
27
+
28
+ it "exposes a particular resource model given a class" do
29
+ controller.class.exposes ResourceFullFake
30
+ controller.model_class.should == ResourceFullFake
31
+ controller.class.exposes ResourceFullMock # cleanup
32
+ end
33
+
34
+ it "renders two formats by default" do
35
+ controller.class.allowed_formats.should include(:xml, :html)
36
+ end
37
+
38
+ it "allows you to specify what formats to render" do
39
+ controller.class.responds_to :xml, :json
40
+ controller.class.allowed_formats.should include(:xml, :json)
41
+ controller.class.allowed_formats.should_not include(:html)
42
+ end
43
+
44
+ class NonResourcesController < ActionController::Base; end
45
+ class ResourcesController < ResourceFull::Base; end
46
+
47
+ it "knows about all controller subclasses of itself" do
48
+ ActionController::Routing.expects(:possible_controllers).at_least_once.returns %w{resources non_resources}
49
+ ResourceFull::Base.all_resources.should include(ResourcesController)
50
+ ResourceFull::Base.all_resources.should_not include(NonResourcesController)
51
+ end
52
+
53
+ it "serializes the notion of a resource controller as XML" do
54
+ ResourceFullMockUsersController.clear_queryable_params!
55
+ ResourceFullMockUsersController.queryable_with :first_name
56
+ xml = Hash.from_xml(ResourceFullMockUsersController.to_xml)
57
+ xml["resource"]["name"].should == "resource_full_mock_users"
58
+ xml["resource"]["parameters"].first["name"].should == "first_name"
59
+ end
60
+
61
+ it "has a default value of :id for the resource identifier column" do
62
+ ResourceFullMockUsersController.resource_identifier.should == :id
63
+ end
64
+
65
+ it "allows you to set the resource_identifier field" do
66
+ controller.class.identified_by :first_name
67
+ controller.class.resource_identifier.should == :first_name
68
+ controller.class.resource_identifier = :id # cleanup
69
+ end
70
+
71
+ it "is paginatable by default" do
72
+ controller.class.should be_paginatable
73
+ end
74
+
75
+ it "translates a model name into a controller constant" do
76
+ ResourceFull::Base.controller_for("resource_full_mock_users").should == ResourceFullMockUsersController
77
+ end
78
+
79
+ it "raises ResourceNotFound if it cannot constantize the requested controller" do
80
+ lambda do
81
+ ResourceFull::Base.controller_for("nonsense")
82
+ end.should raise_error(ResourceFull::ResourceNotFound, "not found: nonsense")
83
+ end
84
+
85
+ it "returns the controller it's been given if it receives a Class object" do
86
+ ResourceFull::Base.controller_for(ResourceFullMockUsersController).should == ResourceFullMockUsersController
87
+ end
88
+ end
@@ -0,0 +1,30 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ module ResourceFull
4
+ module Controllers
5
+ describe ResourcesController, :type => :controller do
6
+ it "finds all resources" do
7
+ get :index, :format => 'xml'
8
+
9
+ response.should have_tag('resources>resource') do
10
+ with_tag('name', 'resource_full_mock_users')
11
+ with_tag('name', 'resource_full_mock_addresses')
12
+ end
13
+ end
14
+
15
+ it "finds a specific resource" do
16
+ get :show, :format => 'xml', :id => 'resource_full_mock_users'
17
+
18
+ response.should have_tag('resource>name', 'resource_full_mock_users')
19
+ response.should_not have_tag('resource>name', 'resource_full_mock_addresses')
20
+ end
21
+
22
+ it "returns a 404 response when the requested resource is not found" do
23
+ get :show, :format => 'xml', :id => 'foo'
24
+
25
+ response.body.should have_tag("errors") { with_tag("error", "not found: foo") }
26
+ response.code.should == '404'
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,274 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe "ResourceFull::Dispatch", :type => :controller do
4
+ controller_name "resource_full_mocks"
5
+
6
+ before(:each) do
7
+ ResourceFullMock.stubs(:find).with(:all).returns([stub(:id => 1, :to_xml => "")])
8
+ end
9
+
10
+ it "exposes a method for skipping format and method protection"
11
+
12
+ describe "based on request format" do
13
+ controller_name "resource_full_mocks"
14
+
15
+ after :each do
16
+ controller.class.responds_to :defaults
17
+ end
18
+
19
+ it "dispatches to index_xml render method if xml is requested" do
20
+ controller.expects(:index_xml)
21
+ get :index, :format => 'xml'
22
+ end
23
+
24
+ it "dispatches to index_json render method if json is requested" do
25
+ controller.expects(:index_json)
26
+ get :index, :format => 'json'
27
+ end
28
+
29
+ it "dispatches to index_html render method if html is requested" do
30
+ controller.expects(:index_html)
31
+ controller.stubs(:render)
32
+ get :index, :format => 'html'
33
+ end
34
+
35
+ it "raises a 406 error if it does not respond to a format for which no methods are included" do
36
+ get :index, :format => 'txt'
37
+ response.code.should == '406'
38
+ end
39
+
40
+ it "raises a 406 error if it does not respond to a format which has been explicitly removed" do
41
+ controller.class.responds_to :xml
42
+ get :index, :format => 'html'
43
+ response.code.should == '406'
44
+ end
45
+
46
+ it "includes an appropriate error message if it does not respond to a format which has been explicitly removed" do
47
+ controller.class.responds_to :xml
48
+ get :index, :format => 'html'
49
+ response.body.should =~ /Resource does not have a representation in text\/html format/
50
+ end
51
+ end
52
+
53
+ describe "based on request action" do
54
+ controller_name "resource_full_mocks"
55
+
56
+ after :each do
57
+ controller.class.responds_to :defaults
58
+ end
59
+
60
+ it "claims to respond to create, read, update, delete, and count by default" do
61
+ controller.class.responds_to :defaults
62
+ controller.class.allowed_methods.should include(:create, :read, :update, :delete)
63
+ end
64
+
65
+ it "lists all the standard Rails methods plus count as its possible actions" do
66
+ controller.class.possible_actions.should include(:create, :new, :show, :index, :count, :update, :edit, :destroy)
67
+ end
68
+
69
+ it "claims to not respond to any methods for an unsupported format" do
70
+ controller.class.responds_to :xml
71
+ controller.class.allowed_methods(:html).should be_empty
72
+ end
73
+
74
+ it "claims to respond to default methods for a requested format if no explicit methods are given" do
75
+ controller.class.responds_to :xml
76
+ controller.class.allowed_methods(:xml).should include(:create, :read, :update, :delete)
77
+ end
78
+
79
+ it "claims to respond to only methods given a single value with the :only option" do
80
+ controller.class.responds_to :xml, :only => :read
81
+ controller.class.allowed_methods(:xml).should == [:read]
82
+ end
83
+
84
+ it "claims to respond to only methods given multiple values with the :only option" do
85
+ controller.class.responds_to :xml, :only => [:read, :delete]
86
+ controller.class.allowed_methods(:xml).should == [:read, :delete]
87
+ end
88
+
89
+ it "responds successfully to supported methods" do
90
+ controller.class.responds_to :xml, :only => :read
91
+ get :index, :format => "xml"
92
+ response.should be_success
93
+ end
94
+
95
+ it "disallows unsupported methods with code 405" do
96
+ controller.class.responds_to :html, :only => :read
97
+ controller.stubs(:destroy)
98
+ delete :destroy, :id => 1
99
+ response.code.should == '405'
100
+ response.body.should =~ /Resource does not allow destroy action/
101
+ end
102
+
103
+ it "ignores and does not verify custom methods" do
104
+ controller.class.responds_to :xml, :only => [:delete]
105
+
106
+ get :foo, :format => 'xml'
107
+ response.body.should have_tag("foo", "bar")
108
+ response.code.should == '200'
109
+ end
110
+
111
+ it "allows you to specify the appropriate CRUD semantics of a custom method"
112
+ end
113
+
114
+ describe "GET index" do
115
+ controller_name "resource_full_mocks"
116
+
117
+ before :each do
118
+ controller.stubs(:render)
119
+ end
120
+
121
+ it "sets an @mocks instance variable based on the default finder" do
122
+ ResourceFullMock.stubs(:find).returns "a list of mocks"
123
+ get :index, :format => 'html'
124
+ assigns(:resource_full_mocks).should == "a list of mocks"
125
+ end
126
+
127
+ it "sets an @mocks instance variable appropriately if the default finder is overridden" do
128
+ begin
129
+ controller.class.class_eval do
130
+ def find_all_resource_full_mocks; "another list of mocks"; end
131
+ end
132
+ get :index, :format => 'html'
133
+ assigns(:resource_full_mocks).should == "another list of mocks"
134
+ ensure
135
+ controller.class.class_eval do
136
+ undef :find_all_resource_full_mocks
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ describe "GET count" do
143
+ controller_name "resource_full_mocks"
144
+
145
+ before :each do
146
+ controller.stubs(:render)
147
+ end
148
+
149
+ it "should render the count" do
150
+ ResourceFullMock.stubs(:count).returns(12)
151
+ get :count, :format => 'html'
152
+ response.body.should == ["", []]
153
+ end
154
+ end
155
+
156
+ describe "GET show" do
157
+ controller_name "resource_full_mocks"
158
+
159
+ before :each do
160
+ controller.stubs(:render)
161
+ end
162
+
163
+ it "sets a @mock instance variable based on the default finder" do
164
+ ResourceFullMock.stubs(:find).returns "a mock"
165
+ get :show, :id => 1, :format => 'html'
166
+ assigns(:resource_full_mock).should == "a mock"
167
+ end
168
+
169
+ it "sets a @mock instance variable appropriately if the default finder is overridden" do
170
+ controller.class.class_eval do
171
+ def find_resource_full_mock; "another mock"; end
172
+ end
173
+ get :show, :id => 1, :format => 'html'
174
+ assigns(:resource_full_mock).should == "another mock"
175
+ end
176
+ end
177
+
178
+ describe "POST create" do
179
+ controller_name "resource_full_mocks"
180
+
181
+ before :each do
182
+ controller.stubs :render
183
+ end
184
+
185
+ it "sets a @mock instance variable based on the default creator" do
186
+ ResourceFullMock.stubs(:create).returns stub(:errors => stub_everything, :id => :mock)
187
+ post :create, :format => 'html'
188
+ assigns(:resource_full_mock).id.should == :mock
189
+ end
190
+
191
+ it "sets a @mock instance variable appropriately if the default creator is overridden" do
192
+ ResourceFullMock.stubs(:super_create).returns stub(:errors => stub_everything, :id => :super_mock)
193
+ controller.class.class_eval do
194
+ def create_resource_full_mock; ResourceFullMock.super_create; end
195
+ end
196
+ post :create, :format => 'html'
197
+ assigns(:resource_full_mock).id.should == :super_mock
198
+ end
199
+ end
200
+
201
+ describe "PUT update" do
202
+ controller_name "resource_full_mocks"
203
+
204
+ before :each do
205
+ controller.stubs :render
206
+ end
207
+
208
+ it "sets a @mock instance variable based on the default updater" do
209
+ ResourceFullMock.stubs(:find).returns stub(:id => 1, :update_attributes => true, :errors => stub_everything)
210
+ put :update, :id => 1, :format => 'html'
211
+ assigns(:resource_full_mock).id.should == 1
212
+ end
213
+
214
+ it "sets a @mock instance variable appropriately if the default updater is overridden" do
215
+ ResourceFullMock.stubs(:super_update).returns stub(:errors => stub_everything, :id => :super_mock)
216
+ controller.class.class_eval do
217
+ def update_resource_full_mock; ResourceFullMock.super_update; end
218
+ end
219
+ put :update, :id => 1, :format => 'html'
220
+ assigns(:resource_full_mock).id.should == :super_mock
221
+ end
222
+ end
223
+
224
+ describe "when the user agent is IE7" do
225
+ before :each do
226
+ request.env["HTTP_USER_AGENT"] = "MSIE 7.0"
227
+ controller.stubs(:find_all_resource_full_mocks).returns([])
228
+ end
229
+
230
+ it "should set the request format to json when the incoming request format looks like json" do
231
+ get :index, :format => 'json-test'
232
+ response.content_type.should == "application/json"
233
+ end
234
+
235
+ it "should set the request format to json when the incoming request format looks like javascript" do
236
+ get :index, :format => 'javascript-test'
237
+ response.content_type.should == "application/json"
238
+ end
239
+
240
+ it "should set the request format to json when the incoming request uri looks like json" do
241
+ request.env["REQUEST_URI"] = "/resource_full_mocks.json?foo=bar"
242
+ get :index
243
+ response.content_type.should == "application/json"
244
+ end
245
+
246
+ it "should set the request format to xml when the incoming request format looks like xml" do
247
+ get :index, :format => 'xml-test'
248
+ response.content_type.should == "application/xml"
249
+ end
250
+
251
+ it "should set the request format to json when the incoming request uri looks like xml" do
252
+ request.env["REQUEST_URI"] = "/resource_full_mocks.xml?foo=bar"
253
+ get :index
254
+ response.content_type.should == "application/xml"
255
+ end
256
+
257
+ # Dirk assures me that the following functionality is necessary due to the way Rails handles IE7
258
+ # request formats, or perhaps the way IE7 sends its request content-type.
259
+ # TODO Find a better criterion than 'else, use text/html'.
260
+ it "should default the request format to text/html when the incoming request uri is not supported" do
261
+ controller.stubs :render
262
+ request.env["REQUEST_URI"] = "/resource_full_mocks.png"
263
+ get :index
264
+ response.content_type.should == "text/html"
265
+ end
266
+
267
+ # See above.
268
+ it "should default the request format to text/html when the incoming request format is not supported" do
269
+ controller.stubs :render
270
+ get :index, :format => "image/png"
271
+ response.content_type.should == "text/html"
272
+ end
273
+ end
274
+ end
@@ -0,0 +1,62 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ module ResourceFull
4
+ module Models
5
+ describe ResourcedRoute do
6
+ it "has a verb, name, pattern, and action" do
7
+ ResourcedRoute.new(:controller => "resource_full_mock_users", :verb => "GET").verb.should == "GET"
8
+ ResourcedRoute.new(:controller => "resource_full_mock_users", :name => "users").name.should == "users"
9
+ ResourcedRoute.new(:controller => "resource_full_mock_users", :pattern => "/users").pattern.should == "/users"
10
+ ResourcedRoute.new(:controller => "resource_full_mock_users", :action => "index").action.should == "index"
11
+ end
12
+
13
+ it "has an associated controller derived from the given string" do
14
+ ResourcedRoute.new(:controller => "resource_full_mock_users").controller.should == ResourceFullMockUsersController
15
+ end
16
+
17
+ it "has an associated controller derived from the given class" do
18
+ ResourcedRoute.new(:controller => ResourceFullMockUsersController).controller.should == ResourceFullMockUsersController
19
+ end
20
+
21
+ it "should know if it's a formatted route" do
22
+ ResourcedRoute.new(:controller => "resource_full_mock_users", :name => "formatted_resource_full_mock_users").should be_formatted
23
+ end
24
+
25
+ class DumbController < ActionController::Base; end
26
+
27
+ it "should know if it's a resourced route" do
28
+ ResourcedRoute.new(:controller => DumbController).should_not be_resourced
29
+ end
30
+
31
+ it "should know how to look up its resource" do
32
+ ResourcedRoute.new(:controller => ResourceFullMockUsersController).resource.should == "resource_full_mock_users"
33
+ end
34
+
35
+ describe "query" do
36
+ it "raises an exception when it can't find a particular route" do
37
+ lambda do
38
+ ResourcedRoute.find("this route does not exist")
39
+ end.should raise_error(ResourceFull::Models::RouteNotFound)
40
+ end
41
+
42
+ it "locates a particular named route" do
43
+ route = ResourcedRoute.find :resource_full_mock_users
44
+ route.pattern.should =~ /\/resource_full_mock_users/
45
+ route.verb.should == "GET"
46
+ route.action.should == "index"
47
+ route.controller.should == ResourceFullMockUsersController
48
+ end
49
+
50
+ it "locates all named routes" do
51
+ ResourcedRoute.find(:all).collect(&:name).should include(:resource_full_mock_users, :new_resource_full_mock_user, :resource_full_mock_addresses)
52
+ end
53
+
54
+ it "should filter by a particular resource" do
55
+ route_names = ResourcedRoute.find(:all, :resource_id => "resource_full_mock_users").collect(&:name)
56
+ route_names.should include(:resource_full_mock_users)
57
+ route_names.should_not include(:resource_full_mock_addresses)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end