.html.erb - see the View section for more info.)
Controllers can be generated by calling Merb.root/script/generate controller ControllerName.
By default, generated controllers inherit from the Application class (Merb.root/app/controllers/application.rb)
which itself inherits from Merb:Controller. Application is a good place to put code pertinent to all controllers.
An example would be setting a filter to check if a user is logged in or to preload user data for each controller.
==== +before+ and +after+ filters
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 actions from certain filters. :only and :exclude take :symbols or [:sym, :sam] array of symbols.
class Foo < Merb::Controller
before :setup_user, :only => :foo
before lambda {|c| c.headers['X-Foo] = 'bar' }, :exclude => [:foo, :baz]
def setup_user
# blah blah
end
def foo
# blah
end
def regular_action
# blah
end
end
To stop the before filter chain you use throw :halt with a few options:
# halts the filter chain and calls filters_halted which you can override
# in your controller to specialize it.
throw :halt
# halts the filters and calls the method named after the symbol:
throw :halt, :other_action
# halts the filter chain and returns the result of the Proc being called
throw :halt, Proc.new{ |c| c.redirect "/foo" }
# halts the chain and returns whatever is in the string
throw :halt, "You don't have permissions dude!
"
or even render templates:
throw :halt, render 'foo'
throw :halt, partial 'foo'
After filters accept a symbol, string or Proc and call that proc with the controller:
after Proc.new {|c| Tidy.new(c.body) }, :only => :index
=== Views
(Merb.root/app/views/*)
A view can be loosely defined as any data sent back to the client (a "view" of your data.)
By default, Merb controllers send the return value of your controller action as the view.
The Controller#render method simply renders the specified view and returns it as a string.
By default, a call to +render+ without any options renders the view template associated
with that controller action. Using the default ERB templating system, this means that a
call to +render+ in Posts#index would render the file Merb.root/app/views/posts/index.html.erb
==== Layouts
(Merb.root/app/views/layout/*)
Layouts are generic templates in which your specific view templates are rendered. A sample
layout could look like:
My Application Layout
<%= catch_content :layout %>
By default, +render+ will look for a corresponding layout for your controller in the form
of Merb.root/app/views/layout/.html.erb . If no specific layout is present,
+render+ will attempt to use Merb.root/app/view/layout/application.html.erb
See #render for more details/options, as well as how to use different templating systems
in your app.
You can return several different types of values from your controller actions:
* String: Any string will get sent to the browser as standard text/html
* File/IO: Any file descriptor will get handed over to mongrel to be streamed to the client.
* Proc Object: The object will be called and the return value sent to the client.
That last point has some cool connotations if you think about it. Merb does
have a mutex lock around the call to your controller’s action anywhere that
you can call AR objects. Merb’s lock is way smaller then rails giant lock
though and allows for many more concurrent requests to be handled by one
process. By returning a Proc object from your action, you allow merb to
release the lock and the proc is called in multi threaded way. This allows
for all kinds of cool streaming and ‘futures’ where you return the proc and
release the mutex. It’s basically like handing over the proc to mongrel and
mongrel handles calling it in a thread safe manner.
=== Helpers
(Merb.root/app/helpers/*)
app/helpers/global_helper.rb will be available to all of your views.
Helpers named after your controller plus _helper.rb will be included in the views
for that controller only.
=== File uploads
When a file is uploaded with Merb, it gets put in a Tempfile. So
you just want to copy it to the right place on the filesystem.
def upload
puts params[:file].inspect
FileUtils.mv params[:file][:tempfile].path, Merb.root+"/uploads/#{params[:file][:filename]}"
render
end
A file upload will have a hash of params like this:
{
:filename => File.basename(filename),
:content_type => content_type,
:tempfile => ,
:size => File.size(body)
}
== Merb app layout
merb_app:
app
controllers
helpers
mailers
models
parts
views
config
gems
lib
log
public
Rakefile
script
spec
test
unit