root/tags/0.3.6/README

Revision 279, 9.3 kB (checked in by e.@brainspl.at, 1 year ago)

a few session optimization, thanks for pushing me ara. session key generation used to be an orser of magnitude slower, now its fast. a few touchups elsewhere

  • Property svn:executable set to
Line 
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
20
21 To generate a new merb app after the gem is installed:
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
32 params into params and the cookies into cookies when it instantiates your
33 controller class.
34
35 === RouteMatcher and route compiler
36
37 Reads your route definition and compiles
38 a method on the fly that will match the request path against each route and do the right thing.
39
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::Router.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 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.herb if no layout exists named after your controller.
65 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.
81
82 That last point has some cool connotations if you think about it. Merb does
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 lock
85 though and allows for many more concurrent requests to be handled by one
86 process. By returning a Proc object from your action, you allow merb to
87 release the lock and the proc is called in multi threaded way. This allows
88 for all kinds of cool streaming and ‘futures’ where you return the proc and
89 release the mutex. It’s basically like handing over the proc to mongrel and
90 mongrel handles calling it in a thread safe manner.
91
92
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
100
101 You can also render partials like so:
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.
107
108 Partials compile the template ands returns a string. So you can also call
109 them and assign them to a var if you want:
110
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
192
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.
194
195         class Foo < Merb::Controller
196  
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
213
214 To stop the before filter chain you use throw :halt with a few options:
215
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
243
244 Sessions are available when you start merb with the sql_session set to true or the
245 memory_session set to true. See generated app for migration too add session table.
246
247 === Helpers
248
249 dist/app/helpers/global_helper.rb will be available to all of your views.
250  Helpers named after your controller plus _helper.rb will be included in the views
251  for that controller only.
252
253 === The +merb+ server
254
255 right now you add your routes in
256 the appdir/dist/conf/router.rb file. So by default it runs on port 4000
257
258         $ cd /path/to/your/merb/app
259         $ merb 
260
261 Or to start merb on a different port:
262
263         $ merb -p 3500
264
265 To start a cluster of merb servers you specify the first port and then how many
266 servers you want spawned. SO this command will start a merb instance on ports
267 3000, 3001, 3002
268
269         $ merb -p 3000 -c 3
270
271 To start a Merb IRB console where all your models and other classes are pre loaded
272 use the -i flag
273
274         $merb -i
275
276 === File uploads
277 This is one of the things that Merb was written for. Rails doesn't allow
278 multiple concurrent file uploads at once without blocking an entire rails backend for each file upload. Merb allows multiple file uploads at once.
279 When a file is uploaded with Merb, it gets put in a Tempfile. So
280 you just want to copy it to the right place on the filesystem.
281
282         def upload
283           puts params[:file].inspect
284  
285           FileUtils.mv params[:file][:tempfile].path, MERB_ROOT+"/uploads/#{params[:file][:filename]}"
286
287           render
288         end
289
290 A file upload will have a hash of params like this:
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
300
301 A Merb app contains everything it needs to run in production in the
302 MERB_ROOT/dist directory. So for deployment you only need to deploy the dist dir. This
303 keeps your test code and development plugins separate from your main app and lets you
304 not deploy them to the live server. You deal with two things with this setup, MERB_ROOT
305 and DIST_ROOT. MERB_ROOT is the root of the whole tree. And DISTROOT is MERB_ROOT+/dist
306 You will cd into MERB_ROOT to run the merb command line. ANd when you deploy live you
307 will put the dist dir into another empty MERB_ROOT on the production server.
308
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
Note: See TracBrowser for help on using the browser.