Skip to content

Commit

Permalink
Wrote specs for assuring that NoMethodErrors aren't returned as 404 w…
Browse files Browse the repository at this point in the history
…hen it is a 505. Clarified and cleaned up the error handling in the Halcyon::Application#dispatch method consequently. Should learn to write specs before committing and pushing broken code.
  • Loading branch information
mtodd committed Apr 17, 2008
1 parent 075636d commit 5642b5e
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 24 deletions.
45 changes: 21 additions & 24 deletions lib/halcyon/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,35 +122,32 @@ def call(env)
#
# Returns (String|Array|Hash):body
def dispatch(env)
begin
route = env['halcyon.route']
# make sure that the right controller/action is called based on the route
controller = case route[:controller]
when NilClass
# default to the Application controller
::Application.new(env)
when String
# pulled from URL, so camelize (from merb/core_ext) and symbolize first
Object.const_get(route[:controller].camel_case.to_sym).new(env)
end

# This block and the following call to +action+ detects if a non-
# existent action is routed to, as opposed to just catching a blanket
# <tt>NoMethodFound</tt> error which can occur in actions too,
# reporting as a <tt>404 Not Found error</tt> incorrectly.
route = env['halcyon.route']
# make sure that the right controller/action is called based on the route
controller = case route[:controller]
when NilClass
# default to the Application controller
::Application.new(env)
when String
# pulled from URL, so camelize (from merb/core_ext) and symbolize first
begin
action = controller.method((route[:action] || 'default').to_sym)
Object.const_get(route[:controller].camel_case.to_sym).new(env)
rescue NameError => e
raise NotFound.new
end

# Calls the action. This will only run if the action exists inside of
# the controller and won't throw false positives for bad method calls
# in the action as a <tt>404 Not Found</tt> error.
action.call
rescue NameError => e
raise NotFound.new
end

# Establish the selected action, defaulting to +default+.
action = (route[:action] || 'default').to_sym

# Respond correctly that a non-existent action was specified if the
# method does not exist.
raise NotFound.new unless controller.methods.include?(action.to_s)

# if no errors have occured up to this point, the route should be fully
# valid and all exceptions raised should be treated as
# <tt>500 Internal Server Error</tt>s, which is handled by <tt>call</tt>.
controller.send(action)
end

# Filters unacceptable requests depending on the configuration of the
Expand Down
6 changes: 6 additions & 0 deletions spec/halcyon/application_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,10 @@
body['body'].should == "Internal Server Error"
end

it "should not confuse a NoMethodFound error in an action as a missing route" do
body = JSON.parse(Rack::MockRequest.new(@app).get("/specs/call_nonexistent_method").body)
body['status'].should.not == 404
body['body'].should == "Internal Server Error"
end

end
6 changes: 6 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ def cause_exception
raise Exception.new("Oops!")
end

def call_nonexistent_method
hash = Hash.new
hash.please_dont_exist_and_please_throw_no_method_error
ok
end

end

class Resources < Application
Expand Down

0 comments on commit 5642b5e

Please sign in to comment.