restrack 1.4.3 → 1.5.0
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/lib/restrack/resource_controller.rb +10 -103
- data/lib/restrack/resource_relations.rb +92 -0
- data/lib/restrack/resource_request.rb +22 -65
- data/lib/restrack/response.rb +119 -0
- data/lib/restrack/support.rb +5 -6
- data/lib/restrack/version.rb +1 -1
- data/lib/restrack/web_service.rb +3 -64
- data/test/sample_app_1/controllers/errors_controller.rb +2 -2
- data/test/sample_app_1/test/test_errors.rb +29 -21
- data/test/sample_app_1/test/test_formats.rb +5 -5
- data/test/sample_app_1/test/test_resource_request.rb +11 -11
- data/test/sample_app_2/test/test_resource_request.rb +1 -1
- data/test/test_web_service.rb +5 -3
- metadata +4 -2
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'restrack/resource_relations'
|
2
|
+
|
1
3
|
module RESTRack
|
2
4
|
|
3
5
|
# All RESTRack controllers should descend from ResourceController. This class
|
@@ -9,6 +11,8 @@ module RESTRack
|
|
9
11
|
#
|
10
12
|
|
11
13
|
class ResourceController
|
14
|
+
extend RESTRack::ResourceRelations
|
15
|
+
|
12
16
|
attr_reader :action, :id, :params
|
13
17
|
class << self; attr_accessor :key_type; end
|
14
18
|
|
@@ -41,110 +45,13 @@ module RESTRack
|
|
41
45
|
# all internal methods are protected rather than private so that calling methods *could* be overriden if necessary.
|
42
46
|
protected
|
43
47
|
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
# This method also will accept any simple data structure when not worried about AR integration.
|
50
|
-
def package_errors(errors)
|
51
|
-
if errors.is_a? Array and errors.count{|e| e.is_a? String} === errors.length
|
52
|
-
# I am AR bound
|
53
|
-
errors = ARFormattedError.new(errors)
|
54
|
-
end
|
55
|
-
@output = @resource_request.package(errors)
|
56
|
-
@output
|
57
|
-
end
|
58
|
-
|
48
|
+
# This returns a datastructure which will automatically be converted by RESTRack
|
49
|
+
# into the error format expected by ActiveResource. ActiveResource expects
|
50
|
+
# attribute input errors to be responded to with a status code of 422, which
|
51
|
+
# is a non-standard HTTP code. Use this to produce the required format of
|
52
|
+
# "<errors><error>...</error><error>...</error></errors>" for the response XML.
|
59
53
|
def package_error(error)
|
60
|
-
|
61
|
-
package_errors(errors)
|
62
|
-
end
|
63
|
-
|
64
|
-
# This method allows one to access a related resource, without providing a direct link to specific relation(s).
|
65
|
-
def self.pass_through_to(entity, opts = {})
|
66
|
-
entity_name = opts[:as] || entity
|
67
|
-
define_method( entity_name.to_sym,
|
68
|
-
Proc.new do |calling_id| # The calling resource's id will come along for the ride when the new bridging method is called magically from ResourceController#call
|
69
|
-
@resource_request.call_controller(entity)
|
70
|
-
end
|
71
|
-
)
|
72
|
-
end
|
73
|
-
|
74
|
-
# This method defines that there is a single link to a member from an entity collection.
|
75
|
-
# The second parameter is an options hash to support setting the local name of the relation via ':as => :foo'.
|
76
|
-
# The third parameter to the method is a Proc which accepts the calling entity's id and returns the id of the relation to which we're establishing the link.
|
77
|
-
# This adds an accessor instance method whose name is the entity's class.
|
78
|
-
def self.has_relationship_to(entity, opts = {}, &get_entity_id_from_relation_id)
|
79
|
-
entity_name = opts[:as] || entity
|
80
|
-
define_method( entity_name.to_sym,
|
81
|
-
Proc.new do |calling_id| # The calling resource's id will come along for the ride when the new bridging method is called magically from ResourceController#call
|
82
|
-
id = get_entity_id_from_relation_id.call(@id)
|
83
|
-
@resource_request.url_chain.unshift(id)
|
84
|
-
@resource_request.call_controller(entity)
|
85
|
-
end
|
86
|
-
)
|
87
|
-
end
|
88
|
-
|
89
|
-
# This method defines that there are multiple links to members from an entity collection (an array of entity identifiers).
|
90
|
-
# This adds an accessor instance method whose name is the entity's class.
|
91
|
-
def self.has_relationships_to(entity, opts = {}, &get_entity_id_from_relation_id)
|
92
|
-
entity_name = opts[:as] || entity
|
93
|
-
define_method( entity_name.to_sym,
|
94
|
-
Proc.new do |calling_id| # The parent resource's id will come along for the ride when the new bridging method is called magically from ResourceController#call
|
95
|
-
entity_array = get_entity_id_from_relation_id.call(@id)
|
96
|
-
begin
|
97
|
-
index = @resource_request.url_chain.shift.to_i
|
98
|
-
rescue
|
99
|
-
raise HTTP400BadRequest, 'You requested an item by index and the index was not a valid number.'
|
100
|
-
end
|
101
|
-
unless index < entity_array.length
|
102
|
-
raise HTTP404ResourceNotFound, 'You requested an item by index and the index was larger than this item\'s list of relations\' length.'
|
103
|
-
end
|
104
|
-
id = entity_array[index]
|
105
|
-
@resource_request.url_chain.unshift(id)
|
106
|
-
@resource_request.call_controller(entity)
|
107
|
-
end
|
108
|
-
)
|
109
|
-
end
|
110
|
-
|
111
|
-
# This method defines that there are multiple links to members from an entity collection (an array of entity identifiers).
|
112
|
-
# This adds an accessor instance method whose name is the entity's class.
|
113
|
-
def self.has_defined_relationships_to(entity, opts = {}, &get_entity_id_from_relation_id)
|
114
|
-
entity_name = opts[:as] || entity
|
115
|
-
define_method( entity_name.to_sym,
|
116
|
-
Proc.new do |calling_id| # The parent resource's id will come along for the ride when the new bridging method is called magically from ResourceController#call
|
117
|
-
entity_array = get_entity_id_from_relation_id.call(@id)
|
118
|
-
id = @resource_request.url_chain.shift
|
119
|
-
raise HTTP400BadRequest, 'No ID provided for has_defined_relationships_to routing.' if id.nil?
|
120
|
-
id = RESTRack.controller_class_for(entity).format_string_id(id) if id.is_a? String
|
121
|
-
unless entity_array.include?( id )
|
122
|
-
raise HTTP404ResourceNotFound, 'Relation entity does not belong to referring resource.'
|
123
|
-
end
|
124
|
-
@resource_request.url_chain.unshift(id)
|
125
|
-
@resource_request.call_controller(entity)
|
126
|
-
end
|
127
|
-
)
|
128
|
-
end
|
129
|
-
|
130
|
-
# This method defines that there are mapped links to members from an entity collection (a hash of entity identifiers).
|
131
|
-
# This adds an accessor instance method whose name is the entity's class.
|
132
|
-
def self.has_mapped_relationships_to(entity, opts = {}, &get_entity_id_from_relation_id)
|
133
|
-
entity_name = opts[:as] || entity
|
134
|
-
define_method( entity_name.to_sym,
|
135
|
-
Proc.new do |calling_id| # The parent resource's id will come along for the ride when the new bridging method is called magically from ResourceController#call
|
136
|
-
entity_map = get_entity_id_from_relation_id.call(@id)
|
137
|
-
key = @resource_request.url_chain.shift
|
138
|
-
id = entity_map[key.to_sym]
|
139
|
-
@resource_request.url_chain.unshift(id)
|
140
|
-
@resource_request.call_controller(entity)
|
141
|
-
end
|
142
|
-
)
|
143
|
-
end
|
144
|
-
|
145
|
-
# Allows decendent controllers to set a data type for the id other than the default.
|
146
|
-
def self.keyed_with_type(klass)
|
147
|
-
self.key_type = klass
|
54
|
+
ARFormattedError.new(error)
|
148
55
|
end
|
149
56
|
|
150
57
|
# Find the action, and id if relevant, that the controller must call.
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module RESTRack
|
2
|
+
# To extend relationship definition methods to RESTRack::ResourceController
|
3
|
+
module ResourceRelations
|
4
|
+
|
5
|
+
# This method allows one to access a related resource, without providing a direct link to specific relation(s).
|
6
|
+
def pass_through_to(entity, opts = {})
|
7
|
+
entity_name = opts[:as] || entity
|
8
|
+
define_method( entity_name.to_sym,
|
9
|
+
Proc.new do |calling_id| # The calling resource's id will come along for the ride when the new bridging method is called magically from ResourceController#call
|
10
|
+
@resource_request.call_controller(entity)
|
11
|
+
end
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
# This method defines that there is a single link to a member from an entity collection.
|
16
|
+
# The second parameter is an options hash to support setting the local name of the relation via ':as => :foo'.
|
17
|
+
# The third parameter to the method is a Proc which accepts the calling entity's id and returns the id of the relation to which we're establishing the link.
|
18
|
+
# This adds an accessor instance method whose name is the entity's class.
|
19
|
+
def has_relationship_to(entity, opts = {}, &get_entity_id_from_relation_id)
|
20
|
+
entity_name = opts[:as] || entity
|
21
|
+
define_method( entity_name.to_sym,
|
22
|
+
Proc.new do |calling_id| # The calling resource's id will come along for the ride when the new bridging method is called magically from ResourceController#call
|
23
|
+
id = get_entity_id_from_relation_id.call(@id)
|
24
|
+
@resource_request.url_chain.unshift(id)
|
25
|
+
@resource_request.call_controller(entity)
|
26
|
+
end
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
# This method defines that there are multiple links to members from an entity collection (an array of entity identifiers).
|
31
|
+
# This adds an accessor instance method whose name is the entity's class.
|
32
|
+
def has_relationships_to(entity, opts = {}, &get_entity_id_from_relation_id)
|
33
|
+
entity_name = opts[:as] || entity
|
34
|
+
define_method( entity_name.to_sym,
|
35
|
+
Proc.new do |calling_id| # The parent resource's id will come along for the ride when the new bridging method is called magically from ResourceController#call
|
36
|
+
entity_array = get_entity_id_from_relation_id.call(@id)
|
37
|
+
begin
|
38
|
+
index = @resource_request.url_chain.shift.to_i
|
39
|
+
rescue
|
40
|
+
raise HTTP400BadRequest, 'You requested an item by index and the index was not a valid number.'
|
41
|
+
end
|
42
|
+
unless index < entity_array.length
|
43
|
+
raise HTTP404ResourceNotFound, 'You requested an item by index and the index was larger than this item\'s list of relations\' length.'
|
44
|
+
end
|
45
|
+
id = entity_array[index]
|
46
|
+
@resource_request.url_chain.unshift(id)
|
47
|
+
@resource_request.call_controller(entity)
|
48
|
+
end
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
# This method defines that there are multiple links to members from an entity collection (an array of entity identifiers).
|
53
|
+
# This adds an accessor instance method whose name is the entity's class.
|
54
|
+
def has_defined_relationships_to(entity, opts = {}, &get_entity_id_from_relation_id)
|
55
|
+
entity_name = opts[:as] || entity
|
56
|
+
define_method( entity_name.to_sym,
|
57
|
+
Proc.new do |calling_id| # The parent resource's id will come along for the ride when the new bridging method is called magically from ResourceController#call
|
58
|
+
entity_array = get_entity_id_from_relation_id.call(@id)
|
59
|
+
id = @resource_request.url_chain.shift
|
60
|
+
raise HTTP400BadRequest, 'No ID provided for has_defined_relationships_to routing.' if id.nil?
|
61
|
+
id = RESTRack.controller_class_for(entity).format_string_id(id) if id.is_a? String
|
62
|
+
unless entity_array.include?( id )
|
63
|
+
raise HTTP404ResourceNotFound, 'Relation entity does not belong to referring resource.'
|
64
|
+
end
|
65
|
+
@resource_request.url_chain.unshift(id)
|
66
|
+
@resource_request.call_controller(entity)
|
67
|
+
end
|
68
|
+
)
|
69
|
+
end
|
70
|
+
|
71
|
+
# This method defines that there are mapped links to members from an entity collection (a hash of entity identifiers).
|
72
|
+
# This adds an accessor instance method whose name is the entity's class.
|
73
|
+
def has_mapped_relationships_to(entity, opts = {}, &get_entity_id_from_relation_id)
|
74
|
+
entity_name = opts[:as] || entity
|
75
|
+
define_method( entity_name.to_sym,
|
76
|
+
Proc.new do |calling_id| # The parent resource's id will come along for the ride when the new bridging method is called magically from ResourceController#call
|
77
|
+
entity_map = get_entity_id_from_relation_id.call(@id)
|
78
|
+
key = @resource_request.url_chain.shift
|
79
|
+
id = entity_map[key.to_sym]
|
80
|
+
@resource_request.url_chain.unshift(id)
|
81
|
+
@resource_request.call_controller(entity)
|
82
|
+
end
|
83
|
+
)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Allows decendent controllers to set a data type for the id other than the default.
|
87
|
+
def keyed_with_type(klass)
|
88
|
+
self.key_type = klass
|
89
|
+
end
|
90
|
+
|
91
|
+
end # module ResourceController
|
92
|
+
end # module RESTRack
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module RESTRack
|
2
2
|
# The ResourceRequest class handles all incoming requests.
|
3
3
|
class ResourceRequest
|
4
|
-
attr_reader :request, :request_id, :params, :post_params, :get_params
|
4
|
+
attr_reader :request, :request_id, :params, :post_params, :get_params, :active_controller
|
5
5
|
attr_accessor :mime_type, :url_chain
|
6
6
|
|
7
7
|
# Initialize the ResourceRequest by assigning a request_id and determining the path, format, and controller of the resource.
|
@@ -13,12 +13,24 @@ module RESTRack
|
|
13
13
|
RESTRack.request_log.info "{#{@request_id}} #{@request.request_method} #{@request.path_info} requested from #{@request.ip}"
|
14
14
|
end
|
15
15
|
|
16
|
-
def fulfill
|
17
|
-
self.prepare
|
18
|
-
return self.response
|
19
|
-
end
|
20
|
-
|
21
16
|
def prepare
|
17
|
+
# MIME type should be determined before raising any exceptions for proper error reporting
|
18
|
+
# Set up the initial routing.
|
19
|
+
@url_chain = @request.path_info.split('/')
|
20
|
+
@url_chain.shift if @url_chain[0] == ''
|
21
|
+
# Pull extension from URL
|
22
|
+
extension = ''
|
23
|
+
unless @url_chain[-1].nil?
|
24
|
+
@url_chain[-1] = @url_chain[-1].sub(/\.([^.]*)$/) do |s|
|
25
|
+
extension = $1.downcase
|
26
|
+
'' # Return an empty string as the substitution so that the extension is removed from `@url_chain[-1]`
|
27
|
+
end
|
28
|
+
end
|
29
|
+
# Determine MIME type from extension
|
30
|
+
@mime_type = get_mime_type_from( extension )
|
31
|
+
|
32
|
+
raise HTTP400BadRequest, "Request path of #{@request.path_info} is invalid" if @request.path_info.include?('//')
|
33
|
+
|
22
34
|
# Pull input data from POST body
|
23
35
|
@post_params = parse_body( @request )
|
24
36
|
@get_params = parse_query_string( @request )
|
@@ -30,20 +42,7 @@ module RESTRack
|
|
30
42
|
@params = @get_params
|
31
43
|
end
|
32
44
|
RESTRack.log.debug 'combined params: ' + @params.inspect
|
33
|
-
|
34
|
-
raise HTTP400BadRequest if @request.path_info.include?('//')
|
35
|
-
@url_chain = @request.path_info.split('/')
|
36
|
-
@url_chain.shift if @url_chain[0] == ''
|
37
|
-
# Pull extension from URL
|
38
|
-
extension = ''
|
39
|
-
unless @url_chain[-1].nil?
|
40
|
-
@url_chain[-1] = @url_chain[-1].sub(/\.([^.]*)$/) do |s|
|
41
|
-
extension = $1.downcase
|
42
|
-
'' # Return an empty string as the substitution so that the extension is removed from `@url_chain[-1]`
|
43
|
-
end
|
44
|
-
end
|
45
|
-
# Determine MIME type from extension
|
46
|
-
@mime_type = get_mime_type_from( extension )
|
45
|
+
|
47
46
|
# Pull first controller from URL
|
48
47
|
@active_resource_name = @url_chain.shift
|
49
48
|
unless @active_resource_name.nil? or RESTRack.controller_exists?(@active_resource_name)
|
@@ -58,12 +57,6 @@ module RESTRack
|
|
58
57
|
@active_controller = instantiate_controller( @active_resource_name )
|
59
58
|
end
|
60
59
|
|
61
|
-
# Send out the typed resource's output.
|
62
|
-
def response
|
63
|
-
RESTRack.log.debug "{#{@request_id}} Retrieving Output"
|
64
|
-
package( @active_controller.call )
|
65
|
-
end
|
66
|
-
|
67
60
|
# Call the next entity in the path stack.
|
68
61
|
# Method called by controller relationship methods.
|
69
62
|
def call_controller(resource_name)
|
@@ -76,28 +69,6 @@ module RESTRack
|
|
76
69
|
@mime_type.to_s
|
77
70
|
end
|
78
71
|
|
79
|
-
# This handles outputing properly formatted content based on the file extension in the URL.
|
80
|
-
def package(data)
|
81
|
-
if @mime_type.like?( RESTRack.mime_type_for( :JSON ) )
|
82
|
-
@output = data.to_json
|
83
|
-
elsif @mime_type.like?( RESTRack.mime_type_for( :XML ) )
|
84
|
-
if File.exists? builder_file
|
85
|
-
@output = builder_up(data)
|
86
|
-
elsif data.respond_to?(:to_xml)
|
87
|
-
@output = data.to_xml
|
88
|
-
else
|
89
|
-
@output = XmlSimple.xml_out(data, 'AttrPrefix' => true, 'XmlDeclaration' => true, 'NoIndent' => true)
|
90
|
-
end
|
91
|
-
elsif @mime_type.like?(RESTRack.mime_type_for( :YAML ) )
|
92
|
-
@output = YAML.dump(data)
|
93
|
-
elsif @mime_type.like?(RESTRack.mime_type_for( :TEXT ) )
|
94
|
-
@output = data.to_s
|
95
|
-
else
|
96
|
-
@output = data
|
97
|
-
end
|
98
|
-
return @output
|
99
|
-
end
|
100
|
-
|
101
72
|
private
|
102
73
|
def get_request_id
|
103
74
|
t = Time.now
|
@@ -151,11 +122,11 @@ module RESTRack
|
|
151
122
|
|
152
123
|
# Determine the MIME type of the request from the extension provided.
|
153
124
|
def get_mime_type_from(extension)
|
154
|
-
unless extension
|
125
|
+
unless extension.blank?
|
155
126
|
mime_type = RESTRack.mime_type_for( extension )
|
156
127
|
end
|
157
|
-
if mime_type.
|
158
|
-
|
128
|
+
if mime_type.blank?
|
129
|
+
unless RESTRack::CONFIG[:DEFAULT_FORMAT].blank?
|
159
130
|
mime_type = RESTRack.mime_type_for( RESTRack::CONFIG[:DEFAULT_FORMAT].to_s.downcase )
|
160
131
|
else
|
161
132
|
mime_type = RESTRack.mime_type_for( :JSON )
|
@@ -174,19 +145,5 @@ module RESTRack
|
|
174
145
|
end
|
175
146
|
end
|
176
147
|
|
177
|
-
# Use Builder to generate the XML.
|
178
|
-
def builder_up(data)
|
179
|
-
buffer = ''
|
180
|
-
xml = Builder::XmlMarkup.new(:target => buffer)
|
181
|
-
xml.instruct!
|
182
|
-
eval( File.new( builder_file ).read )
|
183
|
-
return buffer
|
184
|
-
end
|
185
|
-
|
186
|
-
# Builds the path to the builder file for the current controller action.
|
187
|
-
def builder_file
|
188
|
-
"#{RESTRack::CONFIG[:ROOT]}/views/#{@active_resource_name}/#{@active_controller.action}.xml.builder"
|
189
|
-
end
|
190
|
-
|
191
148
|
end # class ResourceRequest
|
192
149
|
end # module RESTRack
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module RESTRack
|
2
|
+
class Response
|
3
|
+
attr_reader :status, :content_type, :body, :mime_type
|
4
|
+
|
5
|
+
def initialize(request)
|
6
|
+
@request = request
|
7
|
+
begin
|
8
|
+
@request.prepare
|
9
|
+
RESTRack.log.debug "{#{@request.request_id}} Retrieving Output"
|
10
|
+
@body = @request.active_controller.call
|
11
|
+
@status = body.blank? ? 200 : 204
|
12
|
+
RESTRack.log.debug "(#{@request.request_id}) HTTP200OK '#{@request.mime_type.to_s}' response data:\n" + @body.inspect
|
13
|
+
RESTRack.request_log.info "(#{@request.request_id}) HTTP200OK"
|
14
|
+
rescue Exception => exception
|
15
|
+
# This will log the returned status code
|
16
|
+
if @request && @request.request_id
|
17
|
+
RESTRack.request_log.info "(#{@request.request_id}) #{exception.class.to_s} " + exception.message
|
18
|
+
else
|
19
|
+
RESTRack.request_log.info "(<nil-reqid>) #{exception.class.to_s} " + exception.message
|
20
|
+
end
|
21
|
+
case
|
22
|
+
when exception.is_a?( HTTP400BadRequest )
|
23
|
+
@status = 400
|
24
|
+
@body = exception.message || 'The request cannot be fulfilled due to bad syntax.'
|
25
|
+
when exception.is_a?( HTTP401Unauthorized )
|
26
|
+
@status = 401
|
27
|
+
@body = exception.message || 'You have failed authentication for access to the resource.'
|
28
|
+
when exception.is_a?( HTTP403Forbidden )
|
29
|
+
@status = 403
|
30
|
+
@body = exception.message || 'You are forbidden to access that resource.'
|
31
|
+
when exception.is_a?( HTTP404ResourceNotFound )
|
32
|
+
@status = 404
|
33
|
+
@body = exception.message || 'The resource you requested could not be found.'
|
34
|
+
when exception.is_a?( HTTP405MethodNotAllowed )
|
35
|
+
@status = 405
|
36
|
+
@body = exception.message || 'The resource you requested does not support the request method provided.'
|
37
|
+
when exception.is_a?( HTTP409Conflict )
|
38
|
+
@status = 409
|
39
|
+
@body = exception.message || 'The resource you requested is in a conflicted state.'
|
40
|
+
when exception.is_a?( HTTP410Gone )
|
41
|
+
@status = 410
|
42
|
+
@body = exception.message || 'The resource you requested is no longer available.'
|
43
|
+
when exception.is_a?( HTTP422ResourceInvalid )
|
44
|
+
@status = 422
|
45
|
+
@body = exception.message || 'Invalid attribute values sent for resource.'
|
46
|
+
when exception.is_a?( HTTP502BadGateway )
|
47
|
+
@status = 502
|
48
|
+
@body = exception.message || 'The server was acting as a gateway or proxy and received an invalid response from the upstream server.'
|
49
|
+
else # HTTP500ServerError
|
50
|
+
server_error(exception)
|
51
|
+
end # case Exception
|
52
|
+
end # begin / rescue
|
53
|
+
@mime_type = MIME::Type.new(@request.mime_type)
|
54
|
+
@content_type = @request.content_type
|
55
|
+
end
|
56
|
+
|
57
|
+
def output
|
58
|
+
return [status, {'Content-Type' => content_type}, [package(body)] ]
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
def log_server_error(exception)
|
63
|
+
if @request && @request.request_id
|
64
|
+
RESTRack.log.error "(#{@request.request_id}) #{exception.class.to_s} " + exception.message + "\n" + exception.backtrace.join("\n")
|
65
|
+
else
|
66
|
+
RESTRack.log.error "(<nil-reqid>) #{exception.class.to_s} " + exception.message + "\n" + exception.backtrace.join("\n")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def server_error(exception)
|
71
|
+
log_server_error(exception)
|
72
|
+
msg = ''
|
73
|
+
if RESTRack::CONFIG[:SHOW_STACK]
|
74
|
+
msg = (exception.message == exception.class.to_s) ? exception.backtrace.join("\n") : exception.message + "\nstack trace:\n" + exception.backtrace.join("\n")
|
75
|
+
else
|
76
|
+
msg = exception.message
|
77
|
+
end
|
78
|
+
@status = 500
|
79
|
+
@body = msg || 'Server Error.'
|
80
|
+
end
|
81
|
+
|
82
|
+
# This handles outputing properly formatted content based on the file extension in the URL.
|
83
|
+
def package(data)
|
84
|
+
if mime_type.like?( RESTRack.mime_type_for( :JSON ) )
|
85
|
+
output = data.to_json
|
86
|
+
elsif mime_type.like?( RESTRack.mime_type_for( :XML ) )
|
87
|
+
if File.exists? builder_file
|
88
|
+
output = builder_up(data)
|
89
|
+
elsif data.respond_to?(:to_xml)
|
90
|
+
output = data.to_xml
|
91
|
+
else
|
92
|
+
output = XmlSimple.xml_out(data, 'AttrPrefix' => true, 'XmlDeclaration' => true, 'NoIndent' => true)
|
93
|
+
end
|
94
|
+
elsif mime_type.like?(RESTRack.mime_type_for( :YAML ) )
|
95
|
+
output = YAML.dump(data)
|
96
|
+
elsif mime_type.like?(RESTRack.mime_type_for( :TEXT ) )
|
97
|
+
output = data.to_s
|
98
|
+
else
|
99
|
+
output = data
|
100
|
+
end
|
101
|
+
return output
|
102
|
+
end # def package
|
103
|
+
|
104
|
+
# Use Builder to generate the XML.
|
105
|
+
def builder_up(data)
|
106
|
+
buffer = ''
|
107
|
+
xml = Builder::XmlMarkup.new(:target => buffer)
|
108
|
+
xml.instruct!
|
109
|
+
eval( File.new( builder_file ).read )
|
110
|
+
return buffer
|
111
|
+
end
|
112
|
+
|
113
|
+
# Builds the path to the builder file for the current controller action.
|
114
|
+
def builder_file
|
115
|
+
"#{RESTRack::CONFIG[:ROOT]}/views/#{@active_resource_name}/#{@request.active_controller.action}.xml.builder"
|
116
|
+
end
|
117
|
+
|
118
|
+
end # class Response
|
119
|
+
end # module RESTRack
|
data/lib/restrack/support.rb
CHANGED
@@ -59,14 +59,13 @@ class Object
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
-
class ARFormattedError <
|
62
|
+
class ARFormattedError < String
|
63
63
|
# provide this method, as if it is present it will be used to render the xml rather than XmlSimple
|
64
64
|
def to_xml
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
str << "</errors>"
|
65
|
+
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><errors><error>#{self}</error></errors>"
|
66
|
+
end
|
67
|
+
def to_json
|
68
|
+
"{\"errors\": [{\"error\": \"#{self}\"}]}"
|
70
69
|
end
|
71
70
|
end
|
72
71
|
|
data/lib/restrack/version.rb
CHANGED
data/lib/restrack/web_service.rb
CHANGED
@@ -8,71 +8,10 @@ module RESTRack
|
|
8
8
|
|
9
9
|
# Handle requests in the Rack way.
|
10
10
|
def call( env )
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
response = resource_request.fulfill
|
15
|
-
return valid resource_request, response
|
16
|
-
rescue Exception => exception
|
17
|
-
return caught resource_request, exception
|
18
|
-
end
|
11
|
+
resource_request = RESTRack::ResourceRequest.new( :request => Rack::Request.new(env) )
|
12
|
+
response = RESTRack::Response.new(resource_request)
|
13
|
+
return response.output
|
19
14
|
end # method call
|
20
15
|
|
21
|
-
private
|
22
|
-
|
23
|
-
# Return HTTP200OK SUCCESS
|
24
|
-
def valid( resource_request, response )
|
25
|
-
RESTRack.log.debug "(#{resource_request.request_id}) HTTP200OK '#{resource_request.mime_type.to_s}' response data:\n" + response.to_s unless not response.respond_to?( :to_s )
|
26
|
-
RESTRack.request_log.info "(#{resource_request.request_id}) HTTP200OK"
|
27
|
-
return [200, {'Content-Type' => resource_request.content_type}, [response] ]
|
28
|
-
end
|
29
|
-
|
30
|
-
# Return appropriate response code and messages per raised exception type.
|
31
|
-
def caught( resource_request, exception )
|
32
|
-
# This will log the returned status code
|
33
|
-
if resource_request && resource_request.request_id
|
34
|
-
RESTRack.request_log.info "(#{resource_request.request_id}) #{exception.class.to_s} " + exception.message
|
35
|
-
else
|
36
|
-
RESTRack.request_log.info "(<nil-reqid>) #{exception.class.to_s} " + exception.message
|
37
|
-
end
|
38
|
-
case
|
39
|
-
when exception.is_a?( HTTP400BadRequest )
|
40
|
-
return [400, {'Content-Type' => 'text/plain'}, [exception.message || "The request cannot be fulfilled due to bad syntax."] ]
|
41
|
-
when exception.is_a?( HTTP401Unauthorized )
|
42
|
-
return [401, {'Content-Type' => 'text/plain'}, [exception.message || "You have failed authentication for access to the resource."] ]
|
43
|
-
when exception.is_a?( HTTP403Forbidden )
|
44
|
-
return [403, {'Content-Type' => 'text/plain'}, [exception.message || "You are forbidden to access that resource."] ]
|
45
|
-
when exception.is_a?( HTTP404ResourceNotFound )
|
46
|
-
return [404, {'Content-Type' => 'text/plain'}, [exception.message || "The resource you requested could not be found."] ]
|
47
|
-
when exception.is_a?( HTTP405MethodNotAllowed )
|
48
|
-
return [405, {'Content-Type' => 'text/plain'}, [exception.message || "The resource you requested does not support the request method provided."] ]
|
49
|
-
when exception.is_a?( HTTP409Conflict )
|
50
|
-
return [409, {'Content-Type' => 'text/plain'}, [exception.message || "The resource you requested is in a conflicted state."] ]
|
51
|
-
when exception.is_a?( HTTP410Gone )
|
52
|
-
return [410, {'Content-Type' => 'text/plain'}, [exception.message || "The resource you requested is no longer available."] ]
|
53
|
-
when exception.is_a?( HTTP422ResourceInvalid )
|
54
|
-
return [422, {'Content-Type' => 'text/plain'}, [exception.message || "Invalid attribute values sent for resource."] ]
|
55
|
-
when exception.is_a?( HTTP502BadGateway )
|
56
|
-
return [502, {'Content-Type' => 'text/plain'}, [exception.message || "The server was acting as a gateway or proxy and received an invalid response from the upstream server."] ]
|
57
|
-
else # HTTP500ServerError
|
58
|
-
log_server_error( resource_request, exception )
|
59
|
-
msg = ''
|
60
|
-
if RESTRack::CONFIG[:SHOW_STACK]
|
61
|
-
msg = (exception.message == exception.class.to_s) ? exception.backtrace.join("\n") : exception.message + "\nstack trace:\n" + exception.backtrace.join("\n")
|
62
|
-
else
|
63
|
-
msg = exception.message
|
64
|
-
end
|
65
|
-
return [500, {'Content-Type' => 'text/plain'}, [msg] ]
|
66
|
-
end # case Exception
|
67
|
-
end # method caught
|
68
|
-
|
69
|
-
def log_server_error( resource_request, exception )
|
70
|
-
if resource_request && resource_request.request_id
|
71
|
-
RESTRack.log.error "(#{resource_request.request_id}) #{exception.class.to_s} " + exception.message + "\n" + exception.backtrace.join("\n")
|
72
|
-
else
|
73
|
-
RESTRack.log.error "(<nil-reqid>) #{exception.class.to_s} " + exception.message + "\n" + exception.backtrace.join("\n")
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
16
|
end # class WebService
|
78
17
|
end # module RESTRack
|
@@ -40,11 +40,11 @@ class SampleApp::ErrorsController < RESTRack::ResourceController
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def resource_invalid
|
43
|
-
raise HTTP422ResourceInvalid, package_error(
|
43
|
+
raise HTTP422ResourceInvalid, package_error('This is a WebDAV HTTP extension code used by ActiveResource to communicate validation errors.')
|
44
44
|
end
|
45
45
|
|
46
46
|
def resource_invalid_active_resource_format
|
47
|
-
raise HTTP422ResourceInvalid,
|
47
|
+
raise HTTP422ResourceInvalid, package_error('This is how ActiveResource expects errors to come through.')
|
48
48
|
end
|
49
49
|
|
50
50
|
def server_error
|
@@ -27,11 +27,12 @@ class SampleApp::TestControllerActions < Test::Unit::TestCase
|
|
27
27
|
:method => 'GET'
|
28
28
|
})
|
29
29
|
output = ''
|
30
|
-
assert_nothing_raised do
|
30
|
+
#assert_nothing_raised do
|
31
31
|
output = @ws.call(env)
|
32
|
-
end
|
32
|
+
#end
|
33
33
|
assert_equal response_code, output[0]
|
34
|
-
|
34
|
+
tester = {"errors" => [{"error"=>"tester"}]}
|
35
|
+
assert_equal tester, JSON.parse(output[2][0])
|
35
36
|
end
|
36
37
|
|
37
38
|
def test_unauthorized
|
@@ -44,7 +45,8 @@ class SampleApp::TestControllerActions < Test::Unit::TestCase
|
|
44
45
|
output = @ws.call(env)
|
45
46
|
end
|
46
47
|
assert_equal response_code, output[0]
|
47
|
-
|
48
|
+
tester = {"errors" => [{"error"=>"tester"}]}
|
49
|
+
assert_equal tester, JSON.parse(output[2][0])
|
48
50
|
end
|
49
51
|
|
50
52
|
def test_forbidden
|
@@ -57,7 +59,8 @@ class SampleApp::TestControllerActions < Test::Unit::TestCase
|
|
57
59
|
output = @ws.call(env)
|
58
60
|
end
|
59
61
|
assert_equal response_code, output[0]
|
60
|
-
|
62
|
+
tester = {"errors" => [{"error"=>"tester"}]}
|
63
|
+
assert_equal tester, JSON.parse(output[2][0])
|
61
64
|
end
|
62
65
|
|
63
66
|
def test_resource_not_found
|
@@ -70,7 +73,8 @@ class SampleApp::TestControllerActions < Test::Unit::TestCase
|
|
70
73
|
output = @ws.call(env)
|
71
74
|
end
|
72
75
|
assert_equal response_code, output[0]
|
73
|
-
|
76
|
+
tester = {"errors" => [{"error"=>"tester"}]}
|
77
|
+
assert_equal tester, JSON.parse(output[2][0])
|
74
78
|
end
|
75
79
|
|
76
80
|
def test_method_not_allowed
|
@@ -83,7 +87,8 @@ class SampleApp::TestControllerActions < Test::Unit::TestCase
|
|
83
87
|
output = @ws.call(env)
|
84
88
|
end
|
85
89
|
assert_equal response_code, output[0]
|
86
|
-
|
90
|
+
tester = {"errors" => [{"error"=>"tester"}]}
|
91
|
+
assert_equal tester, JSON.parse(output[2][0])
|
87
92
|
end
|
88
93
|
|
89
94
|
def test_conflict
|
@@ -96,7 +101,8 @@ class SampleApp::TestControllerActions < Test::Unit::TestCase
|
|
96
101
|
output = @ws.call(env)
|
97
102
|
end
|
98
103
|
assert_equal response_code, output[0]
|
99
|
-
|
104
|
+
tester = {"errors" => [{"error"=>"tester"}]}
|
105
|
+
assert_equal tester, JSON.parse(output[2][0])
|
100
106
|
end
|
101
107
|
|
102
108
|
def test_gone
|
@@ -109,7 +115,8 @@ class SampleApp::TestControllerActions < Test::Unit::TestCase
|
|
109
115
|
output = @ws.call(env)
|
110
116
|
end
|
111
117
|
assert_equal response_code, output[0]
|
112
|
-
|
118
|
+
tester = {"errors" => [{"error"=>"tester"}]}
|
119
|
+
assert_equal tester, JSON.parse(output[2][0])
|
113
120
|
end
|
114
121
|
|
115
122
|
def test_resource_invalid
|
@@ -122,8 +129,8 @@ class SampleApp::TestControllerActions < Test::Unit::TestCase
|
|
122
129
|
output = @ws.call(env)
|
123
130
|
end
|
124
131
|
assert_equal response_code, output[0]
|
125
|
-
|
126
|
-
assert_equal
|
132
|
+
tester = {"errors" => [{"error"=>"This is a WebDAV HTTP extension code used by ActiveResource to communicate validation errors."}]}
|
133
|
+
assert_equal tester, JSON.parse(output[2][0])
|
127
134
|
end
|
128
135
|
|
129
136
|
def test_resource_invalid_active_record_format
|
@@ -132,23 +139,23 @@ class SampleApp::TestControllerActions < Test::Unit::TestCase
|
|
132
139
|
:method => 'GET'
|
133
140
|
})
|
134
141
|
output = ''
|
135
|
-
assert_nothing_raised do
|
142
|
+
#assert_nothing_raised do
|
136
143
|
output = @ws.call(env)
|
137
|
-
end
|
144
|
+
#end
|
138
145
|
assert_equal response_code, output[0]
|
139
|
-
assert_equal '<?xml version="1.0" encoding="UTF-8"?><errors><error>This is how ActiveResource expects errors to come through.</error
|
146
|
+
assert_equal '<?xml version="1.0" encoding="UTF-8"?><errors><error>This is how ActiveResource expects errors to come through.</error></errors>', output[2][0]
|
140
147
|
|
141
148
|
response_code = 422
|
142
149
|
env = Rack::MockRequest.env_for('/errors/resource_invalid_active_resource_format', {
|
143
150
|
:method => 'GET'
|
144
151
|
})
|
145
152
|
output = ''
|
146
|
-
assert_nothing_raised do
|
153
|
+
#assert_nothing_raised do
|
147
154
|
output = @ws.call(env)
|
148
|
-
end
|
155
|
+
#end
|
149
156
|
assert_equal response_code, output[0]
|
150
|
-
|
151
|
-
assert_equal
|
157
|
+
tester = {"errors" => [{"error"=>"This is how ActiveResource expects errors to come through."}]}
|
158
|
+
assert_equal tester, JSON.parse(output[2][0])
|
152
159
|
end
|
153
160
|
|
154
161
|
def test_server_error
|
@@ -158,9 +165,9 @@ class SampleApp::TestControllerActions < Test::Unit::TestCase
|
|
158
165
|
:method => 'GET'
|
159
166
|
})
|
160
167
|
output = ''
|
161
|
-
assert_nothing_raised do
|
168
|
+
#assert_nothing_raised do
|
162
169
|
output = @ws.call(env)
|
163
|
-
end
|
170
|
+
#end
|
164
171
|
assert_equal response_code, output[0]
|
165
172
|
end
|
166
173
|
|
@@ -190,7 +197,8 @@ class SampleApp::TestControllerActions < Test::Unit::TestCase
|
|
190
197
|
output = @ws.call(env)
|
191
198
|
end
|
192
199
|
assert_equal response_code, output[0]
|
193
|
-
|
200
|
+
tester = {"errors"=>[{"error"=>"tester"}]}
|
201
|
+
assert_equal tester, JSON.parse(output[2][0])
|
194
202
|
RESTRack::CONFIG[:SHOW_STACK] = true
|
195
203
|
end
|
196
204
|
|
@@ -18,7 +18,7 @@ class SampleApp::TestFormats < Test::Unit::TestCase
|
|
18
18
|
assert_nothing_raised do
|
19
19
|
output = @ws.call(env)
|
20
20
|
end
|
21
|
-
test_val = "<?xml version
|
21
|
+
test_val = "<?xml version='1.0' standalone='yes'?>\n<opt><foo>bar</foo><baz>123</baz></opt>"
|
22
22
|
assert_equal test_val, output[2][0]
|
23
23
|
end
|
24
24
|
|
@@ -55,7 +55,7 @@ class SampleApp::TestFormats < Test::Unit::TestCase
|
|
55
55
|
test_val = { :foo => 'bar', :baz => 123 }.to_json
|
56
56
|
assert_equal test_val, output[2][0]
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
def test_complex_data_structure_json
|
60
60
|
env = Rack::MockRequest.env_for('/foo_bar/1234567890', {
|
61
61
|
:method => 'GET'
|
@@ -66,7 +66,7 @@ class SampleApp::TestFormats < Test::Unit::TestCase
|
|
66
66
|
end
|
67
67
|
test_val = "{\"foo\":\"abc\",\"bar\":\"123\",\"baz\":456,\"more\":{\"one\":1,\"two\":[1,2],\"three\":\"deep_fu\"}}"
|
68
68
|
assert_equal test_val, output[2][0]
|
69
|
-
|
69
|
+
|
70
70
|
env = Rack::MockRequest.env_for('/foo_bar/42', {
|
71
71
|
:method => 'GET'
|
72
72
|
})
|
@@ -86,7 +86,7 @@ class SampleApp::TestFormats < Test::Unit::TestCase
|
|
86
86
|
}.to_json
|
87
87
|
assert_equal test_val, output[2][0]
|
88
88
|
end
|
89
|
-
|
89
|
+
|
90
90
|
def test_complex_data_structure_xml
|
91
91
|
env = Rack::MockRequest.env_for('/foo_bar/1234567890/complex_show_xml_no_builder.xml', {
|
92
92
|
:method => 'GET'
|
@@ -97,7 +97,7 @@ class SampleApp::TestFormats < Test::Unit::TestCase
|
|
97
97
|
end
|
98
98
|
test_val = "<?xml version='1.0' standalone='yes'?>\n<opt><foo>abc</foo><bar>123</bar><baz>456</baz><more><one>1</one><two>1</two><two>2</two><three>deep_fu</three></more></opt>"
|
99
99
|
assert_equal test_val, output[2][0]
|
100
|
-
|
100
|
+
|
101
101
|
env = Rack::MockRequest.env_for('/foo_bar/42/complex_show_xml_no_builder.xml', {
|
102
102
|
:method => 'GET'
|
103
103
|
})
|
@@ -50,7 +50,7 @@ class SampleApp::TestResourceRequest < Test::Unit::TestCase
|
|
50
50
|
assert_nothing_raised do
|
51
51
|
output = @ws.call(env)
|
52
52
|
end
|
53
|
-
assert_equal
|
53
|
+
assert_equal 204, output[0]
|
54
54
|
|
55
55
|
RESTRack::CONFIG[:ROOT_RESOURCE_ACCEPT] = []
|
56
56
|
env = Rack::MockRequest.env_for('/foo_bar/144', {
|
@@ -60,7 +60,7 @@ class SampleApp::TestResourceRequest < Test::Unit::TestCase
|
|
60
60
|
assert_nothing_raised do
|
61
61
|
output = @ws.call(env)
|
62
62
|
end
|
63
|
-
assert_equal
|
63
|
+
assert_equal 204, output[0]
|
64
64
|
|
65
65
|
RESTRack::CONFIG[:ROOT_RESOURCE_ACCEPT] = nil
|
66
66
|
env = Rack::MockRequest.env_for('/foo_bar/144', {
|
@@ -70,7 +70,7 @@ class SampleApp::TestResourceRequest < Test::Unit::TestCase
|
|
70
70
|
assert_nothing_raised do
|
71
71
|
output = @ws.call(env)
|
72
72
|
end
|
73
|
-
assert_equal
|
73
|
+
assert_equal 204, output[0]
|
74
74
|
|
75
75
|
RESTRack::CONFIG[:ROOT_RESOURCE_ACCEPT] = [ 'foo_bar' ]
|
76
76
|
end
|
@@ -105,7 +105,7 @@ class SampleApp::TestResourceRequest < Test::Unit::TestCase
|
|
105
105
|
assert_nothing_raised do
|
106
106
|
output = @ws.call(env)
|
107
107
|
end
|
108
|
-
assert_equal
|
108
|
+
assert_equal 204, output[0]
|
109
109
|
|
110
110
|
RESTRack::CONFIG[:ROOT_RESOURCE_DENY] = nil
|
111
111
|
env = Rack::MockRequest.env_for('/foo_bar/144', {
|
@@ -115,7 +115,7 @@ class SampleApp::TestResourceRequest < Test::Unit::TestCase
|
|
115
115
|
assert_nothing_raised do
|
116
116
|
output = @ws.call(env)
|
117
117
|
end
|
118
|
-
assert_equal
|
118
|
+
assert_equal 204, output[0]
|
119
119
|
|
120
120
|
RESTRack::CONFIG[:ROOT_RESOURCE_DENY] = ['']
|
121
121
|
# it should handle this, although it is incorrect
|
@@ -126,7 +126,7 @@ class SampleApp::TestResourceRequest < Test::Unit::TestCase
|
|
126
126
|
assert_nothing_raised do
|
127
127
|
output = @ws.call(env)
|
128
128
|
end
|
129
|
-
assert_equal
|
129
|
+
assert_equal 204, output[0]
|
130
130
|
|
131
131
|
RESTRack::CONFIG[:ROOT_RESOURCE_DENY] = [ 'baz' ]
|
132
132
|
end
|
@@ -171,9 +171,9 @@ class SampleApp::TestResourceRequest < Test::Unit::TestCase
|
|
171
171
|
]|
|
172
172
|
})
|
173
173
|
output = ''
|
174
|
-
assert_nothing_raised do
|
174
|
+
#assert_nothing_raised do
|
175
175
|
output = @ws.call(env)
|
176
|
-
end
|
176
|
+
#end
|
177
177
|
assert_equal 500, output[0]
|
178
178
|
end
|
179
179
|
|
@@ -207,7 +207,7 @@ class SampleApp::TestResourceRequest < Test::Unit::TestCase
|
|
207
207
|
assert_nothing_raised do
|
208
208
|
output = @ws.call(env)
|
209
209
|
end
|
210
|
-
assert_equal
|
210
|
+
assert_equal 204, output[0]
|
211
211
|
end
|
212
212
|
|
213
213
|
def test_force_encoding_defined
|
@@ -241,7 +241,7 @@ class SampleApp::TestResourceRequest < Test::Unit::TestCase
|
|
241
241
|
assert_nothing_raised do
|
242
242
|
output = @ws.call(env)
|
243
243
|
end
|
244
|
-
assert_equal
|
244
|
+
assert_equal 204, output[0]
|
245
245
|
end
|
246
246
|
|
247
247
|
def test_force_encoding_not_defined
|
@@ -274,7 +274,7 @@ class SampleApp::TestResourceRequest < Test::Unit::TestCase
|
|
274
274
|
assert_nothing_raised do
|
275
275
|
output = @ws.call(env)
|
276
276
|
end
|
277
|
-
assert_equal
|
277
|
+
assert_equal 204, output[0]
|
278
278
|
end
|
279
279
|
|
280
280
|
end
|
@@ -66,7 +66,7 @@ class SampleApp::TestResourceRequest < Test::Unit::TestCase
|
|
66
66
|
assert_nothing_raised do
|
67
67
|
output = @ws.call(env)
|
68
68
|
end
|
69
|
-
assert_equal
|
69
|
+
assert_equal 204, output[0]
|
70
70
|
|
71
71
|
# the following request should hit the default controller's index method (BazuController)
|
72
72
|
env = Rack::MockRequest.env_for('', {
|
data/test/test_web_service.rb
CHANGED
@@ -6,8 +6,10 @@ require File.expand_path(File.join(File.dirname(__FILE__),'../lib/restrack'))
|
|
6
6
|
module RESTRack
|
7
7
|
class TestWebService < Test::Unit::TestCase
|
8
8
|
|
9
|
+
RESTRack::CONFIG = RESTRack.load_config(File.expand_path(File.join(File.dirname(__FILE__),'../test/sample_app_1/config/constants.yaml')))
|
10
|
+
|
9
11
|
def test_call
|
10
|
-
env = Rack::MockRequest.env_for('/
|
12
|
+
env = Rack::MockRequest.env_for('/foo_bar', {
|
11
13
|
:method => 'POST',
|
12
14
|
:params => %Q|[
|
13
15
|
{
|
@@ -15,10 +17,10 @@ module RESTRack
|
|
15
17
|
}
|
16
18
|
]|
|
17
19
|
})
|
18
|
-
assert_nothing_raised do
|
20
|
+
#assert_nothing_raised do
|
19
21
|
ws = RESTRack::WebService.new # init logs
|
20
22
|
ws.call(env)
|
21
|
-
end
|
23
|
+
#end
|
22
24
|
end
|
23
25
|
|
24
26
|
def test_initialize
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: restrack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
@@ -172,7 +172,9 @@ files:
|
|
172
172
|
- lib/restrack/generator/loader.rb.erb
|
173
173
|
- lib/restrack/http_status.rb
|
174
174
|
- lib/restrack/resource_controller.rb
|
175
|
+
- lib/restrack/resource_relations.rb
|
175
176
|
- lib/restrack/resource_request.rb
|
177
|
+
- lib/restrack/response.rb
|
176
178
|
- lib/restrack/support.rb
|
177
179
|
- lib/restrack/version.rb
|
178
180
|
- lib/restrack/web_service.rb
|