Changeset 278
- Timestamp:
- 06/08/07 12:49:30 (1 year ago)
- Files:
-
- trunk/README (modified) (6 diffs)
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 5 Install these gems first: 6 7 * mongrel 8 * erubis 9 * json 10 * mime-types 11 * archive-tar-minitar 12 * rspec 13 14 Then 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 21 20 22 21 To 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 25 To run your application, simply type +merb+ in the project directory. 26 27 == Features 28 29 === Mongrel handler 30 Merb has a Mongrel handler built in that parses incoming requests 31 including multipart uploads and post as well as <tt>?query=strings</tt>. Puts the 31 32 params into params and the cookies into cookies when it instantiates your 32 33 controller class. 33 34 34 *RouteMatcher and route compiler* 35 === RouteMatcher and route compiler 35 36 36 37 Reads your route definition and compiles 37 38 a method on the fly that will match the request path against each route and do the right thing. 38 39 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 42 Note 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 50 The <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 61 61 Classes with built in render method and template handling 62 62 with instance vars available in the views automatically. Merb also supports 63 63 layouts. It will look for a layout named after your controller class first and 64 64 then fall back to application.herb if no layout exists named after your controller. 65 You can use render :layout => :none.65 You can use render <tt>:layout => :none</tt>. 66 66 67 67 Merb does not automatically render for you in your controller actions, you have … … 71 71 the other hand, returns to the browser whatever the return value of your 72 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 down73 now you can return any string from your action and that will be sent down 74 74 the pipe. So Merbâs render method just returns a string and needs to be the 75 75 last thing you call in your action. You can render multiple times and capture … … 82 82 That last point has some cool connotations if you think about it. Merb does 83 83 have 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 lock84 you can call AR objects. Merbâs lock is way smaller then rails giant lock 85 85 though and allows for many more concurrent requests to be handled by one 86 86 process. By returning a Proc object from your action, you allow merb to … … 91 91 92 92 93 class Test < Merb::Controller94 def hello95 # params, headers and cookies are available here.96 @name = params[:name]97 render98 end99 end93 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 100 100 101 101 You 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 105 This assumes a <tt>_comments.rhtml</tt> file in the same view dir as the current 106 controller/view. 106 107 107 108 Partials compile the template ands returns a string. So you can also call 108 109 them and assign them to a var if you want: 109 110 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 116 Partials can also render views from other controllers by specifying the path: 117 118 partial('/shared/foo') 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 The .jerb template is used for this purpose. 142 143 ==== RESTful Controllers 144 145 RESTful controllers use a different dispatch system based on the request method verbs. Merb 146 supports 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 189 Learn more about this in the controller documentation. 190 191 ==== Before and after filters 190 192 191 193 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. 192 194 193 class Foo < Merb::Controller195 class Foo < Merb::Controller 194 196 195 before :setup_user, :only => :foo196 before lambda {|c| c.headers['X-Foo] = 'bar' }, :exclude => [:foo, :baz]197 198 def setup_user199 # blah blah200 end201 202 def foo203 # blah204 end205 206 def regular_action207 # blah208 end209 210 end197 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 211 213 212 214 To stop the before filter chain you use throw :halt with a few options: 213 215 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 238 After 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 239 243 240 244 Sessions are available when you start merb with the sql_session set to true or the 241 245 memory_session set to true. See generated app for migration too add session table. 242 246 243 Helpers: dist/app/helpers/global_helper.rb will be available to all of your views. 247 === Helpers 248 249 dist/app/helpers/global_helper.rb will be available to all of your views. 244 250 Helpers named after your controller plus _helper.rb will be included in the views 245 251 for that controller only. 246 252 247 *The merb server* 253 === The +merb+ server 254 248 255 right now you add your routes in 249 256 the appdir/dist/conf/router.rb file. So by default it runs on port 4000 250 257 251 $ cd /path/to/your/merb/app252 $ merb258 $ cd /path/to/your/merb/app 259 $ merb 253 260 254 261 Or to start merb on a different port: 255 $ merb -p 3500 262 263 $ merb -p 3500 256 264 257 265 To start a cluster of merb servers you specify the first port and then how many … … 259 267 3000, 3001, 3002 260 268 261 $ merb -p 3000 -c 3269 $ merb -p 3000 -c 3 262 270 263 271 To start a Merb IRB console where all your models and other classes are pre loaded 264 272 use the -i flag 265 273 266 $merb -i267 268 *File uploads* 274 $merb -i 275 276 === File uploads 269 277 This is one of the things that Merb was written for. Rails doesn't allow 270 278 multiple 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. So279 When a file is uploaded with Merb, it gets put in a Tempfile. So 272 280 you just want to copy it to the right place on the filesystem. 273 281 274 def upload275 puts params[:file].inspect282 def upload 283 puts params[:file].inspect 276 284 277 FileUtils.mv params[:file][:tempfile].path, MERB_ROOT+"/uploads/#{params[:file][:filename]}"278 279 render280 end285 FileUtils.mv params[:file][:tempfile].path, MERB_ROOT+"/uploads/#{params[:file][:filename]}" 286 287 render 288 end 281 289 282 290 A 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 291 300 292 301 A Merb app contains everything it needs to run in production in the … … 298 307 will put the dist dir into another empty MERB_ROOT on the production server. 299 308 300 merb_app:301 Rakefile302 README303 scripts304 test305 spec306 unit307 plugins308 dist309 app310 controllers311 models312 views313 conf314 lib315 public316 plugins317 schema309 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
