Changeset 278

Show
Ignore:
Timestamp:
06/08/07 12:49:30 (1 year ago)
Author:
jeremymcanal..@gmail.com
Message:

Improved README markup; more markup and content improvements to come.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/README

    r226 r278  
    1  
    2 Copyright (c) 2006 Ezra Zygmuntowicz 
    3  
    4 Merb. 
    5  
    6 Lightweight MVC Ruby app server. For high performance dynamic pages. 
    7  
    8 ** Dependencies ** 
    9 mongrel 
    10 erubis 
    11 json 
    12 mime-types 
    13 archive-tar-minitar 
    14 rspec 
    15  
    16 Install these gems first then you can build the merb gem from svn trunk like so: 
    17 $ sudo gem install mongrel erubis json mime-types archive-tar-minitar rspec --include-dependencies 
    18 $ svn co http://svn.devjavu.com/merb/trunk merb 
    19 $ cd merb 
    20 $ rake install 
     1= Merb 
     2<em>Lightweight MVC Ruby app server. For high performance dynamic pages.</em> 
     3 
     4==== Dependencies 
     5Install these gems first: 
     6 
     7* mongrel 
     8* erubis 
     9* json 
     10* mime-types 
     11* archive-tar-minitar 
     12* rspec 
     13 
     14Then you can build the merb gem from svn trunk like so: 
     15 
     16  $ sudo gem install mongrel erubis json mime-types archive-tar-minitar rspec --include-dependencies 
     17  $ svn co http://svn.devjavu.com/merb/trunk merb 
     18  $ cd merb 
     19  $ rake install 
    2120 
    2221To generate a new merb app after the gem is installed: 
    23 $ merb -g myapp 
    24  
    25  
    26 **FEATURES**  
    27  
    28 *Mongrel handler*  
    29 built in that parses incoming requests 
    30 including multipart uploads and post as well as ?query=strings. Puts the 
     22 
     23  $ merb -g myapp 
     24 
     25To run your application, simply type +merb+ in the project directory. 
     26 
     27== Features  
     28 
     29=== Mongrel handler 
     30Merb has a Mongrel handler built in that parses incoming requests 
     31including multipart uploads and post as well as <tt>?query=strings</tt>. Puts the 
    3132params into params and the cookies into cookies when it instantiates your 
    3233controller class. 
    3334 
    34 *RouteMatcher and route compiler*  
     35=== RouteMatcher and route compiler 
    3536 
    3637Reads your route definition and compiles 
    3738a method on the fly that will match the request path against each route and do the right thing. 
    3839 
    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 
    42  
    43 Merb::RouteMatcher.prepare do |r| 
    44   r.resources :posts 
    45   r.default_routes 
    46   r.add '/', :controller => 'files', :action => 'index' 
    47 end 
    48  
    49 The r.default_routes routes adds the standard routes: 
    50  
    51 /controller/action/id.xml 
    52 /controller/action/id 
    53 /controller/action.xml 
    54 /controller/action 
    55 /controller.xml  # index action 
    56 /controller      # index action 
    57  
    58  
    59  
    60 *Controllers* 
     40=== _NEW_ RESTful Routes 
     41 
     42Note the <tt>r.resource :posts</tt> macro. That makes it possible to use a RESTful CRUD style controller for the posts resource 
     43 
     44        Merb::RouteMatcher.prepare do |r| 
     45          r.resources :posts 
     46          r.default_routes 
     47          r.add '/', :controller => 'files', :action => 'index' 
     48        end 
     49 
     50The <tt>r.default_routes</tt> routes adds the standard routes: 
     51 
     52        /controller/action/id.xml 
     53        /controller/action/id 
     54        /controller/action.xml 
     55        /controller/action 
     56        /controller.xml  # index action 
     57        /controller      # index action 
     58 
     59=== Controllers 
     60 
    6161Classes with built in render method and template handling 
    6262with instance vars available in the views automatically. Merb also supports  
    6363layouts. It will look for a layout named after your controller class first and 
    6464then fall back to application.herb if no layout exists named after your controller. 
    65 You can use render :layout => :none
     65You can use render <tt>:layout => :none</tt>
    6666 
    6767Merb does not automatically render for you in your controller actions, you have 
     
    7171the other hand, returns to the browser whatever the return value of your  
    7272controller’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  
     73now you can return any string from your action and that will be sent down  
    7474the pipe. So Merb’s render method just returns a string and needs to be the  
    7575last thing you call in your action. You can render multiple times and capture  
     
    8282That last point has some cool connotations if you think about it. Merb does  
    8383have a mutex lock around the call to your controller’s action anywhere that 
    84  you can call AR objects. Merb’s lock is way smaller then rails giant lock  
     84you can call AR objects. Merb’s lock is way smaller then rails giant lock  
    8585though and allows for many more concurrent requests to be handled by one  
    8686process. By returning a Proc object from your action, you allow merb to  
     
    9191 
    9292 
    93 class Test < Merb::Controller  
    94   def hello 
    95     # params, headers and cookies are available here. 
    96     @name = params[:name] 
    97     render  
    98   end  
    99 end 
     93       class Test < Merb::Controller  
     94         def hello 
     95           # params, headers and cookies are available here. 
     96           @name = params[:name] 
     97           render  
     98         end  
     99       end 
    100100 
    101101You can also render partials like so: 
    102 <%= partial(:comments) %> 
    103  
    104 This assumes a _comments.rhtml file in the same view dir as the current  
    105 controller/view 
     102 
     103        <%= partial(:comments) %> 
     104 
     105This assumes a <tt>_comments.rhtml</tt> file in the same view dir as the current  
     106controller/view. 
    106107 
    107108Partials compile the template ands returns a string. So you can also call 
    108109them and assign them to a var if you want: 
    109110 
    110 def someaction 
    111   @one = partial(:one) 
    112   @two = partial(:two) 
    113 end 
    114  
    115 partials can also render views from other controllers by specifying the path 
    116  
    117 partial('/shared/foo') 
    118  
    119  
    120 Merb also allows for returning javascript instead of html for ajax actions 
    121 You have to use the render_js instead of normal render 
    122  
    123 def ajax_action 
    124   @posts = Post.find :all 
    125   render_js 
    126 end 
    127  
    128 # ajax_action.jerb 
    129 $('comments').update('<%=js partial(:posts) %>'); 
    130  
    131 # _posts.herb 
    132 <ul> 
    133   <% @posts.each do |p| %> 
    134     <li> 
    135     <%= p.title %><br /> 
    136     <%= p.body %> 
    137     </li> 
    138   <% end %> 
    139 </ul>    
    140  
    141  
    142 *Restful Controllers* 
    143  
    144 restful controllers use a different dispatch system based on the request method verbs. Merb 
    145 supports multi return values based on the accept header via respond_to 
    146  
    147 class Posts < Merb::Controller 
    148   # GET /posts 
    149   # GET /posts.xml 
    150   def index 
    151     @posts = Post.find :all 
    152     respond_to {|format| 
    153       format.html { render } 
    154       format.js   { render :js => 'index' } 
    155       format.xml  { render :xml => @posts.to_xml } 
    156     } 
    157   end 
    158  
    159   # GET /posts/1 
    160   # GET /posts/1.xml 
    161   def show 
    162   end 
    163  
    164   # GET /posts/new 
    165   def new 
    166   end 
    167  
    168   # GET /posts/1;edit 
    169   def edit 
    170   end 
    171  
    172   # POST /posts 
    173   # POST /posts.xml 
    174   def create 
    175   end 
    176  
    177   # PUT /posts/1 
    178   # PUT /posts/1.xml 
    179   def update 
    180   end 
    181  
    182   # DELETE /posts/1 
    183   # DELETE /posts/1.xml 
    184   def destroy 
    185   end 
    186 end 
    187  
    188  
    189 *Controllers have powerful before and after filters* 
     111        def someaction 
     112          @one = partial(:one) 
     113          @two = partial(:two) 
     114        end 
     115 
     116Partials can also render views from other controllers by specifying the path: 
     117 
     118        partial('/shared/foo') 
     119 
     120Merb also allows for returning JavaScript instead of html for ajax actions 
     121You have to use the render_js instead of normal render: 
     122 
     123        def ajax_action 
     124          @posts = Post.find :all 
     125          render_js 
     126        end 
     127 
     128        # ajax_action.jerb 
     129        $('comments').update('<%=js partial(:posts) %>'); 
     130 
     131        # _posts.herb 
     132        <ul> 
     133          <% @posts.each do |p| %> 
     134            <li> 
     135            <%= p.title %><br /> 
     136            <%= p.body %> 
     137            </li> 
     138          <% end %> 
     139        </ul>    
     140 
     141The .jerb template is used for this purpose. 
     142 
     143==== RESTful Controllers 
     144 
     145RESTful controllers use a different dispatch system based on the request method verbs. Merb 
     146supports multi return values based on the accept header via +respond_to+. 
     147 
     148        class Posts < Merb::Controller 
     149          # GET /posts 
     150          # GET /posts.xml 
     151          def index 
     152            @posts = Post.find :all 
     153            respond_to {|format| 
     154              format.html { render } 
     155              format.js   { render :js => 'index' } 
     156              format.xml  { render :xml => @posts.to_xml } 
     157            } 
     158          end 
     159 
     160          # GET /posts/1 
     161          # GET /posts/1.xml 
     162          def show 
     163          end 
     164 
     165          # GET /posts/new 
     166          def new 
     167          end 
     168 
     169          # GET /posts/1;edit 
     170          def edit 
     171          end 
     172 
     173          # POST /posts 
     174          # POST /posts.xml 
     175          def create 
     176          end 
     177 
     178          # PUT /posts/1 
     179          # PUT /posts/1.xml 
     180          def update 
     181          end 
     182 
     183          # DELETE /posts/1 
     184          # DELETE /posts/1.xml 
     185          def destroy 
     186          end 
     187        end 
     188         
     189Learn more about this in the controller documentation. 
     190 
     191==== Before and after filters 
    190192 
    191193Use 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. 
    192194 
    193 class Foo < Merb::Controller 
     195       class Foo < Merb::Controller 
    194196  
    195   before :setup_user, :only => :foo 
    196   before lambda {|c| c.headers['X-Foo] = 'bar' }, :exclude => [:foo, :baz] 
    197  
    198   def setup_user 
    199     # blah blah 
    200   end 
    201  
    202   def foo 
    203     # blah 
    204   end 
    205  
    206   def regular_action 
    207     # blah 
    208   end 
    209  
    210 end 
     197         before :setup_user, :only => :foo 
     198         before lambda {|c| c.headers['X-Foo] = 'bar' }, :exclude => [:foo, :baz] 
     199 
     200         def setup_user 
     201           # blah blah 
     202         end 
     203 
     204         def foo 
     205           # blah 
     206         end 
     207 
     208         def regular_action 
     209           # blah 
     210         end 
     211 
     212       end 
    211213 
    212214To stop the before filter chain you use throw :halt with a few options: 
    213215 
    214 # halts the filter chain and calls filters_halted which you can override  
    215 # in your controller to specialize it. 
    216  
    217 throw :halt 
    218  
    219 # halts the filters and calls the method named after the symbol: 
    220  
    221 throw :halt, :other_action 
    222  
    223 # halts the filter chain and returns the result of the Proc being called 
    224  
    225 throw :halt, Proc.new{ |c| c.redirect "/foo" } 
    226  
    227 # halts the chain and returns whatever is in the string 
    228  
    229 throw :halt, "<h1>You don't have permissions dude!</h1>" 
    230  
    231 or even render templates: 
    232  
    233 throw :halt, render 'foo' 
    234 throw :halt, partial 'foo' 
    235  
    236 After filters accept a symbol, string or   Proc and call that proc with the controller: 
    237  
    238 after Proc.new {|c| Tidy.new(c.body) }, :only => :index 
     216        # halts the filter chain and calls filters_halted which you can override  
     217        # in your controller to specialize it. 
     218 
     219        throw :halt 
     220 
     221        # halts the filters and calls the method named after the symbol: 
     222 
     223        throw :halt, :other_action 
     224 
     225        # halts the filter chain and returns the result of the Proc being called 
     226 
     227        throw :halt, Proc.new{ |c| c.redirect "/foo" } 
     228 
     229        # halts the chain and returns whatever is in the string 
     230 
     231        throw :halt, "<h1>You don't have permissions dude!</h1>" 
     232 
     233        or even render templates: 
     234 
     235        throw :halt, render 'foo' 
     236        throw :halt, partial 'foo' 
     237 
     238After filters accept a symbol, string or Proc and call that proc with the controller: 
     239 
     240        after Proc.new {|c| Tidy.new(c.body) }, :only => :index 
     241 
     242=== Sessions 
    239243 
    240244Sessions are available when you start merb with the sql_session set to true or the  
    241245memory_session set to true. See generated app for migration too add session table. 
    242246 
    243 Helpers: dist/app/helpers/global_helper.rb will be available to all of your views. 
     247=== Helpers 
     248 
     249dist/app/helpers/global_helper.rb will be available to all of your views. 
    244250 Helpers named after your controller plus _helper.rb will be included in the views 
    245251 for that controller only. 
    246252 
    247 *The merb server* 
     253=== The +merb+ server 
     254 
    248255right now you add your routes in 
    249256the appdir/dist/conf/router.rb file. So by default it runs on port 4000 
    250257 
    251 $ cd /path/to/your/merb/app 
    252 $ merb   
     258       $ cd /path/to/your/merb/app 
     259       $ merb   
    253260 
    254261Or to start merb on a different port: 
    255 $ merb -p 3500 
     262 
     263        $ merb -p 3500 
    256264 
    257265To start a cluster of merb servers you specify the first port and then how many  
     
    2592673000, 3001, 3002 
    260268 
    261 $ merb -p 3000 -c 3 
     269       $ merb -p 3000 -c 3 
    262270 
    263271To start a Merb IRB console where all your models and other classes are pre loaded 
    264272use the -i flag 
    265273 
    266 $merb -i 
    267  
    268 *File uploads*  
     274       $merb -i 
     275 
     276=== File uploads 
    269277This is one of the things that Merb was written for. Rails doesn't allow  
    270278multiple concurrent file uploads at once without blocking an entire rails backend for each file upload. Merb allows multiple file uploads at once. 
    271  When a file is uploaded with Merb, it gets put in a Tempfile. So  
     279When a file is uploaded with Merb, it gets put in a Tempfile. So  
    272280you just want to copy it to the right place on the filesystem. 
    273281 
    274 def upload 
    275   puts params[:file].inspect 
     282       def upload 
     283         puts params[:file].inspect 
    276284   
    277   FileUtils.mv params[:file][:tempfile].path, MERB_ROOT+"/uploads/#{params[:file][:filename]}" 
    278  
    279   render 
    280 end 
     285         FileUtils.mv params[:file][:tempfile].path, MERB_ROOT+"/uploads/#{params[:file][:filename]}" 
     286 
     287         render 
     288       end 
    281289 
    282290A file upload will have a hash of params like this: 
    283 {  
    284 :filename => File.basename(filename),   
    285 :content_type => content_type,   
    286 :tempfile => <Tempfile>,  
    287 :size => File.size(body)  
    288 
    289  
    290 *Merb app layout*  
     291 
     292        {  
     293        :filename => File.basename(filename),   
     294        :content_type => content_type,   
     295        :tempfile => <Tempfile>,  
     296        :size => File.size(body)  
     297        } 
     298 
     299== Merb app layout 
    291300 
    292301A Merb app contains everything it needs to run in production in the  
     
    298307will put the dist dir into another empty MERB_ROOT on the production server. 
    299308 
    300 merb_app: 
    301   Rakefile 
    302   README 
    303   scripts 
    304   test 
    305     spec 
    306     unit 
    307   plugins 
    308   dist 
    309     app 
    310       controllers 
    311       models 
    312       views 
    313     conf 
    314     lib 
    315     public 
    316     plugins 
    317     schema 
     309       merb_app: 
     310         Rakefile 
     311         README 
     312         scripts 
     313         test 
     314           spec 
     315           unit 
     316         plugins 
     317         dist 
     318           app 
     319             controllers 
     320             models 
     321             views 
     322           conf 
     323           lib 
     324           public 
     325           plugins 
     326           schema