Changeset 1038

Show
Ignore:
Timestamp:
11/23/07 13:08:05 (1 year ago)
Author:
e.@brainspl.at
Message:

update readme docs. closes #328

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/README

    r979 r1038  
    11= Merb 
    22 
    3 ==== FrameWork Development Dependencies 
    4  
    5 Install these gems first: 
     3Like Ruby on Rails, Merb (Mongrel + ERB) is an MVC framework. Unlike Rails, Merb is ORM-agnostic, JavaScript library agnostic, and template language agnostic, preferring plugins that add in support for a particular feature rather than trying to produce a monolithic library with everything in the core. In fact, this is a guiding principle of the project, which has led to third-party support for the ActiveRecord, DataMapper, and Sequel ORMs. 
     4 
     5In addition, it means that the core code in Merb is kept simple and well organised. This has multiple benefits. It means it's faster for one thing. It's also easier to understand, maintain and extend. 
     6 
     7=== Get Merb 
     8 
     9The simplest way to get Merb is to install the gem: 
     10 
     11  $ sudo gem install merb --include-dependencies 
     12   
     13If you want to contribute (or just use the latest code), you can build the gem from the svn trunk: 
     14 
     15  $ sudo gem install mongrel json json_pure erubis mime-types rspec hpricot mocha rubigen haml markaby mailfactory Ruby2Ruby -y 
     16  $ svn co http://svn.devjavu.com/merb/trunk merb 
     17  $ cd merb 
     18  $ rake install 
     19 
     20To generate a new merb app after the gem is installed: 
     21   
     22  $ merb myapp 
     23 
     24==== Dependencies 
     25 
     26Currently, Merb itself depends on the following gems: 
    627 
    728* mongrel 
     
    1940* Ruby2Ruby 
    2041 
    21 Then you can build the merb gem from svn trunk like so: 
    22  
    23   $ sudo gem install mongrel json json_pure erubis mime-types rspec hpricot mocha rubigen haml markaby mailfactory Ruby2Ruby -y 
    24   $ svn co http://svn.devjavu.com/merb/trunk merb 
    25   $ cd merb 
    26   $ rake install 
    27  
    28 To generate a new merb app after the gem is installed: 
    29  
    30   $ merb  myapp 
     42You will also probably need to install your ORM of choice as well as any gem plugins you want to use (see below). 
    3143 
    3244=== The +merb+ server 
     
    5466         
    5567To see all the available command line flags use: 
     68 
     69        $ merb -h 
     70                 
     71         
     72== Using Merb 
     73 
     74Merb uses the Model-View-Controller (MVC) pattern.  Incoming requests are matched in the Router and 
     75directed to an appropriate controller action. 
     76 
     77=== Model 
     78 
     79Merb does not come with its own model layer.  While you are free to use whatever data system you like, 
     80the merb core team does maintain plugins for the following Object Relational Mappers (ORM's): 
     81 
     82ActiveRecord:: The same ORM that Rails uses. (<tt>sudo gem install merb_activerecord</tt>) 
     83DataMapper:: Fairly new ORM. (<tt>sudo gem install merb_datamapper</tt>) 
     84Sequel:: Fairly new ORM. (<tt>sudo gem install merb_sequel</tt>) 
     85 
     86To use your choice ORM, install the appropriate gem and uncomment the appropriate +use_orm+ line in 
     87MERB_ROOT/config/dependencies.rb 
     88 
     89=== Controllers 
     90 
     91(MERB_ROOT/app/controllers/*) 
     92 
     93Merb controllers inherit from Merb::Controller and contain built in view/template rendering. 
     94Incoming requests are usually mapped to a specific method in a controller.  For example, using 
     95the default routes, a request to http://www.yourapp.com/posts/show/1 would call the the #show 
     96method of your PostsController (and params[:id] would = 1.) 
     97 
     98The return value of your action function gets sent back to the client as the view.  In most cases, 
     99you are going to want to end your functions with a call to +render+.  By default, +render+ will 
     100render the view template associated with your action (in default merb that would be  
     101MERB_ROOT/app/views/<controller>/<action>.html.erb - see the View section for more info.) 
     102 
     103Controllers can be generated by calling MERB_ROOT/script/generate controller ControllerName. 
     104By default, generated controllers inherit from the Application class (MERB_ROOT/app/controllers/application.rb) 
     105which itself inherits from Merb:Controller.  Application is a good place to put code pertinent to all controllers. 
     106An example would be setting a filter to check if a user is logged in or to preload user data for each controller. 
     107 
     108==== +before+ and +after+ filters 
     109 
     110Use the +before+ method in your controllers. +before+ accepts either a symbol, string 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. You can use :only and :exclude as options to your filters to exclude or include actions from certain filters. :only and :exclude take :symbols or [:sym, :sam] array of symbols. 
     111 
     112        class Foo < Merb::Controller 
    56113  
    57   $ merb -h      
    58  
    59 === Controllers 
    60  
    61 Classes with built in render method and template handling 
    62 with instance vars available in the views automatically. Merb also supports  
    63 layouts. It will look for a layout named after your controller class first and 
    64 then fall back to application.html.erb if no layout exists named after your 
    65 controller. You can use render <tt>:layout => :none</tt>. 
    66  
    67 Merb does not automatically render for you in your controller actions, you have 
    68 to call render yourself. I consider this a big advantage over the way rails does  
    69 it for a few reasons. The main reason is that in rails you can only render once  
    70 per action, so it knows if you haven’t rendered it shoudl auto render. Merb on  
    71 the other hand, returns to the browser whatever the return value of your  
    72 controller’s action method is. This opens up more possibilities imho because 
    73 now you can return any string from your action and that will be sent down  
    74 the pipe. So Merb’s render method just returns a string and needs to be the  
    75 last thing you call in your action. You can render multiple times and capture  
    76 the results into @ivars and then render a master template with many embeded  
    77 templates. Also if you return a handle on a File or IO object from your action  
    78 then merb will hand that over to mongrel to be streamed out to the client. And  
    79 if you return a Proc object from your action, it will be called and the  
    80 return value sent to the client. 
     114          before :setup_user, :only => :foo 
     115          before lambda {|c| c.headers['X-Foo] = 'bar' }, :exclude => [:foo, :baz] 
     116 
     117          def setup_user 
     118            # blah blah 
     119          end 
     120 
     121          def foo 
     122            # blah 
     123          end 
     124 
     125          def regular_action 
     126            # blah 
     127          end 
     128 
     129        end 
     130 
     131To stop the before filter chain you use throw :halt with a few options: 
     132 
     133        # halts the filter chain and calls filters_halted which you can override  
     134        # in your controller to specialize it. 
     135 
     136        throw :halt 
     137 
     138        # halts the filters and calls the method named after the symbol: 
     139 
     140        throw :halt, :other_action 
     141 
     142        # halts the filter chain and returns the result of the Proc being called 
     143 
     144        throw :halt, Proc.new{ |c| c.redirect "/foo" } 
     145 
     146        # halts the chain and returns whatever is in the string 
     147 
     148        throw :halt, "<h1>You don't have permissions dude!</h1>" 
     149 
     150        or even render templates: 
     151 
     152        throw :halt, render 'foo' 
     153        throw :halt, partial 'foo' 
     154 
     155After filters accept a symbol, string or Proc and call that proc with the controller: 
     156 
     157        after Proc.new {|c| Tidy.new(c.body) }, :only => :index 
     158 
     159 
     160=== Views 
     161 
     162(MERB_ROOT/app/views/*) 
     163 
     164A view can be loosely defined as any data sent back to the client (a "view" of your data.) 
     165By default, Merb controllers send the return value of your controller action as the view. 
     166The Controller#render method simply renders the specified view and returns it as a string. 
     167By default, a call to +render+ without any options renders the view template associated 
     168with that controller action.  Using the default ERB templating system, this means that a 
     169call to +render+ in Posts#index would render the file MERB_ROOT/app/views/posts/index.html.erb 
     170 
     171==== Layouts 
     172 
     173(MERB_ROOT/app/views/layout/*) 
     174 
     175Layouts are generic templates in which your specific view templates are rendered.  A sample 
     176layout could look like: 
     177 
     178  <html> 
     179    <head><title>My Application Layout</title></head> 
     180    <body> 
     181      <img src="header" /> 
     182      <div id="content"> 
     183        <%= catch_content :layout %> 
     184      </div> 
     185    </body> 
     186  </html> 
     187 
     188By default, +render+ will look for a corresponding layout for your controller in the form 
     189of MERB_ROOT/app/views/layout/<controller>.html.erb .  If no specific layout is present, 
     190+render+ will attempt to use MERB_ROOT/app/view/layout/application.html.erb 
     191 
     192<i>See #render for more details/options, as well as how to use different templating systems 
     193in your app.</i> 
     194 
     195You can return several different types of values from your controller actions: 
     196 
     197* String: Any string will get sent to the browser as standard text/html 
     198* File/IO: Any file descriptor will get handed over to mongrel to be streamed to the client. 
     199* Proc Object: The object will be called and the return value sent to the client. 
    81200 
    82201That last point has some cool connotations if you think about it. Merb does  
     
    90209mongrel handles calling it in a thread safe manner. 
    91210 
    92  
    93 ==== Before and after filters 
    94  
    95 Use the before method in your controllers. before accepts either a symbol, string 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. You can use :only and :exclude as options to your filters to exclude or include actionsfrom certain filters. :only and :exclude take :symbols or [:sym, :sam] array of symbols. 
    96  
    97         class Foo < Merb::Controller 
    98   
    99           before :setup_user, :only => :foo 
    100           before lambda {|c| c.headers['X-Foo] = 'bar' }, :exclude => [:foo, :baz] 
    101  
    102           def setup_user 
    103             # blah blah 
    104           end 
    105  
    106           def foo 
    107             # blah 
    108           end 
    109  
    110           def regular_action 
    111             # blah 
    112           end 
    113  
    114         end 
    115  
    116 To stop the before filter chain you use throw :halt with a few options: 
    117  
    118         # halts the filter chain and calls filters_halted which you can override  
    119         # in your controller to specialize it. 
    120  
    121         throw :halt 
    122  
    123         # halts the filters and calls the method named after the symbol: 
    124  
    125         throw :halt, :other_action 
    126  
    127         # halts the filter chain and returns the result of the Proc being called 
    128  
    129         throw :halt, Proc.new{ |c| c.redirect "/foo" } 
    130  
    131         # halts the chain and returns whatever is in the string 
    132  
    133         throw :halt, "<h1>You don't have permissions dude!</h1>" 
    134  
    135         or even render templates: 
    136  
    137         throw :halt, render 'foo' 
    138         throw :halt, partial 'foo' 
    139  
    140 After filters accept a symbol, string or Proc and call that proc with the controller: 
    141  
    142         after Proc.new {|c| Tidy.new(c.body) }, :only => :index 
    143  
    144211=== Helpers 
     212 
     213(MERB_ROOT/app/helpers/*) 
    145214 
    146215app/helpers/global_helper.rb will be available to all of your views. 
     
    173242          app 
    174243            controllers 
     244            helpers 
     245            mailers          
    175246            models 
     247            parts 
    176248            views 
    177             parts 
    178             mailers 
    179249          config 
     250          gems 
    180251          lib 
     252          log 
    181253          public 
    182           schema 
    183254          Rakefile 
    184           scripts 
     255          script 
     256          spec 
    185257          test 
    186             spec 
    187258            unit 
    188           plugins 
  • trunk/Rakefile

    r1001 r1038  
    2121@windows = (PLATFORM =~ /win32/) 
    2222 
    23 SUDO = @windows ? "" : (ENV["SUDO_COMMAND"] || "sudo") 
     23SUDO = @windows ? "" : (ENV["SUDO_COMMAND"] && "sudo") 
    2424 
    2525setup_clean [ "pkg", "lib/*.bundle", "*.gem", "doc/rdoc", ".config", 'coverage', "cache"] 
  • trunk/lib/merb/mongrel_handler.rb

    r793 r1038  
    4343  # then mongrel will serve the file directly and your controller can go on 
    4444  # processing other requests. 
    45   def process(request, response)     
     45  def process(request, response)  
     46    return if response.socket.closed? 
     47        
    4648    start      = Time.now 
    4749    benchmarks = {} 
    48      
    49     return if response.socket.closed? 
    5050     
    5151    MERB_LOGGER.info("\nRequest: REQUEST_URI: #{