lib/merb/merb_controller.rb in merb-0.0.8 vs lib/merb/merb_controller.rb in merb-0.0.9

- old
+ new

@@ -11,12 +11,12 @@ # stream it into a tempfile and pass in the filename and tempfile object # to your controller via params. It also parses the ?query=string and # puts that into params as well. class Controller - meta_accessor :layout - + shared_accessor :layout, :session_id_key, :cache_templates + include Merb::ControllerMixin include Merb::RenderMixin include Merb::ResponderMixin attr_accessor :status, :body @@ -35,10 +35,11 @@ @status, @method, @env, @headers, @root = 200, method.downcase.to_sym, env, {'Content-Type' =>'text/html'}, env['SCRIPT_NAME'].sub(/\/$/,'') cookies = query_parse(env['HTTP_COOKIE'], ';,') querystring = query_parse(env['QUERY_STRING']) self.layout ||= :application + self.session_id_key ||= :_session_id @in = req if MULTIPART_REGEXP =~ env['CONTENT_TYPE'] boundary_regexp = /(?:\r?\n|\A)#{Regexp::quote("--#$1")}(?:--)?\r$/ until @in.eof? attrs=MerbHash[] @@ -64,11 +65,15 @@ @in.seek(-$'.size, IO::SEEK_CUR) break end io_buffer << chunk end - querystring[name]=attrs if name + if name =~ /(.*)?\[\]/ + (querystring[$1] ||= []) << attrs + else + querystring[name]=attrs if name + end attrs[:tempfile].rewind if attrs.is_a?MerbHash end elsif @method == :post if ['application/json', 'text/x-json'].include?(env['CONTENT_TYPE']) MERB_LOGGER.info("JSON Request") @@ -78,33 +83,33 @@ else querystring.merge!(query_parse(@in.read)) end end @cookies, @params = cookies.dup, querystring.dup.merge(args) - @cookies.merge!(:session_id => @params[:session_id]) if @params.has_key?(:session_id) + @cookies.merge!(:_session_id => @params[:_session_id]) if @params.has_key?(:_session_id) @method = @params.delete(:_method).downcase.to_sym if @params.has_key?(:_method) @request = Request.new(@env, @method) MERB_LOGGER.info("Params: #{params.inspect}") end def dispatch(action=:to_s) start = Time.now setup_session if respond_to?:setup_session cought = catch(:halt) { call_filters(before_filters) } - case cought + @body = case cought when :filter_chain_completed - @body = send(action) + send(action) when String - @body = cought + cought when nil - @body = filters_halted + filters_halted when Symbol - @body = send(cought) + send(cought) when Proc - @body = cought.call(self) + cought.call(self) else - raise MerbControllerError, "The before filter chain is broken dude." + raise MerbControllerError, "The before filter chain is broken dude. wtf?" end call_filters(after_filters) finalize_session if respond_to?:finalize_session MERB_LOGGER.info("Time spent in #{action} action: #{Time.now - start} seconds") end @@ -143,17 +148,17 @@ # never @session directly. def session @session end - # meta_accessor sets up a class instance variable that can + # shared_accessor sets up a class instance variable that can # be unique for each class but also inherits the meta attrs # from its superclasses. Since @@class variables are almost # global vars within an inheritance tree, we use # @class_instance_variables instead - meta_accessor :before_filters - meta_accessor :after_filters + shared_accessor :before_filters + shared_accessor :after_filters # calls a filter chain according to rules. def call_filters(filter_set) (filter_set || []).each do |(filter, rule)| ok = false @@ -227,22 +232,17 @@ raise(ArgumentError, "You can specify either :only or :exclude but not both at the same time for the same filter." ) if opts.has_key?(:only) && opts.has_key?(:exclude) - if opts[:only] && opts[:only].is_a?(Symbol) - opts[:only] = [opts[:only]] - end - if opts[:exclude] && opts[:exclude].is_a?(Symbol) - opts[:exclude] = [opts[:exclude]] - end + opts = shuffle_filters!(opts) case filter when Symbol, String, Proc (self.before_filters ||= []) << [filter, opts] else - raise(MerbControllerError, + raise(ArgumentError, 'filters need to be either a Symbol, String or a Proc' ) end end @@ -258,20 +258,28 @@ def self.after(filter, opts={}) raise(ArgumentError, "You can specify either :only or :exclude but not both at the same time for the same filter." ) if opts.has_key?(:only) && opts.has_key?(:exclude) + raise(ArgumentError, 'after filters can only be a Proc object' ) unless Proc === filter + + opts = shuffle_filters!(opts) + + (self.after_filters ||= []) << [filter, opts] + end + + def self.shuffle_filters!(opts={}) if opts[:only] && opts[:only].is_a?(Symbol) opts[:only] = [opts[:only]] end if opts[:exclude] && opts[:exclude].is_a?(Symbol) opts[:exclude] = [opts[:exclude]] end - (self.after_filters ||= []) << [filter, opts] - end + return opts + end end end