root/tags/0.2.0/README

Revision 169, 8.4 kB (checked in by e.@brainspl.at, 2 years ago)

Merb just got RESTFULL. You can now use r.resource :posts in yoru router definition to get full rest style dispatching.

  • Property svn:executable set to
Line 
1 <pre>
2 Copyright (c) 2006 Ezra Zygmuntowicz
3
4 Merb. Mongrel+Erb
5
6 Little bitty lightweight ruby app server. For when you really need performance
7 for simple dynamic pages.
8
9 ** Dependencies **
10 mongrel
11 erubis
12 json or fjson
13 mime-types
14 archive-tar-minitar
15 rspec
16
17 Install these gems first then you can build the merb gem from svn trunk like so:
18 $ sudo gem install mongrel erubis json mime-types archive-tar-minitar rspec --include-dependencies
19 $ svn co http://svn.devjavu.com/merb/trunk merb
20 $ cd merb
21 $ rake install
22
23 To generate a new merb app after the gem is installed:
24 $ merb -g myapp
25
26
27 **FEATURES**
28
29 *Mongrel handler*
30 built in that parses incoming requests
31 including multipart uploads and post as well as ?query=strings. 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 Reads your route definition and compiles
37 a method on the fly that will match the request path against each route and do the right thing.
38
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.resource :posts
45   r.add '/:controller/:action/:id'
46   r.add '/', :controller => 'files', :action => 'index'
47 end
48
49 Will be compiled and defined as a method with this lambda as the body:
50
51 lambda{|path|
52   case path
53   when Regexp.new('/posts/([^/,?]+)[;]edit')
54     @sections[:id] = $1
55     return {:rest=>true, :controller=>"posts", :allowed=>{:get=>"edit"}}.update(@sections)
56   when Regexp.new('/posts/new[;]([^/,?]+)')
57     @sections[:action] = $1
58     return {:rest=>true, :controller=>"posts", :allowed=>{:post=>"new", :get=>"new", :delete=>"new", :put=>"new"}}.update(@sections)
59   when Regexp.new('/posts/new')
60     return {:rest=>true, :controller=>"posts", :allowed=>{:get=>"new"}}.update(@sections)
61   when Regexp.new('/posts/([^/,?]+)\.([^/,?]+)')
62     @sections[:id] = $1
63     @sections[:format] = $2
64     return {:rest=>true, :controller=>"posts", :allowed=>{:get=>"show", :delete=>"destroy", :put=>"update"}}.update(@sections)
65   when Regexp.new('/posts\.([^/,?]+)')
66     @sections[:format] = $1
67     return {:rest=>true, :controller=>"posts", :allowed=>{:post=>"create", :get=>"index"}}.update(@sections)
68   when Regexp.new('/posts/([^/,?]+)')
69     @sections[:id] = $1
70     return {:rest=>true, :controller=>"posts", :allowed=>{:get=>"show", :delete=>"destroy", :put=>"update"}}.update(@sections)
71   when Regexp.new('/posts/?')
72     return {:rest=>true, :controller=>"posts", :allowed=>{:post=>"create", :get=>"index"}}.update(@sections)
73   when /\A\/([^\/;.,?]+)(?:\/?\Z|\/([^\/;.,?]+)\/?)(?:\/?\Z|\/([^\/;.,?]+)\/?)\Z/
74       @sections[:controller] = $1
75       @sections[:action] = $2 || 'index'
76       @sections[:id] = $3 if $3
77       return @sections
78   when Regexp.new('/')
79     return {:controller=>"files", :action=>"index"}.update(@sections)
80   else
81     return {:controller=>'Noroutefound', :action=>'noroute'}
82   end
83 }
84
85
86 *Restful Controller*
87
88 restful controllers use a different dispatch system based on the request method verbs.
89
90 class Posts < Merb::Controller
91   # GET /posts
92   # GET /posts.xml
93   def index
94   end
95
96   # GET /posts/1
97   # GET /posts/1.xml
98   def show
99   end
100
101   # GET /posts/new
102   def new
103   end
104
105   # GET /posts/1;edit
106   def edit
107   end
108
109   # POST /posts
110   # POST /posts.xml
111   def create
112   end
113
114   # PUT /posts/1
115   # PUT /posts/1.xml
116   def update
117   end
118
119   # DELETE /posts/1
120   # DELETE /posts/1.xml
121   def destroy
122   end
123 end
124
125
126 *Simple Controllers*
127 classes with built in render method and template handling
128 with instance vars available in the views automatically. Merb also supports
129 layouts. It will look for a layout named after your controller class first and
130 then fall back to application.herb if no layout exists named after your controller.
131 You can use render_no_layout or do render :layout => :none
132
133
134 class Test < Merb::Controller
135   def hello
136     # params, headers and cookies are available here.
137     @name = params[:name]
138     render
139   end
140 end
141
142 You can also render partials like so:
143 <%= partial(:comments) %>
144 This assumes a _comments.rhtml file in the same view dir as the current
145 controller/view
146
147 Partials compile the template ands returns a string. So you can also call
148 them and assign them to a var if you want:
149
150 def someaction
151   @one = partial(:one)
152   @two = partial(:two)
153 end
154
155 partials can also render views from other controllers by specifying the path
156
157 partial('/shared/foo')
158
159
160 Merb also allows for returning javascript instead of html for ajax actions
161 You have to use the render_js instead of normal render
162
163 def ajax_action
164   @posts = Post.find :all
165   render_js
166 end
167
168 # ajax_action.jerb
169 $('comments').update('<%=js partial(:posts) %>');
170
171 # _posts.herb
172 <ul>
173   <% @posts.each do |p| %>
174     <li>
175     <%= p.title %><br />
176     <%= p.body %>
177     </li>
178   <% end %>
179 </ul>   
180
181
182 *Controllers have powerful before and after filters*
183
184 Use the before method in your controllers. before accepts either a symbol
185 or a Proc/lambda object. If you give it a symbol it will call a method with
186 the same name as the symbol. If you give it a proc that takes one argument
187 it will call the proc with the current controller as that argument. You can
188 use :only and :exclude as options to your filters to exclude or include actionsfrom certain filters. :only and :exclude take :symbols or [:sym, :sam]
189 array of symbols.
190
191 class Foo < Merb::Controller
192  
193   before :setup_user, :only => :foo
194   before lambda {|c| c.headers['X-Foo] = 'bar' }, :exclude => [:foo, :baz]
195
196   def setup_user
197     # blah blah
198   end
199
200   def foo
201     # blah
202   end
203
204   def regular_action
205     # blah
206   end
207
208 end
209
210 To stop the before filter chain you use throw :halt with a few options:
211
212 # halts the filter chain and calls filters_halted which you can override
213 # in your controller to specialize it.
214
215 throw :halt
216
217 # halts the filters and calls the method named after the symbol:
218
219 throw :halt, :other_action
220
221 # halts the filter chain and returns the result of the Proc being called
222
223 throw :halt, Proc.new{ |c| c.redirect "/foo" }
224
225 # halts the chain and returns whatever is in the string
226
227 throw :halt, "<h1>You don't have permissions IDIOT!</h1>"
228
229 or even render templates:
230
231 throw :halt, render 'foo'
232 throw :halt, partial 'foo'
233
234 After filters only accept a Proc and call that proc with the controller:
235
236 after Proc.new {|c| Tidy.new(c.body) }, :only => :index
237
238 Sessions are available when you start merb with the sql_session set to true or the memory_session set to true. See generated app for migration too add session table.
239
240 Helpers: dist/app/helpers/global_helper.rb will be available to all of your views. Helpers named afdter your controller plus _helper.rb will be included in the views for that controller only.
241
242
243 *The merb server*
244 right now you add your routes in
245 the appdir/dist/conf/router.rb file. So by default it runs on port 4000
246
247 $ cd /path/to/your/merb/app
248 $ merb 
249
250 Or to start merb on a different port:
251 $ merb -p 3500
252
253 To start a cluster of merb servers you specify the first port and then how many
254 servers you want spawned. SO this command will start a merb instance on ports
255 3000, 3001, 3002
256
257 $ merb -p 3000 -c 3
258
259 To start a Merb IRB console where all your models and other classes are pre loaded
260 use the -i flag
261
262 $merb -i
263
264 *File uploads*
265 This is one of the things that Merb was written for. Rails doesn't allow
266 multiple concurrent file uploads at once without blocking an entire rails backend for each file upload. Merb allows multiple file uploads at once.
267 progress bar. When a file is uploaded with Merb, it gets put in a Tempfile. So
268 you just want to copy it to the right place on the filesystem.
269
270 def upload
271   puts params[:file].inspect
272  
273   FileUtils.mv params[:file][:tempfile].path, MERB_ROOT+"/uploads/#{params[:file][:filename]}"
274
275   render
276 end
277
278
279 *Merb app layout*
280
281 A Merb app contains everything it needs to run in production in the
282 MERB_ROOT/dist directory. So for deployment you only need to deploy the dist dir. This
283 keeps your test code and development plugins separate from your main app and lets you
284 not deploy them to the live server. You deal with two things with this setup, MERB_ROOT
285 and DIST_ROOT. MERB_ROOT is the root of the whole tree. And DISTROOT is MERB_ROOT+/dist
286 You will cd into MERB_ROOT to run the merb command line. ANd when you deploy live you
287 will put the dist dir into another empty MERB_ROOT on the production server.
288
289 merb_app:
290   Rakefile
291   README
292   scripts
293   test
294     spec
295     unit
296   plugins
297   dist
298     app
299       controllers
300       models
301       views
302     conf
303     lib
304     public
305     plugins
306     schema
307 </pre>
Note: See TracBrowser for help on using the browser.