Changeset 169
- Timestamp:
- 01/24/07 21:17:16 (2 years ago)
- Files:
-
- trunk/README (modified) (3 diffs)
- trunk/lib/merb.rb (modified) (1 diff)
- trunk/lib/merb/core_ext/merb_object.rb (modified) (2 diffs)
- trunk/lib/merb/merb_controller.rb (modified) (2 diffs)
- trunk/lib/merb/merb_exceptions.rb (modified) (1 diff)
- trunk/lib/merb/merb_handler.rb (modified) (2 diffs)
- trunk/lib/merb/merb_request.rb (modified) (1 diff)
- trunk/lib/merb/merb_router.rb (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/README
r160 r169 6 6 Little bitty lightweight ruby app server. For when you really need performance 7 7 for simple dynamic pages. 8 9 **Sample APP included**10 8 11 9 ** Dependencies ** … … 37 35 *RouteMatcher and route compiler* 38 36 Reads your route definition and compiles 39 a method on the fly that will match the request path against each route and do the 40 right thing. So the following routes: 37 a method on the fly that will match the request path against each route and do the right thing. 38 39 *** NEW RESTFULL ROUTES *** 40 41 note the r.resource :posts macro. That makes it possible to use a restfull crud style controller for the posts resource 41 42 42 43 Merb::RouteMatcher.prepare do |r| 43 r. add '/foo/:bar/baz/:id', :controller => 'Test', :action => 'foo'44 r.resource :posts 44 45 r.add '/:controller/:action/:id' 45 r.add '/ bar/:*rest', :controller => 'Test', :action => 'glob'46 r.add '/', :controller => 'files', :action => 'index' 46 47 end 47 48 … … 50 51 lambda{|path| 51 52 case path 52 when Regexp.new('/foo/([^/;.,?]+)/baz/([^/;.,?]+)') 53 @sections[:bar] = $1 54 @sections[:id] = $2 55 return {:controller=>"Test", :action=>"foo"}.merge(@sections) 53 when Regexp.new('/posts/([^/,?]+)[;]edit') 54 @sections[:id] = $1 55 return {:rest=>true, :controller=>"posts", :allowed=>{:get=>"edit"}}.update(@sections) 56 when Regexp.new('/posts/new[;]([^/,?]+)') 57 @sections[:action] = $1 58 return {:rest=>true, :controller=>"posts", :allowed=>{:post=>"new", :get=>"new", :delete=>"new", :put=>"new"}}.update(@sections) 59 when Regexp.new('/posts/new') 60 return {:rest=>true, :controller=>"posts", :allowed=>{:get=>"new"}}.update(@sections) 61 when Regexp.new('/posts/([^/,?]+)\.([^/,?]+)') 62 @sections[:id] = $1 63 @sections[:format] = $2 64 return {:rest=>true, :controller=>"posts", :allowed=>{:get=>"show", :delete=>"destroy", :put=>"update"}}.update(@sections) 65 when Regexp.new('/posts\.([^/,?]+)') 66 @sections[:format] = $1 67 return {:rest=>true, :controller=>"posts", :allowed=>{:post=>"create", :get=>"index"}}.update(@sections) 68 when Regexp.new('/posts/([^/,?]+)') 69 @sections[:id] = $1 70 return {:rest=>true, :controller=>"posts", :allowed=>{:get=>"show", :delete=>"destroy", :put=>"update"}}.update(@sections) 71 when Regexp.new('/posts/?') 72 return {:rest=>true, :controller=>"posts", :allowed=>{:post=>"create", :get=>"index"}}.update(@sections) 56 73 when /\A\/([^\/;.,?]+)(?:\/?\Z|\/([^\/;.,?]+)\/?)(?:\/?\Z|\/([^\/;.,?]+)\/?)\Z/ 57 74 @sections[:controller] = $1 58 75 @sections[:action] = $2 || 'index' 59 @sections[:id] = $3 || nil76 @sections[:id] = $3 if $3 60 77 return @sections 61 when Regexp.new('/bar/([^;.,?]+)') 62 @sections[:rest] = $1 63 return {:controller=>"Test", :action=>"glob"}.merge(@sections) 78 when Regexp.new('/') 79 return {:controller=>"files", :action=>"index"}.update(@sections) 64 80 else 65 81 return {:controller=>'Noroutefound', :action=>'noroute'} 66 82 end 67 83 } 84 85 86 *Restful Controller* 87 88 restful controllers use a different dispatch system based on the request method verbs. 89 90 class Posts < Merb::Controller 91 # GET /posts 92 # GET /posts.xml 93 def index 94 end 95 96 # GET /posts/1 97 # GET /posts/1.xml 98 def show 99 end 100 101 # GET /posts/new 102 def new 103 end 104 105 # GET /posts/1;edit 106 def edit 107 end 108 109 # POST /posts 110 # POST /posts.xml 111 def create 112 end 113 114 # PUT /posts/1 115 # PUT /posts/1.xml 116 def update 117 end 118 119 # DELETE /posts/1 120 # DELETE /posts/1.xml 121 def destroy 122 end 123 end 124 68 125 69 126 *Simple Controllers* trunk/lib/merb.rb
r167 r169 48 48 MERB_ROOT = Merb::Server.merb_root || Dir.pwd 49 49 DIST_ROOT = Merb::Server.dist_root || Dir.pwd+'/dist' 50 MERB_ENV = Merb::Server.config[:environment] 50 51 51 52 logpath = $TESTING ? "/tmp/merb_test.log" : "#{MERB_ROOT}/log/merb.#{Merb::Server.port}.log" trunk/lib/merb/core_ext/merb_object.rb
r142 r169 11 11 self.class.class_eval { define_method name, &blk } 12 12 end 13 13 14 def blank? 14 15 if respond_to? :empty? then empty? … … 18 19 end 19 20 21 def with_options(options) 22 yield Merb::OptionMerger.new(self, options) 23 end 20 24 end 25 26 module Merb 27 class OptionMerger #:nodoc: 28 instance_methods.each do |method| 29 undef_method(method) if method !~ /^(__|instance_eval|class)/ 30 end 31 32 def initialize(context, options) 33 @context, @options = context, options 34 end 35 36 private 37 def method_missing(method, *arguments, &block) 38 merge_argument_options! arguments 39 @context.send(method, *arguments, &block) 40 end 41 42 def merge_argument_options!(arguments) 43 arguments << if arguments.last.respond_to? :to_hash 44 @options.merge(arguments.pop) 45 else 46 @options.dup 47 end 48 end 49 end 50 end trunk/lib/merb/merb_controller.rb
r167 r169 20 20 include Merb::ResponderMixin 21 21 22 attr_accessor :status, :body 22 attr_accessor :status, :body, :request 23 23 24 24 MULTIPART_REGEXP = /\Amultipart\/form-data.*boundary=\"?([^\";,]+)/n.freeze … … 85 85 end 86 86 end 87 87 88 @cookies, @params = cookies.dup, querystring.dup.merge(args) 88 @cookies.merge!(:_session_id => @params[:_session_id]) if @params.has_key?(:_session_id) 89 @method = @params.delete(:_method).downcase.to_sym if @params.has_key?(:_method) 89 @cookies.merge!(session_id_key => @params[session_id_key]) if @params.key?(session_id_key) 90 91 allow = [:post, :put, :delete] 92 allow << :get if MERB_ENV == 'development' 93 if @params.key?(:_method) && [:post, :put, :delete].include?(@method) 94 @method = @params.delete(:_method).downcase.to_sym 95 end 90 96 @request = Request.new(@env, @method) 97 91 98 MERB_LOGGER.info("Params: #{params.inspect}") 92 99 end trunk/lib/merb/merb_exceptions.rb
r149 r169 9 9 class MissingControllerFile < MerbError; end 10 10 class MerbControllerError < MerbError; end 11 11 class RestfulMethodNotAllowed < MerbError; end 12 12 # format exception message for browser display 13 13 def self.html_exception(e) trunk/lib/merb/merb_handler.rb
r167 r169 147 147 # [controller, action] 148 148 def handle(request, response) 149 path = request.params[Mongrel::Const:: PATH_INFO].sub(/\/+/, '/')149 path = request.params[Mongrel::Const::REQUEST_URI].sub(/\/+/, '/') 150 150 path = path[0..-2] if (path[-1] == ?/) && path.size > 1 151 151 152 route = Merb::RouteMatcher.new.route_request(path) 152 [ instantiate_controller(route[:controller], request.body, request.params, route, response), 153 route[:action] ] 153 154 allowed = route.delete(:allowed) 155 rest = route.delete(:rest) 156 157 controller = instantiate_controller(route[:controller], request.body, request.params, route, response) 158 159 if rest 160 method = controller.request.method 161 if allowed.keys.include?(method) 162 controller.params[:action] = allowed[method] 163 [controller, allowed[method]] 164 else 165 raise Merb::RestfulMethodNotAllowed 166 end 167 else 168 [controller, route[:action] ] 169 end 154 170 end 155 171 … … 160 176 def instantiate_controller(controller_name, req, env, params, res) 161 177 if !File.exist?(DIST_ROOT+"/app/controllers/#{controller_name.snake_case}.rb") 162 raise Merb::MissingControllerFile178 raise "Bad controller! #{controller_name.snake_case}" 163 179 end 164 180 begin trunk/lib/merb/merb_request.rb
r106 r169 79 79 # returns the REQUEST_METHOD 80 80 def method 81 @method ||= @env['REQUEST_METHOD'] 81 @method ||= @env['REQUEST_METHOD'].downcase.intern 82 82 end 83 83 trunk/lib/merb/merb_router.rb
r168 r169 37 37 # the final compiled lambda that gets used 38 38 # as the body of the route_request method. 39 def self.compiled_statement 40 @@compiled_statement 41 end 42 39 43 def compiled_statement 40 44 @@compiled_statement … … 91 95 statement 92 96 end 93 97 98 # add a resource to be compiled for rest style dispatch 99 def self.resource(res) 100 with_options :controller => res.to_s, :rest => true do |r| 101 r.add "/#{res}/:id[;]edit", :allowed => {:get => 'edit'} 102 r.add "/#{res}/new[;]:action", :allowed => {:get => 'new', :post => 'new', :put => 'new', :delete => 'new'} 103 r.add "/#{res}/new" , :allowed => {:get => 'new'} 104 # r.add "/#{res}/:id[;]+:action$", :allowed => {:get => '?', :post => '?', :put => '?', :delete => '?'} 105 r.add "/#{res}/:id\\.:format", :allowed => {:get => 'show', :put => 'update', :delete => 'destroy'} 106 r.add "/#{res}\\.:format", :allowed => {:get => 'index', :post => 'create'} 107 r.add "/#{res}/:id", :allowed => {:get => 'show', :put => 'update', :delete => 'destroy'} 108 r.add "/#{res}/?", :allowed => {:get => 'index', :post => 'create'} 109 end 110 end 111 94 112 end 95 113 96 end 114 end
