lib/merb/merb_controller.rb in merb-0.0.4 vs lib/merb/merb_controller.rb in merb-0.0.5
- old
+ new
@@ -8,11 +8,14 @@
# puts that into params as well.
class Controller
attr_accessor :status
-
+ # parses the http request into params, headers and cookies
+ # that you can use in your controller classes. Also handles
+ # file uploads by writing a tempfile and passing a reference
+ # in params.
def initialize(req, env, args, method=(env['REQUEST_METHOD']||"GET")) #:nodoc:
env = MerbHash[env.to_hash]
puts env.inspect if $DEBUG
puts req.inspect if $DEBUG
@layout = 'application'
@@ -55,72 +58,132 @@
end
elsif @method == "post"
qs.merge!(query_parse(@in.read))
end
@cookies, @params = @k.dup, qs.dup.merge(args)
+ MERB_LOGGER.info("Params: #{params.inspect}")
end
+ # redirect to another url It can be like /foo/bar
+ # for redirecting within your same app. Or it can
+ # be a fully qualified url to another site.
def redirect(url)
+ MERB_LOGGER.info("Redirecting to: #{url}")
@status = 302
@headers.merge!({'Location'=> url})
return ''
end
+ # pass in a path to a file and this will set the
+ # right headers and let mongrel do its thang and
+ # serve the static file directly.
def send_file(file)
headers['X-SENDFILE'] = file
return
end
+ # accessor for @params. Please use params and
+ # never @params directly.
def params
@params
end
+ # accessor for @cookies. Please use cookies and
+ # never @cookies directly.
def cookies
@cookies
end
+ # accessor for @headers. Please use headers and
+ # never @headers directly.
def headers
@headers
end
+ # parses a query string or the payload of a POST
+ # request into the params hash. So for example:
+ # /foo?bar=nik&post[title]=heya&post[body]=whatever
+ # parses into:
+ # {:bar => 'nik', :post => {:title => 'heya', :body => 'whatever}}
def query_parse(qs, d = '&;')
m = proc {|_,o,n|o.update(n,&m)rescue([*o]<<n)}
(qs||'').split(/[#{d}] */n).inject(MerbHash[]) { |h,p|
k, v=unescape(p).split('=',2)
h.update(k.split(/[\]\[]+/).reverse.
inject(v) { |x,i| MerbHash[i,x] },&m)
}
end
+ # does url escaping
def escape(s)
Mongrel::HttpRequest.escape(s)
end
+ # does url unescaping
def unescape(s)
Mongrel::HttpRequest.unescape(s)
end
-
+ # escape text for javascript.
+ def escape_js(javascript)
+ (javascript || '').gsub('\\','\0\0').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" }
+ end
+ alias :js :escape_js
+
+ # shortcut to a template path based on name.
def template_dir(loc)
File.expand_path(Merb::Server.config[:merb_root] + "/dist/app/views/#{loc}")
end
+ # returns the current method name. Used for
+ # auto discovery of which template to render
+ # based on the action name.
def current_method_name(depth=0)
caller[depth] =~ /`(.*)'$/; $1
end
+ # does a render with no layout. Also sets the
+ # content type header to text/javascript and
+ # escapes the template for javascript eval on
+ # the client
+ def render_js(template=current_method_name(1), b=binding)
+ headers['Content-Type'] = "text/javascript"
+ template = Erubis::Eruby.new(IO.read( template_dir(self.class.name.snake_case) + "/#{template}.merbjs" ))
+ template.result(b)
+ end
+ # set the @layout. Use this right before a render to
+ # set the name of the layout to use minus the .rhtml
def layout(l)
@layout = l
end
+ def render_nothing(status)
+ @status = status
+ return ''
+ end
+
+ # renders the action without wrapping it in a layout.
def render_no_layout(template=current_method_name(1), b=binding)
template = Erubis::Eruby.new( IO.read( template_dir(self.class.name.snake_case) + "/#{template}.rhtml" ) )
template.result(b)
- end
+ end
+ def partial(template)
+ template = Erubis::Eruby.new( IO.read( template_dir(self.class.name.snake_case) + "/_#{template}.rhtml" ) )
+ template.result(binding)
+ end
+
+ # renders a template based on the current action name
+ # you can pass the name of a template if you want to
+ # render a template with a different name then then
+ # current action name. Wraps the rendered template in
+ # the layout. Uses layout/application.rhtml unless
+ # there is a layout named after the current controller
+ # or @layout has been set to another value.
def render(template=current_method_name(1), b=binding)
+ MERB_LOGGER.info("Rendering template: #{template_dir(template)}")
name = self.class.name.snake_case
template = Erubis::Eruby.new( IO.read( template_dir(name) + "/#{template}.rhtml" ) )
layout_content = template.result(b)
return layout_content if (@layout.to_s == 'none')
if ['application', name].include?(@layout.to_s)
@@ -130,14 +193,30 @@
layout = 'application'
end
else
layout = @layout.to_s
end
+ MERB_LOGGER.info("With Layout: #{template_dir('layout')}/#{layout}.rhtml")
@layout_content = layout_content
layout_tmpl = Erubis::Eruby.new( IO.read( template_dir('layout') + "/#{layout}.rhtml" ) )
layout_tmpl.result(b)
end
-
end
+end
+
+class Noroutefound < Merb::Controller
+ # This is the class that handles requests that don't
+ # match any defined routes.
+
+ def method_missing(sym, *args, &blk)
+ @status = 404
+ "<html><body><h1>No Matching Route</h1></body></html>"
+ end
+
+ def to_s
+ @status = 404
+ "<html><body><h1>No Matching Route s</h1></body></html>"
+ end
+
end
\ No newline at end of file