root/tags/0.4.0/README

Revision 801, 8.9 kB (checked in by iv..@gweezlebur.com, 1 year ago)

list json_pure as a dependency

  • 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 * json
9 * json_pure
10 * erubis
11 * mime-types
12 * rspec
13 * hpricot
14 * mocha
15 * rubigen
16 * haml
17 * markaby
18 * mailfactory
19 * activerecord (if you want to store sessions in a database)
20
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 -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 -g myapp
31
32 To run your application, simply type +merb+ in the project directory.
33
34 == Features
35
36 === Mongrel handler
37 Merb has a Mongrel handler built in that parses incoming requests
38 including multipart uploads and post as well as <tt>?query=strings</tt>. Puts the
39 params into params and the cookies into cookies when it instantiates your
40 controller class.
41
42 === RouteMatcher and route compiler
43
44 Reads your route definition and compiles
45 a method on the fly that will match the request path against each route and do the right thing.
46
47 === _NEW_ RESTful Routes
48
49 Note the <tt>r.resource :posts</tt> macro. That makes it possible to use a RESTful CRUD style controller for the posts resource
50
51         Merb::Router.prepare do |r|
52           r.resources :posts
53           r.default_routes
54           r.add '/', :controller => 'files', :action => 'index'
55         end
56
57 The <tt>r.default_routes</tt> routes adds the standard routes:
58
59         /controller/action/id.xml
60         /controller/action/id
61         /controller/action.xml
62         /controller/action
63         /controller.xml  # index action
64         /controller      # index action
65
66 === Controllers
67
68 Classes with built in render method and template handling
69 with instance vars available in the views automatically. Merb also supports
70 layouts. It will look for a layout named after your controller class first and
71 then fall back to application.html.erb if no layout exists named after your
72 controller. You can use render <tt>:layout => :none</tt>.
73
74 Merb does not automatically render for you in your controller actions, you have
75 to call render yourself. I consider this a big advantage over the way rails does
76 it for a few reasons. The main reason is that in rails you can only render once
77 per action, so it knows if you haven’t rendered it shoudl auto render. Merb on
78 the other hand, returns to the browser whatever the return value of your
79 controller’s action method is. This opens up more possibilities imho because
80 now you can return any string from your action and that will be sent down
81 the pipe. So Merb’s render method just returns a string and needs to be the
82 last thing you call in your action. You can render multiple times and capture
83 the results into @ivars and then render a master template with many embeded
84 templates. Also if you return a handle on a File or IO object from your action
85 then merb will hand that over to mongrel to be streamed out to the client. And
86 if you return a Proc object from your action, it will be called and the
87 return value sent to the client.
88
89 That last point has some cool connotations if you think about it. Merb does
90 have a mutex lock around the call to your controller’s action anywhere that
91 you can call AR objects. Merb’s lock is way smaller then rails giant lock
92 though and allows for many more concurrent requests to be handled by one
93 process. By returning a Proc object from your action, you allow merb to
94 release the lock and the proc is called in multi threaded way. This allows
95 for all kinds of cool streaming and ‘futures’ where you return the proc and
96 release the mutex. It’s basically like handing over the proc to mongrel and
97 mongrel handles calling it in a thread safe manner.
98
99
100         class Test < Merb::Controller
101           def hello
102             # params, headers and cookies are available here.
103             @name = params[:name]
104             render
105           end
106         end
107
108 You can also render partials like so:
109
110         <%= partial(:comments) %>
111
112 This assumes a <tt>_comments.rhtml</tt> file in the same view dir as the current
113 controller/view.
114
115 Partials compile the template ands returns a string. So you can also call
116 them and assign them to a var if you want:
117
118         def someaction
119           @one = partial(:one)
120           @two = partial(:two)
121         end
122
123 Partials can also render views from other controllers by specifying the path:
124
125         partial('/shared/foo')
126
127 Merb also allows for returning JavaScript instead of html for ajax actions
128 You have to use the render_js instead of normal render:
129
130         def ajax_action
131           @posts = Post.find :all
132           render_js
133         end
134
135         # ajax_action.jerb
136         $('comments').update('<%=js partial(:posts) %>');
137
138         # _posts.herb
139         <ul>
140           <% @posts.each do |p| %>
141             <li>
142             <%= p.title %><br />
143             <%= p.body %>
144             </li>
145           <% end %>
146         </ul>   
147
148 The .jerb template is used for this purpose.
149
150 ==== RESTful Controllers
151
152 RESTful controllers use a different dispatch system based on the request method verbs. Merb
153 supports multi return values based on the accept header via +respond_to+.
154
155         class Posts < Merb::Controller
156           # GET /posts
157           # GET /posts.xml
158           def index
159             @posts = Post.find :all
160             respond_to {|format|
161               format.html { render }
162               format.js   { render :js => :index }
163               format.xml  { render :xml => @posts.to_xml }
164             }
165           end
166
167           # GET /posts/1
168           # GET /posts/1.xml
169           def show
170           end
171
172           # GET /posts/new
173           def new
174           end
175
176           # GET /posts/1;edit
177           def edit
178           end
179
180           # POST /posts
181           # POST /posts.xml
182           def create
183           end
184
185           # PUT /posts/1
186           # PUT /posts/1.xml
187           def update
188           end
189
190           # DELETE /posts/1
191           # DELETE /posts/1.xml
192           def destroy
193           end
194         end
195        
196 Learn more about this in the controller documentation.
197
198 ==== Before and after filters
199
200 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.
201
202         class Foo < Merb::Controller
203  
204           before :setup_user, :only => :foo
205           before lambda {|c| c.headers['X-Foo] = 'bar' }, :exclude => [:foo, :baz]
206
207           def setup_user
208             # blah blah
209           end
210
211           def foo
212             # blah
213           end
214
215           def regular_action
216             # blah
217           end
218
219         end
220
221 To stop the before filter chain you use throw :halt with a few options:
222
223         # halts the filter chain and calls filters_halted which you can override
224         # in your controller to specialize it.
225
226         throw :halt
227
228         # halts the filters and calls the method named after the symbol:
229
230         throw :halt, :other_action
231
232         # halts the filter chain and returns the result of the Proc being called
233
234         throw :halt, Proc.new{ |c| c.redirect "/foo" }
235
236         # halts the chain and returns whatever is in the string
237
238         throw :halt, "<h1>You don't have permissions dude!</h1>"
239
240         or even render templates:
241
242         throw :halt, render 'foo'
243         throw :halt, partial 'foo'
244
245 After filters accept a symbol, string or Proc and call that proc with the controller:
246
247         after Proc.new {|c| Tidy.new(c.body) }, :only => :index
248
249 === Sessions
250
251 Sessions are available when you start merb with the sql_session set to true or the
252 memory_session set to true. See generated app for migration too add session table.
253
254 === Helpers
255
256 app/helpers/global_helper.rb will be available to all of your views.
257  Helpers named after your controller plus _helper.rb will be included in the views
258  for that controller only.
259
260 === The +merb+ server
261
262 right now you add your routes in
263 the appdir/config/router.rb file. So by default it runs on port 4000
264
265         $ cd /path/to/your/merb/app
266         $ merb 
267
268 Or to start merb on a different port:
269
270         $ merb -p 3500
271
272 To start a cluster of merb servers you specify the first port and then how many
273 servers you want spawned. SO this command will start a merb instance on ports
274 3000, 3001, 3002
275
276         $ merb -p 3000 -c 3
277
278 To start a Merb IRB console where all your models and other classes are pre loaded
279 use the -i flag
280
281         $merb -i
282
283 === File uploads
284 This is one of the things that Merb was written for. Rails doesn't allow
285 multiple concurrent file uploads at once without blocking an entire rails backend for each file upload. Merb allows multiple file uploads at once.
286 When a file is uploaded with Merb, it gets put in a Tempfile. So
287 you just want to copy it to the right place on the filesystem.
288
289         def upload
290           puts params[:file].inspect
291  
292           FileUtils.mv params[:file][:tempfile].path, MERB_ROOT+"/uploads/#{params[:file][:filename]}"
293
294           render
295         end
296
297 A file upload will have a hash of params like this:
298
299         {
300         :filename => File.basename(filename), 
301         :content_type => content_type, 
302         :tempfile => <Tempfile>,
303         :size => File.size(body)
304         }
305
306 == Merb app layout
307
308         merb_app:
309
310           app
311             controllers
312             models
313             views
314             parts
315             mailers
316           config
317           lib
318           public
319           schema
320           Rakefile
321           scripts
322           test
323             spec
324             unit
325           plugins
Note: See TracBrowser for help on using the browser.