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