Copyright (c) 2006 Ezra Zygmuntowicz Merb. Mongrel+Erb Little bitty lightweight ruby app server. For when you really need performance for simple dynamic pages. **Sample APP included** ** Dependencies ** mongrel erubis json or fjson mime-types Install these gems first then you can build the merb gem from svn trunk like so: $ sudo gem install mongrel erubis json mime-types --include-dependencies $ svn co http://svn.devjavu.com/merb $ cd merb $ sudo rake install **Important** The new default filename extensions for templates are as follows html -> .herb js -> .jerb xml -> .xerb You can change the extensions to anything you want in your config file in yourapp/dist/conf/merb.yml. See the default settings in the sample app. First you need to install the dependencies. Merb requires the follwing gems erubis json fjson # will be used if present. requires C extension. # fastthread will be used if present and is reccommended. sudo gem install fastthread --source=http://mongrel.rubyforge.org/ If you have checked out merb trunk from svn you will want to build and install the gem to use merb. Run this command from the root of the merb svn checkout to do that: $ sudo rake install If you installed merb from gems then unpack the gem and grab the sample app $ gem unpack merb now with either the svn or the unpacked gem you can try out the sample app. $ cd merb* $ cd examples/sample_app $ merb You will need the mongrel_upload_progress gem installed to go to /files so use the -f flag to load a config file for mongrel_upload_progress $ merb -f dist/conf/mup.conf then the sample app will be running on port 4000 in the foreground. you can go to a few urls: http://localhost:4000/files/start http://localhost:4000/foo/123/baz/12234345 **FEATURES** *Mongrel handler* built in that parses incoming requests including multipart uploads and post as well as ?query=strings. Puts the params into params and the cookies into cookies when it instantiates your controller class. *RouteMatcher and route compiler* Reads your route definition and compiles a method on the fly that will match the request path against each route and do the right thing. So the following routes: Merb::RouteMatcher.prepare do |r| r.add '/foo/:bar/baz/:id', :controller => 'Test', :action => 'foo' r.add '/:controller/:action/:id' r.add '/bar/:*rest', :controller => 'Test', :action => 'glob' end Will be compiled and defined as a method with this lambda as the body: lambda{|path| case path when Regexp.new('/foo/([^/;.,?]+)/baz/([^/;.,?]+)') @sections[:bar] = $1 @sections[:id] = $2 return {:controller=>"Test", :action=>"foo"}.merge(@sections) when /\A\/([^\/;.,?]+)(?:\/?\Z|\/([^\/;.,?]+)\/?)(?:\/?\Z|\/([^\/;.,?]+)\/?)\Z/ @sections[:controller] = $1 @sections[:action] = $2 || 'index' @sections[:id] = $3 || nil return @sections when Regexp.new('/bar/([^;.,?]+)') @sections[:rest] = $1 return {:controller=>"Test", :action=>"glob"}.merge(@sections) else return {:controller=>'Noroutefound', :action=>'noroute'} end } *Simple Controllers* classes with built in render method and template handling with instance vars available in the views automatically. Merb also supports layouts. It will look for a layout named after your controller class first and then fall back to application.herb if no layout exists named after your controller. You can use render_no_layout or do layout :none right before you render class Test < Merb::Controller def hello # params, headers and cookies are available here. @name = params[:name] render end end Hello, <%= @name %> <%= @layout_content %>

<%= params.inspect %>

<%= cookies.inspect %>

<% 5.times do %>

Hello, <%= @name %>!

<% end %> You can also render partials like so: <%= partial(:comments) %> This assumes a _comments.rhtml file in the same view dir as the current controller/view Merb also allows for returning javascript instead of html for ajax actions You have to use the render_js instead of normal render def ajax_action @posts = Post.find :all render_js end # ajax_action.jerb $('comments').update('<%=js partial(:posts) %>'); # _posts.herb *Controllers also now have before filters* Use the before method in your controllers. before accepts either a symbol or a Proc/lambda object. If you give it a symbol it will call a method with the same name as the symbol. If you give it a proc that takes one argument it will call the proc with the current controller as that argument. class Foo < Merb::Controller before :setup_user before lambda {|c| c.headers['X-Foo] = 'bar' } def setup_user # blah blah end def regular_action # blah end end Sessions are available when you start merb with the -s flag. See sample app for migration too add session table. *The merb server* right now you add your routes in the appdir/dist/conf/router.rb file. So by default it runs on port 4000 $ cd /path/to/your/merb/app $ merb Or to start merb on a different port: $ merb -p 3500 To start a cluster of merb servers you specify the first port and then how many servers you want spawned. SO this command will start a merb instance on ports 3000, 3001, 3002 $ merb -p 3000 -c 3 To start a Merb IRB console where all your models and other classes are pre loaded use the -i flag $merb -i *File uploads* This is one of the things that Merb was written for. Rails doesn't allow multiple concurrent file uploads at once without blocking an entire rails backend for each file upload. Merb allows multiple file uploads at once. Start the server and browse to http://localhost:4000/files/start and you will get a file upload form. This uses the mongrel_upload_progress gem so that must be installed first. There is a very simple upload controller example that handles this upload with a progress bar. When a file is uploaded with Merb, it gets put in a Tempfile. So you just want to copy it to the right place on the filesystem. def upload puts params[:file].inspect FileUtils.mv params[:file][:tempfile].path, MERB_ROOT+"/uploads/#{params[:file][:filename]}" render end *Merb app layout* A Merb app contains everything it needs to run in production in the MERB_ROOT/dist directory. So for deployment you only need to deploy the dist dir. This keeps your test code and development plugins separate from your main app and lets you not deploy them to the live server. You deal with two things with this setup, MERB_ROOT and DIST_ROOT. MERB_ROOT is the root of the whole tree. And DISTROOT is MERB_ROOT+/dist You will cd into MERB_ROOT to run the merb command line. ANd when you deploy live you will put the dist dir into another empty MERB_ROOT on the production server. app_skeleton Rakefile README scripts test test_helper.rb fixtures spec unit plugins dist app controllers models views conf lib public plugins schema