Register the method for converting objects to PDF as #to_pdf.
+
Register the incoming mime-type "Accept" header as application/pdf.
+
Specify a new header for PDF types so it will set Content-Encoding to gzip.
+
+
+
You can then do:
+
+ class Foo < Application
+ provides :pdf
+ end
+
+
+
Where can I find help?
+
If you have any questions or if you can't figure something out, please take a
+ look at our project page,
+ feel free to come chat at irc.freenode.net, channel #merb,
+ or post to merb mailing list
+ on Google Groups.
+
+
What if I've found a bug?
+
If you want to file a bug or make your own contribution to Merb,
+ feel free to register and create a ticket at our
+ project development page
+ on Lighthouse.
+
+
How do I edit this page?
+
You can change what people see when this happens by editing app/views/exceptions/not_acceptable.html.erb.
+
+
+
+
+
diff --git a/app/views/exceptions/not_found.html.erb b/app/views/exceptions/not_found.html.erb
new file mode 100644
index 0000000..42b41a8
--- /dev/null
+++ b/app/views/exceptions/not_found.html.erb
@@ -0,0 +1,47 @@
+
+
+
+
+
pocket rocket web framework
+
+
+
+
+
Exception:
+
<%= request.exceptions.first.message %>
+
+
+
+
Welcome to Merb!
+
Merb is a light-weight MVC framework written in Ruby. We hope you enjoy it.
+
+
Where can I find help?
+
If you have any questions or if you can't figure something out, please take a
+ look at our project page,
+ feel free to come chat at irc.freenode.net, channel #merb,
+ or post to merb mailing list
+ on Google Groups.
+
+
What if I've found a bug?
+
If you want to file a bug or make your own contribution to Merb,
+ feel free to register and create a ticket at our
+ project development page
+ on Lighthouse.
+
+
How do I edit this page?
+
You're seeing this page because you need to edit the following files:
+
The name of the action in the Exceptions controller which will get invoked
+
+
+
+
+ when an instance of this Exception sub/class is raised by an action.
+
+
+:api: public @overridable
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/exceptions.rb, line 33
+ defself.action_name
+ ifself==Exception
+ returnnilunlessObject.const_defined?(:Exceptions) &&
+ Exceptions.method_defined?(:exception)
+ end
+ name = self.to_s.split('::').last.snake_case
+ Object.const_defined?(:Exceptions) &&
+ Exceptions.method_defined?(name) ?name:superclass.action_name
+ end
+
+
+
+
+
+ ()
+
+
+The status that will be sent in the response when an instance is raised
+during a request. Override this to send a different status.
+
+
Returns
+
+
Integer:
The status code to send in the response. Defaults to 500.
+
+
+
+
+:api: public @overridable
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/exceptions.rb, line 51
+ defself.status
+ 500
+ end
+
+
+
+
+
+
+
+
+
+
+
+ ()
+
+
+Returns the action_name that will be invoked on your
+Exceptions controller when this exception is raised. Override this method
+to force a different action to be invoked.
+
+
Returns
+
+
String:
The name of the action in the Exceptions controller which will get invoked
+
+
+
+
+ when this exception is raised during a request.
+
+Assuming that the total time taken for puts calls was less than 5% of the
+total time to run, puts won’t appear in the profile report. The code
+block will be run 30 times in the example above.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/core_ext/kernel.rb, line 419
+ def__profile__(name, min=1, iter=100)
+ require'ruby-prof'unlessdefined?(RubyProf)
+ return_result = ''
+ result = RubyProf.profiledo
+ iter.times{return_result = yield}
+ end
+ printer = RubyProf::GraphHtmlPrinter.new(result)
+ path = File.join(Merb.root, 'log', "#{name}.html")
+ File.open(path, 'w') do|file|
+ printer.print(file, {:min_percent =>min,
+ :print_file =>true})
+ end
+ return_result
+ end
+
+
+
+
+
+ ()
+
+
+Defines debugger method so that code even works if debugger was not
+requested. Drops a note to the logs that Debugger was not available.
+
+ ]]>
+
+
+
+# File lib/merb-core/core_ext/kernel.rb, line 477
+ defdebugger
+ Merb.logger.info!"\n***** Debugger requested, but was not "+
+ "available: Start server with --debugger "+
+ "to enable *****\n"
+ end
+
+
+
+
+
+ (*args)
+
+
+Loads both gem and library dependencies that are passed in as arguments.
+Execution is deferred to the Merb::BootLoader::Dependencies.run during bootup.
+
+
Parameters
+
+*args<String, Hash, Array>
+The dependencies to load.
+
+ ]]>
+
+
+
+# File lib/merb-core/core_ext/kernel.rb, line 176
+ defdependencies(*args)
+ args.mapdo|arg|
+ casearg
+ whenStringthendependency(arg)
+ whenHashthenarg.map { |r,v|dependency(r, v) }
+ whenArraythenarg.map { |r|dependency(r) }
+ end
+ end
+ end
+
+
+
+
+
+ (name, *ver, &blk)
+
+
+Loads the given string as a gem. Execution is deferred until after the
+logger has been instantiated and the framework directory structure is
+defined.
+
+
+If that has already happened, the gem will be activated immediately, but it
+will still be registered.
+
+
Parameters
+
+name<String> The name of the gem to load. *ver<Gem::Requirement,
+Gem::Version, Array, to_str>
+
+
+ Version requirements to be passed to Gem::Dependency.new.
+ If the last argument is a Hash, extract the :immediate option,
+ forcing a dependency to load immediately.
+
+
Options
+
+:immediate when true, gem is loaded immediately even if framework is not
+yet ready. :require_as file name to require for this gem.
+
+
+See examples below.
+
+
Notes
+
+If block is given, it is called after require is called. If you use a block
+to require multiple files, require first using :require_as option and the
+rest in the block.
+
+
Examples
+
+Usage scenario is typically one of the following:
+
+
+
Gem name and loaded file names are the same (ex.: amqp
+gem uses amqp.rb). In this case no extra options needed.
+
+
+
+
+dependency "amqp"
+
+
+
Gem name is different from the file needs to be required
+(ex.: ParseTree gem uses parse_tree.rb as main file).
+
+
You need to require a specific version of the gem.
+
+
+
+
+dependency "RedCloth", "3.0.4"
+
+
+
You want to load dependency as soon as the method is called.
+
+
+
+
+dependency "syslog", :immediate => true
+
+
+
You need to execute some arbitraty code after dependency is loaded:
+
+
+
+
+dependency "ruby-growl" do
+
+
+ g = Growl.new "localhost", "ruby-growl",
+ ["ruby-growl Notification"]
+ g.notify "ruby-growl Notification", "Ruby-Growl is set up",
+ "Ruby-Growl is set up"
+
+
+end
+
+
Returns
+
+
Gem::Dependency:
The dependency information.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/core_ext/kernel.rb, line 107
+ defdependency(name, *ver, &blk)
+ immediate = ver.last.delete(:immediate) ifver.last.is_a?(Hash)
+ ifimmediate||Merb::BootLoader.finished?(Merb::BootLoader::Dependencies)
+ load_dependency(name, *ver, &blk)
+ else
+ track_dependency(name, *ver, &blk)
+ end
+ end
+
+
+
+
+
+ (opts = {})
+
+
+Checks that the given objects quack like the given conditions.
+
+
Parameters
+
+opts<Hash>
+
+
+ Conditions to enforce. Each key will receive a quacks_like? call with the
+ value (see Object#quacks_like? for details).
+
+
Raises
+
+
<ArgumentError>:
An object failed to quack like a condition.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/core_ext/kernel.rb, line 467
+ defenforce!(opts = {})
+ opts.eachdo|k,v|
+ raiseArgumentError, "#{k.inspect} doesn't quack like #{v.inspect}"unlessk.quacks_like?(v)
+ end
+ end
+
+
+
+
+
+ (args)
+
+
+Extracts an options hash if it is the last item in the args array. Used
+internally in methods that take *args.
+
+
+ String:: Single dependency.
+ Hash::
+ Multiple dependencies where the keys are names and the values versions.
+ Array:: Multiple string dependencies.
+
+
Examples
+
+dependencies "RedCloth" # Loads the the RedCloth gem dependencies
+"RedCloth", "merb_helpers" # Loads RedCloth and
+merb_helpers dependencies "RedCloth" => "3.0" #
+Loads RedCloth 3.0
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/core_ext/kernel.rb, line 204
+ defload_dependencies(*args)
+ args.mapdo|arg|
+ casearg
+ whenStringthenload_dependency(arg)
+ whenHashthenarg.map { |r,v|load_dependency(r, v) }
+ whenArraythenarg.map { |r|load_dependency(r) }
+ end
+ end
+ end
+
+
+
+
+
+ (name, *ver, &blk)
+
+
+Loads the given string as a gem.
+
+
+This new version tries to load the file via ROOT/gems first before moving
+off to the system gems (so if you have a lower version of a gem in
+ROOT/gems, it’ll still get loaded).
+
+
Parameters
+
+name<String> The name or dependency object of the gem to load.
+*ver<Gem::Requirement, Gem::Version, Array, to_str>
+
+
+ Version requirements to be passed to Gem.activate.
+
+
Notes
+
+If the gem cannot be found, the method will attempt to require the string
+as a library. If block given, it is called instead of doing a require, so
+that you can pass some arbitraty code do load the gem.
+
+
Returns
+
+
Gem::Dependency:
The dependency information.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/core_ext/kernel.rb, line 138
+ defload_dependency(name, *ver, &blk)
+ dep = name.is_a?(Gem::Dependency) ?name:track_dependency(name, *ver, &blk)
+ Merb.logger.verbose!("activating gem '#{dep.name}' ...")
+ gem(dep)
+ rescueGem::LoadError =>e
+ msg = "Could not activate gem #{name} using gem '#{dep.name}': #{e.message}.\nIt usually means gem has unsatisfied dependencies. Run Merb with --verbose option if you are not sure what the problem is."
+ Merb.fatal!msg, e
+ ensure
+ begin
+ Merb.logger.verbose!("loading gem '#{dep.name}' ...")
+ [dep.require_as].flatten.eachdo|req|
+ Merb.logger.verbose!("running require '#{req}' ...")
+ requirereq
+ end
+ rescueLoadError =>e
+ msg = "Could not load gem #{name} (tried to require #{dep.require_as.inspect}): #{e.message}.\nIt may happen because you mispelled file to require or gem has unsatisfied dependencies. Run Merb with --verbose option if you are not sure what the problem is."
+ Merb.fatal!msg, e
+ end
+
+ ifblock = dep.require_block
+ Merb.logger.verbose!("calling a block after loading of '#{dep.name}' ...")
+ block.call
+ end
+
+ returndep# ensure needs explicit return
+ end
+
+
+
+
+
+ (library, message = nil)
+
+
+Does a basic require, and prints a message if an error occurs.
+
+
Parameters
+
+
library<to_s>:
The library to attempt to include.
+
+
+
message<String>:
The error to add to the log upon failure. Defaults to nil.
+
+
+This means if you refer to the same string 6 times per request and your
+application takes 100 requests per second, there are 600 objects for weak
+MRI garbage collector to work on.
+
+
+GC cycles take up to 80% (!) time of request processing in some cases.
+Eventually Rubinius and maybe MRI 2.0 gonna improve this situation but at
+the moment, all commonly used strings, regexp and numbers used as constants
+so no extra objects created and VM just operates pointers.
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+ '1.0' unless defined?(Merb::VERSION)
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (key, transform_method, mimes, new_response_headers = {}, default_quality = 1, &block)
+
+
+Any specific outgoing headers should be included here. These are not the
+content-type header but anything in addition to it.
+transform_method should be set to a symbol of the method used to
+transform a resource into this mime type. For example for the :xml mime
+type an object might be transformed by calling :to_xml, or for the :js mime
+type, :to_json. If there is no transform method, use nil.
+
+
Autogenerated Methods
+
+Adding a mime-type adds a render_type method that sets the content type and
+calls render.
+
+
+By default this does: def render_all, def render_yaml, def render_text, def
+render_html, def render_xml, def render_js, and def render_yaml
+
+
Parameters
+
+
key<Symbol>:
The name of the mime-type. This is used by the provides API
+
+
+
transform_method<~to_s>:
The associated method to call on objects to convert them to the appropriate
+mime-type. For instance, :json would use :to_json as its transform_method.
+
+
+
mimes<Array[String]>:
A list of possible values sent in the Accept header, such as text/html,
+that should be associated with this content-type.
+
+
+
new_response_headers<Hash>:
The response headers to set for the mime type. For example:
+‘Content-Type’ => ‘application/json;
+charset=utf-8’; As a shortcut for the common charset option, use
+:charset => ‘utf-8’, which will be correctly appended to the
+mimetype itself.
+
+
+
&block:
a block which receives the current controller when the format
+
+
+
+
+ is set (in the controller's #content_type method)
+
A hash mapping Content-Type values to the mime type key of the appropriate
+entry in available_mime_types
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mime.rb, line 30
+ defavailable_accepts
+ ResponderMixin::MIMES
+ end
+
+
+
+
+
+ ()
+
+
+Returns a hash of the available mime types.
+
+
Returns
+
+
Hash{Symbol => Hash{Symbol => Object}}:
The available mime types.
+
+
+
+
Notes
+
+Each entry corresponds to a call to add_mime_type,
+having the mime type key (:html, :xml, :json, etc.) as the key and a hash
+containing the following entries:
+
+
+ :accepts # the mime types that will be recognized by this entry
+ :transform_method # the method called on an object to convert it to content of this type (such as to_json)
+ :content_type # the value set to the "Content-Type" HTTP header when this mime is sent in a response
+ :response_headers # sent in a response using this content type
+ :default_quality # the scale factor used in describing content type preference
+ :response_block # the block to be called with the controller when a request responds to this mime type
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mime.rb, line 21
+ defavailable_mime_types
+ ResponderMixin::TYPES
+ end
+
+
+
+
+
+ (e)
+
+
+Required to show exceptions in the log file
+
+
Parameters
+
+
e<Exception>:
The exception that a message is being generated for
+
+
+ ]]>
+
+
+
+# File lib/merb-core/plugins.rb, line 63
+ defself.add_rakefiles(*rakefiles)
+ Merb.add_rakefiles(*rakefiles)
+ end
+
+
+
+
+
+ ()
+
+
+Returns the configuration settings hash for plugins. This is prepopulated
+from Merb.root / "config/plugins.yml" if it is present.
+
+
Returns
+
+
Hash:
The configuration loaded from Merb.root / "config/plugins.yml"
+or, if the load fails, an empty hash whose default value is another Hash.
+
+
+
+
+:api: plugin
+
+ ]]>
+
+
+
+# File lib/merb-core/plugins.rb, line 14
+ defself.config
+ @config||=begin
+ # this is so you can do Merb.plugins.config[:helpers][:awesome] = "bar"
+ config_hash = Hash.new {|h,k|h[k] = {}}
+ file = Merb.root/"config"/"plugins.yml"
+
+ ifFile.exists?(file)
+ require'yaml'
+ to_merge = YAML.load_file(file)
+ else
+ to_merge = {}
+ end
+
+ config_hash.merge(to_merge)
+ end
+ end
+
+
+
+
+
+ ()
+
+ Returns
+
Module that is including RenderMixin
+(probably a controller)
+
+
+
+
+@api private
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/render.rb, line 9
+ defself.included(base)
+ base.extend(ClassMethods)
+ base.class_evaldo
+ class_inheritable_accessor:_default_render_options
+ end
+ end
+
+
+
+
+
+
+
+
+
+
+
+ (layout = nil)
+
+
+Gets the layout that should be used. The content-type will be appended to
+the layout unless the layout already contains a "." in it.
+
+
+If no layout was passed in, this method will look for one with the same
+name as the controller, and finally one in
+"application.#{content_type}".
+
+
Parameters
+
+
layout<~to_s>:
A layout, relative to the layout root. Defaults to nil.
+
+
+
+
Returns
+
+
String:
The method name that corresponds to the found layout.
+
+
+
+
Raises
+
+
TemplateNotFound:
If a layout was specified (either via layout in the class or by passing one
+in to this method), and not found. No error will be raised if no layout was
+specified, and the default layouts were not found.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/render.rb, line 369
+ def_get_layout(layout = nil)
+ returnfalseiflayout==false
+
+ layout = layout.instance_of?(Symbol) &&self.respond_to?(layout, true) ?send(layout) :layout
+ layout = layout.to_siflayout
+
+ # If a layout was provided, throw an error if it's not found
+ iflayout
+ template_method, template_location =
+ _template_for(layout, layout.index(".") ?nil:content_type, "layout")
+
+ raiseTemplateNotFound, "No layout found at #{template_location}"unlesstemplate_method
+ template_method
+
+ # If a layout was not provided, try the default locations
+ else
+ template, location = _template_for(controller_name, content_type, "layout")
+ template, location = _template_for("application", content_type, "layout") unlesstemplate
+ template
+ end
+ end
+
+
+
+
+
+ (opts)
+
+
+Takes the options hash and handles it as appropriate.
+
+
Parameters
+
+
opts<Hash>:
The options hash that was passed into render.
+
+
+
+
Options
+
+
:status<~to_i>:
The status of the response will be set to opts[:status].to_i
+
+
+
+
Returns
+
+
Hash:
The options hash that was passed in.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/render.rb, line 344
+ def_handle_options!(opts)
+ self.status = opts.delete(:status).to_iifopts[:status]
+ headers["Location"] = opts.delete(:location) ifopts[:location]
+ opts
+ end
+
+
+
+
+
+ (context, content_type, controller=nil, template=nil, locals=[])
+
+
+Iterates over the template roots in reverse order, and returns the template
+and template location of the first match.
+
+
Parameters
+
+
context<Object>:
The controller action or template (basename or absolute path).
+
+
+
content_type<~to_s>:
The content type (like html or json).
+
+
+
controller<~to_s>:
The name of the controller. Defaults to nil.
+
+
+
locals<Array[Symbol]>:
A list of locals to assign from the args passed into the compiled template.
+
+
+
+
Options (opts)
+
+
:template<String>:
The location of the template to use. Defaults to whatever matches this
+context, content_type and controller.
+
+
+
+
Returns
+
+
Array[Symbol, String]:
A pair consisting of the template method and location.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/render.rb, line 410
+ def_template_for(context, content_type, controller=nil, template=nil, locals=[])
+ template_method, template_location = nil, nil
+
+ # absolute path to a template (:template => "/foo/bar")
+ iftemplate.is_a?(String) &&template=~%r{^/}
+ template_location = self._absolute_template_location(template, content_type)
+ return [_template_method_for(template_location, locals), template_location]
+ end
+
+ self.class._template_roots.reverse_eachdo|root, template_meth|
+ # :template => "foo/bar.html" where root / "foo/bar.html.*" exists
+ iftemplate
+ template_location = root/self.send(template_meth, template, content_type, nil)
+ # :layout => "foo" where root / "layouts" / "#{controller}.html.*" exists
+ else
+ template_location = root/self.send(template_meth, context, content_type, controller)
+ end
+
+ breakiftemplate_method = _template_method_for(template_location.to_s, locals)
+ end
+
+ # template_location is a Pathname
+ [template_method, template_location.to_s]
+ end
+
+
+
+
+
+ (template_location, locals)
+
+
+Returns the template method for a location, and checks to make sure the
+current controller actually responds to the method.
+
+
Parameters
+
+
template_location<String>:
The physical path of the template
+
+
+
locals<Array[Symbol]>:
A list of locals to assign from the args passed into the compiled template.
+
+
+
+
Returns
+
+
String:
The method, if it exists. Otherwise return nil.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/render.rb, line 446
+ def_template_method_for(template_location, locals)
+ meth = Merb::Template.template_for(template_location, [], locals)
+ meth&&self.respond_to?(meth) ?meth:nil
+ end
+
+
+
+
+
+ (obj, string = nil, &block)
+
+
+Called in templates to append content for later use. Works like
+throw_content.
+
+
+@param [Object] obj
+
+
+ Key used in the thrown_content hash.
+
+
+@param [String] string
+
+
+ Textual content. Default to nil.
+
+
+@yield
+
+
+ Evaluated with result concatenated to string.
+
+
+@raise [ArgumentError]
+
+
+ Neither string nor block given
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/render.rb, line 512
+ defappend_content(obj, string = nil, &block)
+ unlessstring||block_given?
+ raiseArgumentError, "You must pass a block or a string into append_content"
+ end
+ @_caught_content[obj] = [] if@_caught_content[obj].nil?
+ @_caught_content[obj] <<string.to_s<< (block_given?? capture(&block) :"")
+ end
+
+
+
+
+
+ (obj = :for_layout)
+
+
+Called in templates to get at content thrown in another template. The
+results of rendering a template are automatically thrown into :for_layout,
+so catch_content or catch_content(:for_layout) can be used inside layouts
+to get the content rendered by the action template.
+
+
Parameters
+
+
obj<Object>:
The key in the thrown_content hash. Defaults to :for_layout.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/render.rb, line 460
+ defcatch_content(obj = :for_layout)
+ @_caught_content[obj] ||''
+ end
+
+
+
+
+
+ (obj = :for_layout)
+
+
+Called when renderers need to be sure that existing thrown content is
+cleared before throwing new content. This prevents double rendering of
+content when multiple templates are rendered after each other.
+
+
Parameters
+
+
obj<Object>:
The key in the thrown_content hash. Defaults to :for_layout.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/render.rb, line 528
+ defclear_content(obj = :for_layout)
+ @_caught_content.delete(obj) unless@_caught_content[obj].nil?
+ end
+
+
+
+
+
+ (object, thing = nil, opts = {})
+
+
+Renders an object using to registered transform method based on the
+negotiated content-type, if a template does not exist. For instance, if the
+content-type is :json, Merb will first look for
+current_action.json.*. Failing that, it will run object.to_json.
+
+
Parameter
+
+
object<Object>:
An object that responds_to? the transform method registered for the
+negotiated mime-type.
+
+
+If you need to pass extra parameters to serialization method, for instance,
+to exclude some of attributes or serialize associations, just pass options
+for it. For instance,
+
+serializes object with polymorphic association, not raw locatable_*
+attributes.
+
+
Options
+
+:template a template to use for rendering :layout a layout to use for
+rendering :status the status code to return (defaults to 200) :location the
+value of the Location header
+
+
+all other options options that will be pass to serialization method
+
+
+ like #to_json or #to_xml
+
+
Notes
+
+The transformed object will not be used in a layout unless a :layout is
+explicitly passed in the opts.
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/render.rb, line 205
+ defdisplay(object, thing = nil, opts = {})
+ template_opt = thing.is_a?(Hash) ?thing.delete(:template) :opts.delete(:template)
+
+ casething
+ # display @object, "path/to/foo" means display @object, nil, :template => "path/to/foo"
+ whenString
+ template_opt, thing = thing, nil
+ # display @object, :template => "path/to/foo" means display @object, nil, :template => "path/to/foo"
+ whenHash
+ opts, thing = thing, nil
+ end
+
+ # Try to render without the object
+ render(thing||action_name.to_sym, opts.merge(:template =>template_opt))
+
+ # If the render fails (i.e. a template was not found)
+ rescueTemplateNotFound =>e
+ # Merge with class level default render options
+ # @todo can we find a way to refactor this out so we don't have to do it everywhere?
+ opts = self.class.default_render_options.merge(opts)
+
+ # Figure out what to transform and raise NotAcceptable unless there's a transform method assigned
+ transform = Merb.mime_transform_method(content_type)
+ if!transform
+ raiseNotAcceptable, "#{e.message} and there was no transform method registered for #{content_type.inspect}"
+ elsif!object.respond_to?(transform)
+ raiseNotAcceptable, "#{e.message} and your object does not respond to ##{transform}"
+ end
+
+ layout_opt = opts.delete(:layout)
+ _handle_options!(opts)
+ throw_content(:for_layout, opts.empty?? object.send(transform) :object.send(transform, opts))
+
+ meth, _ = _template_for(layout_opt, layout_opt.to_s.index(".") ?nil:content_type, "layout") iflayout_opt
+ meth? send(meth) :catch_content(:for_layout)
+ end
+
+
+
+
+
+ (template, opts={})
+
+
+Renders a partial template.
+
+
Parameters
+
+
template<~to_s>:
The path to the template, relative to the current controller or the
+template root; absolute path will work too. If the template contains a
+"/", Merb will search for it relative to the
+template root; otherwise, Merb will search for it
+relative to the current controller.
+
+
+The "_bar" partial will be called once for each element of the
+array specified by :with for a total of three iterations. Each element of
+the array will be available in the partial via a local variable named
+bar. Additionally, there will be two extra local variables:
+collection_index and collection_size.
+collection_index is the index of the object currently referenced
+by bar in the collection passed to the partial.
+collection_size is the total size of the collection.
+
+
+By default, the object specified by :with will be available through a local
+variable with the same name as the partial template. However, this can be
+changed using the :as option.
+
+
+ partial :bar, :with => "one", :as => :number
+
+
+In this case, "one" will be available in the partial through the
+local variable named number.
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/render.rb, line 287
+ defpartial(template, opts={})
+
+ # partial :foo becomes "#{controller_name}/_foo"
+ # partial "foo/bar" becomes "foo/_bar"
+ template = template.to_s
+ iftemplate=~%r{^/}
+ template_path = File.dirname(template) /"_#{File.basename(template)}"
+ else
+ kontroller = (m = template.match(/.*(?=\/)/)) ?m[0] :controller_name
+ template = "_#{File.basename(template)}"
+ end
+
+ # This handles no :with as well
+ with = [opts.delete(:with)].flatten
+ as = (opts.delete(:as) ||template.match(%r[(?:.*/)?_([^\./]*)])[1]).to_sym
+
+ # Ensure that as is in the locals hash even if it isn't passed in here
+ # so that it's included in the preamble.
+ locals = opts.merge(:collection_index =>-1, :collection_size =>with.size, as =>opts[as])
+ template_method, template_location = _template_for(
+ template,
+ opts.delete(:format) ||content_type,
+ kontroller,
+ template_path,
+ locals.keys)
+
+ # this handles an edge-case where the name of the partial is _foo.* and your opts
+ # have :foo as a key.
+ named_local = opts.key?(as)
+
+ sent_template = with.mapdo|temp|
+ locals[as] = tempunlessnamed_local
+
+ iftemplate_method&&self.respond_to?(template_method)
+ locals[:collection_index] +=1
+ send(template_method, locals)
+ else
+ raiseTemplateNotFound, "Could not find template at #{template_location}.*"
+ end
+ end.join
+
+ sent_template
+ end
+
+
+
+
+
+ (thing = nil, opts = {})
+
+
+Renders the specified item, with the specified options.
+
+
The thing to render. This will default to the current action
+
+
+
opts<Hash>:
An options hash (see below)
+
+
+
+
Options (opts)
+
+
:format<Symbol>:
A registered mime-type format
+
+
+
:template<String>:
The path to the template relative to the template root
+
+
+
:status<~to_i>:
The status to send to the client. Typically, this would be an integer
+(200), or a Merb status code (Accepted)
+
+
+
:layout<~to_s, FalseClass>:
A layout to use instead of the default. This should be relative to the
+layout root. By default, the layout will be either the controller_name or
+application. If you want to use an alternative content-type than the one
+that the base template was rendered as, you will need to do :layout =>
+"foo.#{content_type}" (i.e. "foo.json"). If you want to
+render without layout, use :layout => false. This overrides layout set
+by layout method.
+
+
+
+
Returns
+
+
String:
The rendered template, including layout, if appropriate.
+
+
+
+
Raises
+
+
TemplateNotFound:
There is no template for the specified location.
+
+
+
+
Alternatives
+
+If you pass a Hash as the first parameter, it will be
+moved to opts and "thing" will be the current action
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/render.rb, line 100
+ defrender(thing = nil, opts = {})
+ # render :format => :xml means render nil, :format => :xml
+ opts, thing = thing, nilifthing.is_a?(Hash)
+
+ # Merge with class level default render options
+ opts = self.class.default_render_options.merge(opts)
+
+ # If you don't specify a thing to render, assume they want to render the current action
+ thing||=action_name.to_sym
+
+ # Content negotiation
+ self.content_type = opts[:format] ifopts[:format]
+
+ # Handle options (:status)
+ _handle_options!(opts)
+
+ # Do we have a template to try to render?
+ ifthing.is_a?(Symbol) ||opts[:template]
+
+ template_method, template_location =
+ _template_for(thing, content_type, controller_name, opts[:template])
+
+ # Raise an error if there's no template
+ unlesstemplate_method&&self.respond_to?(template_method)
+ template_files = Merb::Template.template_extensions.map { |ext|"#{template_location}.#{ext}" }
+ raiseTemplateNotFound, "Oops! No template found. Merb was looking for #{template_files.join(', ')}"+
+ "for content type '#{content_type}'. You might have mispelled the template or file name. "+
+ "Registered template extensions: #{Merb::Template.template_extensions.join(', ')}. "+
+ "If you use Haml or some other template plugin, make sure you required Merb plugin dependency "+
+ "in your init file."
+ end
+
+ # Call the method in question and throw the content for later consumption by the layout
+ throw_content(:for_layout, self.send(template_method))
+
+ # Do we have a string to render?
+ elsifthing.is_a?(String)
+
+ # Throw it for later consumption by the layout
+ throw_content(:for_layout, thing)
+ end
+
+ # If we find a layout, use it. Otherwise, just render the content thrown for layout.
+ (layout = _get_layout(opts[:layout])) ?send(layout) :catch_content(:for_layout)
+ end
+
+
+
+
+
+ (obj, string = nil, &block)
+
+
+Called in templates to store up content for later use. Takes a string
+and/or a block. First, the string is evaluated, and then the block is
+captured using the capture() helper provided by the template languages. The
+two are concatenated together.
+
+
Parameters
+
+
obj<Object>:
The key in the thrown_content hash.
+
+
+
string<String>:
Textual content. Defaults to nil.
+
+
+
&block:
A block to be evaluated and concatenated to string.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/render.rb, line 492
+ defthrow_content(obj, string = nil, &block)
+ unlessstring||block_given?
+ raiseArgumentError, "You must pass a block or a string into throw_content"
+ end
+ @_caught_content[obj] = string.to_s<< (block_given?? capture(&block) :"")
+ end
+
+
+
+
+
+ (obj = :for_layout)
+
+
+Called in templates to test for the existence of previously thrown content.
+
+
Parameters
+
+
obj<Object>:
The key in the thrown_content hash. Defaults to :for_layout.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/render.rb, line 24
+ defdefault_render_options
+ self._default_render_options||= {}
+ end
+
+
+
+
+
+ (layout)
+
+
+Sets the default layout to use or nil/false to disable layout rendering.
+This is a shortcut for render_options :layout =>
+false.
+
+
Parameters
+
+
layout<~to_s>:
The layout that should be used for this class.
+
+
+
+
Notes
+
+You can override by passing :layout => true to render method.
+
+
Returns
+
+
Hash:
The default render options.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/render.rb, line 51
+ deflayout(layout)
+ self.default_render_options.update(:layout => (layout||false))
+ end
+
+
+
+
+
+ (opts)
+
+
+Sets default render options at the class level.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/rack/handler/mongrel.rb, line 53
+ definitialize(app)
+ @app = app
+ end
+
+
+
+
+
+ (app, options={}) {|@server if block_given?| ...}
+
+
+Runs the server and yields it to a block.
+
+
+An ORM should implement Merb::Orms::MyOrm#close_sandbox! to support this.
+Usually this involves rolling back a transaction. :api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/rack/adapter/irb.rb, line 113
+ defclose_sandbox!
+ orm_modules.each { |orm|orm.close_sandbox!iform.respond_to?(:close_sandbox!) }
+ puts"Modifications have been rolled back"
+ end
+
+
+
+
+
+ ()
+
+
+Starts a sandboxed session (delegates to any Merb::Orms::* modules).
+
+
+An ORM should implement Merb::Orms::MyOrm#open_sandbox! to support this.
+Usually this involves starting a transaction. :api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/rack/adapter/irb.rb, line 102
+ defopen_sandbox!
+ puts"Loading #{Merb.environment} environment in sandbox (Merb #{Merb::VERSION})"
+ puts"Any modifications you make will be rolled back on exit"
+ orm_modules.each { |orm|orm.open_sandbox!iform.respond_to?(:open_sandbox!) }
+ end
+
+
+
+
+
+ ()
+
+
+Reloads classes using Merb::BootLoader::ReloadClasses.
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/rack/adapter/irb.rb, line 65
+ defreload!
+ Merb::BootLoader::ReloadClasses.reload
+ end
+
+
+
+
+
+ ()
+
+
+Prints all routes for the application. :api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/rack/adapter/irb.rb, line 71
+ defshow_routes
+ seen = []
+ unlessMerb::Router.named_routes.empty?
+ puts"==== Named routes"
+ Merb::Router.named_routes.eachdo|name,route|
+ # something weird happens when you combine sprintf and irb
+ puts"Helper : #{name}"
+ meth = $1.upcaseifroute.conditions[:method].to_s=~/(get|post|put|delete)/
+ puts"HTTP method: #{meth || 'GET'}"
+ puts"Route : #{route}"
+ puts"Params : #{route.params.inspect}"
+ puts
+ seen<<route
+ end
+ end
+ puts"==== Anonymous routes"
+ (Merb::Router.routes-seen).eachdo|route|
+ meth = $1.upcaseifroute.conditions[:method].to_s=~/(get|post|put|delete)/
+ puts"HTTP method: #{meth || 'GET'}"
+ puts"Route : #{route}"
+ puts"Params : #{route.params.inspect}"
+ puts
+ end
+ nil
+ end
+
+
+
+
+
+ ()
+
+
+Explictly show logger output during IRB session :api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/rack/adapter/irb.rb, line 120
+ deftrace_log!
+ Merb.logger.auto_flush = true
+ end
+
+
+
+
+
+ (name, *args)
+
+
+There are three possible ways to use this method. First, if you have a
+named route, you can specify the route as the first parameter as a symbol
+and any parameters in a hash. Second, you can generate the default route by
+just passing the params hash, just passing the params hash. Finally, you
+can use the anonymous parameters. This allows you to specify the parameters
+to a named route in the order they appear in the router.
+
+
Parameters(Named Route)
+
+
name<Symbol>:
The name of the route.
+
+
+
args<Hash>:
Parameters for the route generation.
+
+
+
+
Parameters(Default Route)
+
+
args<Hash>:
Parameters for the route generation. This route will use the default route.
+
+
+
+
Parameters(Anonymous Parameters)
+
+
name<Symbol>:
The name of the route.
+
+
+
args<Array>:
An array of anonymous parameters to generate the route with. These
+parameters are assigned to the route parameters in the order that they are
+passed.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/rack/adapter/abstract.rb, line 244
+ defself.exit_process(status = 0)
+ exit(status)
+ end
+
+
+
+
+
+ (port)
+
+
+This method is designed to be overridden in a rack adapter. It will be
+called to create a new instance of the server for the adapter to start. The
+adapter should attempt to bind to a port at this point. This is called from
+the AbstractAdapter start
+method.
+
+
Parameters
+
+
port<Integer>:
The port the server should listen on
+
+
+
+
+:api: plugin @overridable
+
+ ]]>
+
+
+
+# File lib/merb-core/rack/adapter/abstract.rb, line 25
+ defself.new_server(port)
+ raiseNotImplemented
+ end
+
+
+
+
+
+ (whoami, port)
+
+
+Sets the process title.
+
+
Parameters
+
+
whoami<Symbol>:
Either :spawner for the master process or :worker for any of the worker
+
+
+
+
+ processes.
+
+
+
port<Integer>:
The base port that the app is running on.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/rack/adapter/abstract.rb, line 256
+ defself.process_title(whoami, port)
+ name = Merb::Config[:name]
+ app = "merb#{" : #{name}" if (name && name != "merb")}"
+ max_port = Merb::Config[:cluster] ? (Merb::Config[:cluster] -1) :0
+ numbers = ((whoami!=:worker) && (max_port>0)) ?"#{port}..#{port + max_port}":port
+ file = Merb::Config[:socket_file] %portifMerb::Config[:socket_file]
+
+ listening_on = ifMerb::Config[:socket]
+ "socket#{'s' if max_port > 0 && whoami != :worker} #{numbers} "\
+ "#{file ? file : "#{Merb.log_path}/#{name}.#{port}.sock"}"
+ else
+ "port#{'s' if max_port > 0 && whoami != :worker} #{port}"
+ end
+ "#{app} : #{whoami} (#{listening_on})"
+ end
+
+
+
+
+
+ (port)
+
+
+Spawns a new worker process at a port.
+
+
Parameters
+
+
port<Integer>:
The port to start the worker process on.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/rack/adapter/abstract.rb, line 50
+ defself.spawn_worker(port)
+ worker_pid = Kernel.fork
+ start_at_port(port, @opts) unlessworker_pid
+
+ # If we have a worker_pid, we're in the parent.
+ throw(:new_worker) unlessworker_pid
+
+ @pids[port] = worker_pid
+ $WORKERS = @pids.values
+ end
+
+
+
+
+
+ (opts={})
+
+
+The main start method for bootloaders that support forking. This method
+launches the adapters which inherit using the new_server and start_server
+methods. This method should not be overridden in adapters which want to
+fork.
+
+
Parameters
+
+
opts<Hash>:
A hash of options
+
+
+
+
+ socket: the socket to bind to
+ port: the port to bind to
+ cluster: the number
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/rack/adapter/abstract.rb, line 73
+ defself.start(opts={})
+ @opts = opts
+ $WORKERS||= []
+ parent = nil
+
+ @pids = {}
+ port = (opts[:socket] ||opts[:port]).to_i
+ max_port = Merb::Config[:cluster] ?Merb::Config[:cluster] -1:0
+
+ # If we only have a single merb, just start it up and dispense with
+ # the spawner/worker setup.
+ ifmax_port==0
+ start_at_port(port)
+ return
+ end
+
+ $0 = process_title(:spawner, port)
+
+ # For each port, spawn a new worker. The parent will continue in
+ # the loop, while the worker will throw :new_worker and be booted
+ # out of the loop.
+ catch(:new_worker) do
+ 0.upto(max_port) do|i|
+ parent = spawn_worker(port+i)
+ end
+ end
+
+ # If we're in a worker, we're done. Otherwise, we've completed
+ # setting up workers and now need to watch them.
+ returnunlessparent
+
+ # For each worker, set up a thread in the spawner to watch it
+ 0.upto(max_port) do|i|
+ Thread.newdo
+ catch(:new_worker) do
+ loopdo
+ pid = @pids[port+i]
+ begin
+ # Watch for the pid to exit.
+ _, status = Process.wait2(pid)
+
+ # If the pid doesn't exist, we want to silently exit instead of
+ # raising here.
+ rescueSystemCallError =>e
+ ensure
+ # If there was no worker with that PID, the status was non-0
+ # (we send back a status of 128 when ABRT is called on a
+ # worker, and Merb.fatal! exits with a status of 1), or if
+ # Merb is in the process of exiting, *then* don't respawn.
+ # Note that processes killed with kill -9 will return no
+ # exitstatus, and we respawn them.
+ if!status||
+ (status.exitstatus&&status.exitstatus!=0) ||
+ Merb.exitingthen
+ Thread.exit
+ end
+ end
+
+ # Otherwise, respawn the worker, and watch it again.
+ spawn_worker(port+i)
+ end
+ end
+ end
+ end
+
+ # The spawner process will make it here, and when it does, it should just
+ # sleep so it can pick up ctrl-c if it's in console mode.
+ sleep
+
+ end
+
+
+
+
+
+ (port, opts = @opts)
+
+
+Forks a server on the specified port and start the app.
+
+
Parameters
+
+
port<Integer>:
The port to start the server on
+
+
+
opts<Hash>:
The hash of options, defaults to the @opts
+
+
+
+
+ instance variable.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/rack/adapter/abstract.rb, line 152
+ defself.start_at_port(port, opts = @opts)
+ at_exitdo
+ Merb::Server.remove_pid(port)
+ end
+
+ Merb::Worker.startunlessMerb.testing?
+
+ # If Merb is daemonized, trap INT. If it's not daemonized,
+ # we let the master process' ctrl-c control the cluster
+ # of workers.
+ ifMerb::Config[:daemonize]
+ Merb.trap('INT') do
+ Merb.exiting = true
+ stop
+ Merb.logger.warn!"Exiting port #{port}\n"
+ exit_process
+ end
+ # If it was not fork_for_class_load, we already set up
+ # ctrl-c handlers in the master thread.
+ elsifMerb::Config[:fork_for_class_load]
+ ifMerb::Config[:console_trap]
+ Merb::Server.add_irb_trap
+ end
+ end
+
+ # In daemonized mode or not, support HUPing the process to
+ # restart it.
+ Merb.trap('HUP') do
+ Merb.exiting = true
+ stop
+ Merb.logger.warn!"Exiting port #{port} on #{Process.pid}\n"
+ exit_process
+ end
+
+ # ABRTing the process will kill it, and it will not be respawned.
+ Merb.trap('ABRT') do
+ Merb.exiting = true
+ stopped = stop(128)
+ Merb.logger.warn!"Exiting port #{port}\n"ifstopped
+ exit_process(128)
+ end
+
+ # Each worker gets its own `ps' name.
+ $0 = process_title(:worker, port)
+
+ # Store the PID for this worker
+ Merb::Server.store_pid(port)
+
+ Merb::Config[:log_delimiter] = "#{process_title(:worker, port)} ~ "
+
+ Merb.reset_logger!
+ Merb.logger.warn!("Starting #{self.name.split("::").last} at port #{port}")
+
+ # If we can't connect to the port, keep trying until we can. Print
+ # a warning about this once. Try every 0.25s.
+ printed_warning = false
+ loopdo
+ begin
+ # Call the adapter's new_server method, which should attempt
+ # to bind to a port.
+ new_server(port)
+ rescueErrno::EADDRINUSE =>e
+ ifMerb::Config[:bind_fail_fatal]
+ Merb.fatal!"Could not bind to #{port}. It was already in use", e
+ end
+
+ unlessprinted_warning
+ Merb.logger.warn!"Port #{port} is in use, " \
+ "Waiting for it to become available."
+ printed_warning = true
+ end
+
+ sleep0.25
+ next
+ end
+ break
+ end
+
+ Merb.logger.warn!"Successfully bound to port #{port}"
+
+ Merb::Server.change_privilege
+
+ # Call the adapter's start_server method.
+ start_server
+ end
+
+
+
+
+
+ ()
+
+
+This method is designed to be overridden in a rack adapter. It will be
+called to start a server created with the new_server
+method. This is called from the AbstractAdapter start method.
+
+
+:api: plugin @overridable
+
+ ]]>
+
+
+
+# File lib/merb-core/rack/adapter/abstract.rb, line 11
+ defself.start_server
+ raiseNotImplemented
+ end
+
+
+
+
+
+ (status)
+
+
+This method is designed to be overridden in a rack adapter. It will be
+called to stop the adapter server.
+
+
+If you hear someone say "Use provides" they’re talking
+about the Responder. If you hear someone ask
+"What happened to respond_to?" it was replaced by provides and
+the other Responder methods.
+
+
A simple example
+
+The best way to understand how all of these pieces fit together is with an
+example. Here’s a simple web-service ready resource that provides a
+list of all the widgets we know about. The widget list is available in 3
+formats: :html (the default), plus :xml and :text.
+
+
+ class Widgets < Application
+ provides :html # This is the default, but you can
+ # be explicit if you like.
+ provides :xml, :text
+
+ def index
+ @widgets = Widget.fetch
+ render @widgets
+ end
+ end
+
+
+Let’s look at some example requests for this list of widgets.
+We’ll assume they’re all GET requests, but that’s only to
+make the examples easier; this works for the full set of RESTful methods.
+
+
+
The simplest case, /widgets.html Since the request includes a specific
+format (.html) we know what format to return. Since :html is in our list of
+provided formats, that’s what we’ll return. render
+will look for an index.html.erb (or another template format like
+index.html.mab; see the documentation on Template engines)
+
+
+
Almost as simple, /widgets.xml This is very similar. They want :xml, we
+have :xml, so that’s what they get. If render doesn’t
+find an index.xml.builder or similar template, it will call to_xml
+on @widgets. This may or may not do something useful, but you can see how
+it works.
+
+
+
A browser request for /widgets This time the URL doesn’t say what
+format is being requested, so we’ll look to the HTTP Accept: header.
+If it’s ‘/’ (anything), we’ll use the first
+format on our list, :html by default.
+
+
+If it parses to a list of accepted formats, we’ll look through them,
+in order, until we find one we have available. If we find one, we’ll
+use that. Otherwise, we can’t fulfill the request: they asked for a
+format we don’t have. So we raise 406: Not Acceptable.
+
+
+
+
A more complex example
+
+Sometimes you don’t have the same code to handle each available
+format. Sometimes you need to load different data to serve /widgets.xml
+versus /widgets.txt. In that case, you can use content_type to determine what format will be
+delivered.
+
+
+ class Widgets < Application
+ def action1
+ if content_type == :text
+ Widget.load_text_formatted(params[:id])
+ else
+ render
+ end
+ end
+
+ def action2
+ case content_type
+ when :html
+ handle_html()
+ when :xml
+ handle_xml()
+ when :text
+ handle_text()
+ else
+ render
+ end
+ end
+ end
+
+
+You can do any standard Ruby flow control using content_type. If you don’t call it yourself,
+it will be called (triggering content negotiation) by render.
+
+
+Once content_type has been called, the
+output format is frozen, and none of the provides methods can be used.
+
Look for one that is provided, in order of request
+
+
+
Raise 406 if none found
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/responder.rb, line 268
+ def_perform_content_negotiation
+ if (fmt = params[:format]) &&!fmt.empty?
+ accepts = [fmt.to_sym]
+ elsifrequest.accept=~%r{^(text/html|\*/\*)}&&_provided_formats.first==:html
+ # Handle the common case of text/html and :html provided after checking :format
+ return:html
+ else
+ accepts = Responder.parse(request.accept).map {|t|t.to_sym}.compact
+ end
+
+ # no need to make a bunch of method calls to _provided_formats
+ provided_formats = _provided_formats
+
+ specifics = accepts&provided_formats
+ returnspecifics.firstunlessspecifics.length==0
+ returnprovided_formats.firstifaccepts.include?(:all) &&!provided_formats.empty?
+
+ message = "A format (%s) that isn't provided (%s) has been requested. "
+ message+="Make sure the action provides the format, and be "
+ message+="careful of before filters which won't recognize "
+ message+="formats provided within actions."
+ raiseMerb::ControllerExceptions::NotAcceptable,
+ (message% [accepts.join(', '), provided_formats.join(', ')])
+ end
+
+
+
+
+
+ ()
+
+ Returns
+
+
Array[Symbol]:
The current list of formats provided for this instance of the controller.
+It starts with what has been set in the controller (or :html by default)
+but can be modified on a per-action basis.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/responder.rb, line 199
+ def_provided_formats
+ @_provided_formats||=class_provided_formats.dup
+ end
+
+
+
+
+
+ (fmt = nil)
+
+
+Returns the output format for this request, based on the provided formats,
+params[:format] and the client’s HTTP Accept header.
+
+
+The first time this is called, it triggers content negotiation and caches
+the value. Once you call content_type you
+can not set or change the list of provided formats.
+
+
+Called automatically by render, so you should only call it if you
+need the value, not to trigger content negotiation.
+
+
Parameters
+
+
fmt<String>:
An optional format to use instead of performing content negotiation. This
+can be used to pass in the values of opts[:format] from the render function
+to short-circuit content-negotiation when it’s not necessary. This
+optional parameter should not be considered part of the public API.
+
+
+
+
Returns
+
+
Symbol:
The content-type that will be used for this controller.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/responder.rb, line 316
+ defcontent_type(fmt = nil)
+ self.content_type = (fmt||_perform_content_negotiation) unless@_content_type
+ @_content_type
+ end
+
+
+
+
+
+ (type)
+
+
+Sets the content type of the current response to a value based on a passed
+in key. The Content-Type header will be set to the first registered header
+for the mime-type.
+
+
Parameters
+
+
type<Symbol>:
The content type.
+
+
+
+
Raises
+
+
ArgumentError:
type is not in the list of registered mime-types.
+
+
+
+
Returns
+
+
Symbol:
The content-type that was passed in.
+
+
+
+
+:api: plugin
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/responder.rb, line 335
+ defcontent_type=(type)
+ unlessMerb.available_mime_types.has_key?(type)
+ raiseMerb::ControllerExceptions::NotAcceptable.new("Unknown content_type for response: #{type}")
+ end
+
+ @_content_type = type
+
+ mime = Merb.available_mime_types[type]
+
+ headers["Content-Type"] = mime[:content_type]
+
+ # merge any format specific response headers
+ mime[:response_headers].each { |k,v|headers[k] ||=v }
+
+ # if given, use a block to finetune any runtime headers
+ mime[:response_block].call(self) ifmime[:response_block]
+
+ @_content_type
+ end
+
+
+
+
+
+ (*formats)
+
+
+Removes formats from the list of provided formats for this particular
+request. Usually used to remove formats from a single action. See also the
+controller-level does_not_provide that affects all
+actions in a controller.
+
+
Parameters
+
+
*formats<Symbol>:
Registered mime-type
+
+
+
+
Returns
+
+
Array[Symbol]:
List of formats that remain after removing the ones not to provide.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/responder.rb, line 256
+ defdoes_not_provide(*formats)
+ @_provided_formats-=formats.flatten
+ end
+
+
+
+
+
+ (*formats)
+
+
+Sets list of provided formats for this particular request. Usually used to
+limit formats to a single action. See also the controller-level only_provides that affects all actions in a controller.
+
+
Parameters
+
+
*formats<Symbol>:
A list of formats to use as the per-action list of provided formats.
+
+
+
+
Returns
+
+
Array[Symbol]:
List of formats passed in.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/responder.rb, line 238
+ defonly_provides(*formats)
+ @_provided_formats = []
+ provides(*formats)
+ end
+
+
+
+
+
+ (*formats)
+
+
+Adds formats to the list of provided formats for this particular request.
+Usually used to add formats to a single action. See also the
+controller-level provides that affects all actions in a controller.
+
+
Parameters
+
+
*formats<Symbol>:
A list of formats to add to the per-action list of provided formats.
+
+
+
+
Raises
+
+
Merb::ResponderMixin::ContentTypeAlreadySet:
Content negotiation already occurred, and the content_type is set.
+
+
+
+
Returns
+
+
Array[Symbol]:
List of formats passed in.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/responder.rb, line 219
+ defprovides(*formats)
+ if@_content_type
+ raiseContentTypeAlreadySet, "Cannot modify provided_formats because content_type has already been set"
+ end
+ @_provided_formats = self._provided_formats|formats# merges with class_provided_formats if not already
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lib/merb-core/controller/mixins/responder.rb
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ()
+
+
+Clear the list of provides.
+
+
Returns
+
+
Array:
An empty Array.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/responder.rb, line 177
+ defclear_provides
+ self.class_provided_formats.clear
+ end
+
+
+
+
+
+ (*formats)
+
+
+This class should not provide any of this list of formats, despite any.
+other definitions previously or in superclasses.
+
+
Parameters
+
+
*formats<Symbol>:
Registered mime-types.
+
+
+
+
Returns
+
+
Array[Symbol]:
List of formats that remain after removing the ones not to provide.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/responder.rb, line 167
+ defdoes_not_provide(*formats)
+ self.class_provided_formats-=formats
+ end
+
+
+
+
+
+ (*formats)
+
+
+This class should only provide the formats listed here, despite any other
+definitions previously or in superclasses.
+
+
Parameters
+
+
*formats<Symbol>:
Registered mime-types.
+
+
+
+
Returns
+
+
Array[Symbol]:
List of formats passed in.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/responder.rb, line 151
+ defonly_provides(*formats)
+ clear_provides
+ provides(*formats)
+ end
+
+
+
+
+
+ (*formats)
+
+
+Adds symbols representing formats to the controller’s default list of
+provided_formats. These will apply to every action in the controller,
+unless modified in the action. If the last argument is a Hash or an Array, these are regarded as arguments to pass
+to the to_<mime_type> method as needed.
+
+
Parameters
+
+
*formats<Symbol>:
A list of mime-types that the controller should provide.
+
+
+
+
Returns
+
+
Array[Symbol]:
List of formats passed in.
+
+
+
+
Examples
+
+ provides :html, :xml
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/responder.rb, line 137
+ defprovides(*formats)
+ self.class_provided_formats|=formats
+ end
+
+
+
+
+
+ ()
+
+
+Reset the list of provides to include only :html.
+
+
Returns
+
+
Array[Symbol]:
[:html].
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/responder.rb, line 187
+ defreset_provides
+ only_provides(:html)
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lib/merb-core/controller/mixins/responder.rb
+
+
+
+
+ StandardError
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lib/merb-core/controller/mixins/authentication.rb
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (realm = "Application", &authenticator)
+
+
+Attempts to authenticate the user via HTTP Basic authentication. Takes a
+block with the username and password, if the block yields false the
+authentication is not accepted and :halt is thrown.
+
+
+If no block is passed, basic_authentication, the request and
+authenticate methods can be chained. These can be used to
+independently request authentication or confirm it, if more control is
+desired.
+
+
Parameters
+
+
realm<~to_s>:
The realm to authenticate against. Defaults to ‘Application’.
+
+
+
&authenticator:
A block to check if the authentication is valid.
+
+
+ class Application < Merb::Controller
+
+ before :authenticate
+
+ protected
+
+ def authenticate
+ basic_authentication("My App") do |username, password|
+ password == "secret"
+ end
+ end
+
+ end
+
+ class Application < Merb::Controller
+
+ before :authenticate
+
+ def authenticate
+ user = basic_authentication.authenticate do |username, password|
+ User.authenticate(username, password)
+ end
+
+ if user
+ @current_user = user
+ else
+ basic_authentication.request
+ end
+ end
+
+ end
+
+
+If you need to request basic authentication inside an action you need to
+use the request! method.
+
+
Example
+
+ class Sessions < Application
+
+ def new
+ case content_type
+ when :html
+ render
+
+ else
+ user = basic_authentication.authenticate do |username, password|
+ User.authenticate(username, password)
+ end
+
+ if user
+ display(user)
+ else
+ basic_authentication.request
+ end
+ end
+ end
+
+ end
+
Whether there has been any basic authentication credentials provided
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/authentication.rb, line 142
+ defprovided?
+ @auth.provided?
+ end
+
+
+
+
+
+ ()
+
+
+Request basic authentication and halt the
+filter chain. This is for use in a before filter.
+
+
Throws
+
+:halt with an "HTTP Basic: Access denied." message with no
+layout, and sets the status to Unauthorized.
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/exceptions.rb, line 219
+ definherited(subclass)
+ # don't set the constant yet - any class methods will be called after self.inherited
+ # unless self.status = ... is set explicitly, the status code will be inherited
+ register_status_code(subclass, self.status) ifself.status?
+ end
+
+
+
+
+
+ ()
+
+
+Gets the actual status-code for an Exception
+class.
+
+
+As usual, this can come from a constant upwards in the inheritance chain.
+
+
Returns
+
+
Fixnum:
The status code of this exception.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/exceptions.rb, line 174
+ defstatus
+ const_get(:STATUS) rescue0
+ end
+
+
+
+
+
+ (num)
+
+
+Sets the actual status-code for an Exception
+class.
+
+
+If possible, set the STATUS constant, and update any previously registered
+(inherited) status-code.
+
The status set on this exception, or nil if a status was already set.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/exceptions.rb, line 191
+ defstatus=(num)
+ unlessself.status?
+ register_status_code(self, num)
+ self.const_set(:STATUS, num.to_i)
+ end
+ end
+
+
+
+
+
+ ()
+
+
+See if a status-code has been defined (on self explicitly).
+
+
A proc that should get called outside the mutex, and which will return the
+value to render.
+
+
+
+
Returns
+
+
Proc:
A block that the server can call later, allowing Merb
+to release the thread lock and render another request.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/controller.rb, line 86
+ defrender_deferred(&blk)
+ Proc.newdo|response|
+ response.write(blk.call)
+ end
+ end
+
+
+
+
+
+ (str, &blk)
+
+
+Renders the passed in string, then calls the block outside the mutex and
+after the string has been returned to the client.
+
+
Parameters
+
+
str<String>:
A String to return to the client.
+
+
+
&blk:
A block that should get called once the string has been returned.
+
+
+
+
Returns
+
+
Proc:
A block that Mongrel can call after returning the
+string to the user.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/controller.rb, line 104
+ defrender_then_call(str, &blk)
+ Proc.newdo|response|
+ response.write(str)
+ blk.call
+ end
+ end
+
+
+
+
+
+ (&blk)
+
+
+Enqueues a block to run in a background thread outside of the request
+response dispatch.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/controller.rb, line 17
+ defrun_later(&blk)
+ Merb::Dispatcher.work_queue<<blk
+ end
+
+
+
+
+
+ (data)
+
+
+Writes a chunk from render_chunked to the
+response that is sent back to the client. This should only be called within
+a render_chunked block.
+
+
Parameters
+
+
data<String>:
a chunk of data to return.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/controller.rb, line 69
+ defsend_chunk(data)
+ only_runs_on_mongrel!
+ @response.write('%x'%data.size+"\r\n")
+ @response.write(data+"\r\n")
+ end
+
+
+
+
+
+ (data, opts={})
+
+
+Sends binary data over HTTP to the user as a file download. May set content
+type, apparent file name, and specify whether to show data inline or
+download as an attachment.
+
+
Parameters
+
+
data<String>:
Path to file to send to the client.
+
+
+
opts<Hash>:
Options for sending the data (see below).
+
+
+
+
Options (opts)
+
+
:disposition<String>:
The disposition of the file send. Defaults to "attachment".
+
+
+
:filename<String>:
The name to use for the file. Defaults to the filename of file.
+
+
+
:type<String>:
The content type.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/controller.rb, line 210
+ defsend_data(data, opts={})
+ opts.update(Merb::Const::DEFAULT_SEND_FILE_OPTIONS.merge(opts))
+ disposition = opts[:disposition].dup||DEFAULT_SEND_FILE_OPTIONS[:disposition]
+ disposition<<%(; filename="#{opts[:filename]}")ifopts[:filename]
+ headers.update(
+ Merb::Const::CONTENT_TYPE =>opts[:type].strip, # fixes a problem with extra '\r' with some browsers
+ Merb::Const::CONTENT_DISPOSITION =>disposition,
+ Merb::Const::CONTENT_TRANSFER_ENCODING =>Merb::Const::BINARY
+ )
+ data
+ end
+
+
+
+
+
+ (file, opts={})
+
+
+Sends a file over HTTP. When given a path to a file, it will set the right
+headers so that the static file is served directly.
+
+
Parameters
+
+
file<String>:
Path to file to send to the client.
+
+
+
opts<Hash>:
Options for sending the file (see below).
+
+
+
+
Options (opts)
+
+
:disposition<String>:
The disposition of the file send. Defaults to "attachment".
+
+
+
:filename<String>:
The name to use for the file. Defaults to the filename of file.
+
+
+
:type<String>:
The content type.
+
+
+
+
Returns
+
+
IO:
An I/O stream for the file.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/mixins/controller.rb, line 177
+ defsend_file(file, opts={})
+ opts.update(Merb::Const::DEFAULT_SEND_FILE_OPTIONS.merge(opts))
+ disposition = opts[:disposition].dup||DEFAULT_SEND_FILE_OPTIONS[:disposition]
+ disposition<<%(; filename="#{opts[:filename] ? opts[:filename] : File.basename(file)}")
+ headers.update(
+ Merb::Const::CONTENT_TYPE =>opts[:type].strip, # fixes a problem with extra '\r' with some browsers
+ Merb::Const::CONTENT_DISPOSITION =>disposition,
+ Merb::Const::CONTENT_TRANSFER_ENCODING =>Merb::Const::BINARY
+ )
+ Proc.newdo|response|
+ file = File.open(file, 'rb')
+ whilechunk = file.read(16384)
+ response.writechunk
+ end
+ file.close
+ end
+ end
+
+
+
+
+
+ (name, value, expires)
+
+
+Sets a cookie to be included in the response.
+
+
+If you need to set a cookie, then use the cookies hash.
+
+
Parameters
+
+
name<~to_s>:
A name for the cookie.
+
+
+
value<~to_s>:
A value for the cookie.
+
+
+
expires<~gmtime:~strftime, Hash>:
An expiration time for the cookie, or a hash of cookie options.
+
+
A hash containing the controller and action along with any parameters
+
+
+
+ ]]>
+
+
+
+# File lib/merb-core/test/helpers/route_helper.rb, line 85
+ defrequest_to(path, method = :get, env = {})
+ env[:request_method] ||=method.to_s.upcase
+ env[:request_uri] = path
+
+ check_request_for_route(build_request({}, env))
+ end
+
+
+
+
+
+ (*args)
+
+
+Mimics the resource method available to controllers
+
+
Paramaters
+
+
resources<Object>:
The resources to generate URLs from
+
+
+
params<Hash>:
Any extra parameters that are required.
+
+
+
+
Returns
+
+
String:
The generated URL.
+
+
+
+ ]]>
+
+
+
+# File lib/merb-core/test/helpers/route_helper.rb, line 73
+ defresource(*args)
+ args<<@request_params|| {}
+ Merb::Router.resource(*args)
+ end
+
+
+
+
+
+ (*args)
+
+
+There are three possible ways to use this method. First, if you have a
+named route, you can specify the route as the first parameter as a symbol
+and any paramters in a hash. Second, you can generate the default route by
+just passing the params hash, just passing the params hash. Finally, you
+can use the anonymous parameters. This allows you to specify the parameters
+to a named route in the order they appear in the router.
+
+
Parameters(Named Route)
+
+
name<Symbol>:
The name of the route.
+
+
+
args<Hash>:
Parameters for the route generation.
+
+
+
+
Parameters(Default Route)
+
+
args<Hash>:
Parameters for the route generation. This route will use the default route.
+
+
+
+
Parameters(Anonymous Parameters)
+
+
name<Symbol>:
The name of the route.
+
+
+
args<Array>:
An array of anonymous parameters to generate the route with. These
+parameters are assigned to the route parameters in the order that they are
+passed.
+
+
The failure message to be displayed in negative matches.
+
+
+
+ ]]>
+
+
+
+# File lib/merb-core/test/matchers/controller_matchers.rb, line 86
+ defnegative_failure_message
+ "expected #{@target.name} not to provide #{@expected}, but it does"
+ end
+
+
+
+
+
+ ()
+
+ Returns
+
The failure message to be displayed in negative matches.
+
+
+
+ ]]>
+
+
+
+# File lib/merb-core/test/matchers/controller_matchers.rb, line 23
+ defnegative_failure_message
+ "expected#{inspect_target} not to redirect"
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lib/merb-core/test/matchers/route_matchers.rb
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (klass_or_name, action)
+
+
+Passes when the actual route parameters match the expected controller class
+and controller action. Exposes a with method for specifying
+parameters.
+
+
Parameters
+
+
klass_or_name<Class, String>:
The controller class or class name to match routes for.
+
+
+
action<~to_s>:
The name of the action to match routes for.
+
+
+
+
Example
+
+ # Passes if a GET request to "/" is routed to the Widgets controller's
+ # index action.
+ request_to("/", :get).should route_to(Widgets, :index)
+
+ # Use the 'with' method for parameter checks
+ request_to("/123").should route_to(widgets, :show).with(:id => "123")
+
The failure message to be displayed in negative matches.
+
+
+
+ ]]>
+
+
+
+# File lib/merb-core/test/matchers/route_matchers.rb, line 64
+ defnegative_failure_message
+ "expected the request not to route to #{@expected_controller.camel_case}##{@expected_action}#{expected_parameters_message}, but it did"
+ end
+
+
+
+
+
+ (parameters)
+
+
+Creates a new paramter matcher.
+
+
The failure message to be displayed in negative matches.
+
+
+
+ ]]>
+
+
+
+# File lib/merb-core/test/matchers/route_matchers.rb, line 114
+ defnegative_failure_message
+ "expected the route not to contain parameters #{@expected.inspect}, but it did"
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lib/merb-core/test/helpers/mock_request_helper.rb
+
+ lib/merb-core/test/helpers/request_helper.rb
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (params = {}, env = {})
+
+
+Prepares and returns a request suitable for dispatching with
+dispatch_request. If you don’t need to modify the request object
+before dispatching (e.g. to add cookies), you probably want to use dispatch_to instead.
+
+
Parameters
+
+
params<Hash>:
An optional hash that will end up as params in the controller instance.
+
+
+
env<Hash>:
An optional hash that is passed to the fake request. Any request options
+should go here (see fake_request),
+including :req or :post_body for setting the request body itself.
+
+
A request object that has been setup for testing.
+
+
+
controller_klass<Merb::Controller>:
The class object off the controller to dispatch the action to.
+
+
+
action<Symbol>:
The action to dispatch the request to.
+
+
+
&blk:
The controller is yielded to the block provided for actions prior to
+the action being dispatched.
+
+
+
+
Returns
+
+An instance of controller_klass based on the parameters.
+
+
Notes
+
+Does not use routes.
+
+
+:api: public @deprecated
+
+ ]]>
+
+
+
+# File lib/merb-core/test/helpers/mock_request_helper.rb, line 364
+ defdispatch_request(request, controller_klass, action, &blk)
+ controller = controller_klass.new(request)
+ yieldcontrollerifblock_given?
+ controller._dispatch(action)
+
+ Merb.logger.infocontroller._benchmarks.inspect
+ Merb.logger.flush
+
+ controller
+ end
+
+
+
+
+
+ (controller_klass, action, params = {}, env = {}, &blk)
+
+
+Dispatches an action to the given class. This bypasses the router and is
+suitable for unit testing of controllers.
+
+
Parameters
+
+
controller_klass<Controller>:
The controller class object that the action should be dispatched to.
+
+
+
action<Symbol>:
The action name, as a symbol.
+
+
+
params<Hash>:
An optional hash that will end up as params in the controller instance.
+
+
+
env<Hash>:
An optional hash that is passed to the fake request. Any request options
+should go here (see fake_request),
+including :req or :post_body for setting the request body itself.
+
+
+
&blk:
The controller is yielded to the block provided for actions prior to
+the action being dispatched.
+
+
+
+
Example
+
+ dispatch_to(MyController, :create, :name => 'Homer' ) do |controller|
+ controller.stub!(:current_user).and_return(@user)
+ end
+
+
Notes
+
+Does not use routes.
+
+
+:api: public @deprecated
+
+ ]]>
+
+
+
+# File lib/merb-core/test/helpers/mock_request_helper.rb, line 116
+ defdispatch_to(controller_klass, action, params = {}, env = {}, &blk)
+ params = merge_controller_and_action(controller_klass, action, params)
+ dispatch_request(build_request(params, env), controller_klass, action.to_s, &blk)
+ end
+
+
+
+
+
+ (controller_klass, action, username, password, params = {}, env = {}, &blk)
+
+
+Dispatches an action to the given class and using HTTP Basic Authentication
+This bypasses the router and is suitable for unit testing of controllers.
+
+
Parameters
+
+
controller_klass<Controller>:
The controller class object that the action should be dispatched to.
+
+
+
action<Symbol>:
The action name, as a symbol.
+
+
+
username<String>:
The username.
+
+
+
password<String>:
The password.
+
+
+
params<Hash>:
An optional hash that will end up as params in the controller instance.
+
+
+
env<Hash>:
An optional hash that is passed to the fake request. Any request options
+should go here (see fake_request),
+including :req or :post_body for setting the request body itself.
+
+
+
&blk:
The controller is yielded to the block provided for actions prior to
+the action being dispatched.
+
+
+
+
Example
+
+ dispatch_with_basic_authentication_to(MyController, :create, 'Fred', 'secret', :name => 'Homer' ) do |controller|
+ controller.stub!(:current_user).and_return(@user)
+ end
+
+ ]]>
+
+
+
+# File lib/merb-core/test/helpers/mock_request_helper.rb, line 13
+ definitialize(env = {}, req = StringIO.new)
+ env.environmentize_keys!
+ env['rack.input'] = req
+ super(DEFAULT_ENV.merge(env))
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lib/merb-core/test/helpers/multipart_request_helper.rb
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (controller_klass, action, params = {}, env = {}, &blk)
+
+
+ Similar to dispatch_to but allows for sending files inside params.
+
+ ==== Paramters
+ controller_klass<Controller>::
+ The controller class object that the action should be dispatched to.
+ action<Symbol>:: The action name, as a symbol.
+ params<Hash>::
+ An optional hash that will end up as params in the controller instance.
+ env<Hash>::
+ An optional hash that is passed to the fake request. Any request options
+ should go here (see +fake_request+).
+ &blk:: The block is executed in the context of the controller.
+
+ ==== Example
+ dispatch_multipart_to(MyController, :create, :my_file => @a_file ) do |controller|
+ controller.stub!(:current_user).and_return(@user)
+ end
+
+ ==== Notes
+ Set your option to contain a file object to simulate file uploads.
+
+ Does not use routes.
+
+
+If a method default_cookies is defined it will be called. This can be used
+for session fixation purposes for example. The method returns a Hash of key => value pairs.
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/template.rb, line 148
+ defengine_for(path)
+ path = File.expand_path(path)
+ EXTENSIONS[path.match(/\.([^\.]*)$/)[1]]
+ end
+
+
+
+
+
+ (io, locals=[], mod = Merb::InlineTemplates)
+
+
+Takes a template at a particular path and inlines it into a module and adds
+it to the METHOD_LIST table to speed lookup later.
+
+
Parameters
+
+
io<path>:
An IO that responds to path (File or VirtualFile)
+
+
+
locals<Array[Symbol]>:
A list of local names that should be assigned in the template method from
+the arguments hash. Defaults to [].
+
+
The name of the method that the template was compiled into.
+
+
+
+
Notes
+
+Even though this method supports inlining into any module, the method must
+be available to instances of AbstractController that will use it.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/template.rb, line 127
+ definline_template(io, locals=[], mod = Merb::InlineTemplates)
+ full_file_path = File.expand_path(io.path)
+ engine_neutral_path = full_file_path.gsub(/\.[^\.]*$/, "")
+
+ SUPPORTED_LOCALS_LIST[engine_neutral_path] |=localsunlesslocals.empty?
+ ret = METHOD_LIST[engine_neutral_path] =
+ engine_for(full_file_path).compile_template(io, template_name(full_file_path), locals, mod)
+
+ io.close
+ ret
+ end
+
+
+
+
+
+ (path)
+
+
+For a given path, gets an IO object that responds to path.
+
+
+This is so that plugins can override this if they provide mechanisms for
+specifying templates that are not just simple files. The plugin is
+responsible for ensuring that the fake path provided will work with template_for, and thus the RenderMixin in general.
+
+
Parameters
+
+
path<String>:
A full path to find a template for. This is the
+
+
+
+
+ path that the RenderMixin assumes it should find the template
+ in.
+
+
Returns
+
+
IO#path:
An IO object that responds to path (File or VirtualFile).
+
+
+
+
+:api: plugin @overridable
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/template.rb, line 52
+ defload_template_io(path)
+ File.open(path, "r")
+ end
+
+
+
+
+
+ (path, locals)
+
+
+Decides if a template needs to be re/compiled.
+
+
Parameters
+
+
path<String>:
The full path of the template to check support for.
+
+
+
locals<Array[Symbol]>:
The list of locals that need to be supported
+
+
+
+
Returns
+
+
Boolean:
Whether or not the template for the provided path needs to be recompiled
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/template.rb, line 88
+ defneeds_compilation?(path, locals)
+ returntrueifMerb::Config[:reload_templates] ||!METHOD_LIST[path]
+
+ current_locals = SUPPORTED_LOCALS_LIST[path]
+ current_locals!=locals&&
+ !(locals-current_locals).empty?
+ end
+
+
+
+
+
+ (engine, extensions)
+
+
+Registers the extensions that will trigger a particular templating engine.
+
+
Parameters
+
+
engine<Class>:
The class of the engine that is being registered
+
+
+
extensions<Array[String]>:
The list of extensions that will be registered with this templating
+language
+
+
+
+
Raises
+
+
ArgumentError:
engine does not have a compile_template method.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/template.rb, line 172
+ defregister_extensions(engine, extensions)
+ raiseArgumentError, "The class you are registering does not have a compile_template method"unless
+ engine.respond_to?(:compile_template)
+ extensions.each{|ext|EXTENSIONS[ext] = engine }
+ Merb::AbstractController.class_eval"include \#{engine}::Mixin\n"
+ end
+
+
+
+
+
+ ()
+
+
+Gets all known template extensions
+
+
Returns
+
+ Array:: Extension strings.
+
+
+:api: plugin
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/template.rb, line 102
+ deftemplate_extensions
+ EXTENSIONS.keys
+ end
+
+
+
+
+
+ (path, template_stack = [], locals=[])
+
+
+Gets the name of the template method for a particular path.
+
+
Parameters
+
+
path<String>:
A full path to find a template method for.
+
+
+
template_stack<Array>:
The template stack. Not used.
+
+
+
locals<Array[Symbol]>:
The names of local variables
+
+
+
+
Returns
+
+
<String>:
name of the method that inlines the template.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/template.rb, line 67
+ deftemplate_for(path, template_stack = [], locals=[])
+ path = File.expand_path(path)
+
+ ifneeds_compilation?(path, locals)
+ file = Dir["#{path}.{#{template_extensions.join(',')}}"].first
+ METHOD_LIST[path] = file? inline_template(load_template_io(file), locals) :nil
+ end
+
+ METHOD_LIST[path]
+ end
+
+
+
+
+
+ (path)
+
+
+Gets the template’s method name from a full path. This replaces
+non-alphanumeric characters with __ and "." with "_"
+
+
+Collisions are potentially possible with something like: ~foo.bar and
+__foo.bar or !foo.bar.
+
+
Parameters
+
+
path<String>:
A full path to convert to a valid Ruby method name
+
+
+
+
Returns
+
+
String:
The template name.
+
+
+
+
+We might want to replace this with something that varies the character
+replaced based on the non-alphanumeric character to avoid edge-case
+collisions.
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/session/memcached.rb, line 50
+ defstore_session(session_id, data)
+ set("session:#{session_id}", data)
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lib/merb-core/dispatch/session/cookie.rb
+
+
+
+
+ Merb::SessionContainer
+
+
+
+
+If you have more than 4K of session data or don’t want your data to
+be visible to the user, pick another session store.
+
+
+CookieOverflow is raised
+if you attempt to store more than 4K of data. TamperedWithCookie is
+raised if the data integrity check fails.
+
+
+A message digest is included with the cookie to ensure data integrity: a
+user cannot alter session data without knowing the secret key included in
+the hash.
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/session/cookie.rb, line 78
+ definitialize(session_id, cookie, secret)
+ supersession_id
+ ifsecret.blank?||secret.length<16
+ msg = "You must specify a session_secret_key in your init file, and it must be at least 16 characters"
+ Merb.logger.warn(msg)
+ raiseArgumentError, msg
+ end
+ @secret = secret
+ self.update(unmarshal(cookie))
+ end
+
+
+
+
+
+ (request)
+
+
+Sets up a new session on request: make it available on request instance.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/session/cookie.rb, line 109
+ defregenerate
+ self.session_id = Merb::SessionMixin.rand_uuid
+ end
+
+
+
+
+
+ ()
+
+
+Creates the raw cookie string; includes an HMAC keyed message digest.
+
+
Returns
+
+
String:
Cookie value.
+
+
+
+
Raises
+
+
CookieOverflow:
More than 4K of data put into session.
+
+
+
+
Notes
+
+Session data is converted to a Hash first, since a container might choose to marshal it,
+which would make it persist attributes like ‘needs_new_cookie’,
+which it shouldn’t.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/session/cookie.rb, line 127
+ defto_cookie
+ unlessself.empty?
+ data = self.serialize
+ value = Merb::Parse.escape"#{data}--#{generate_digest(data)}"
+ ifvalue.size>MAX
+ msg = "Cookies have limit of 4K. Session contents: #{data.inspect}"
+ Merb.logger.error!(msg)
+ raiseCookieOverflow, msg
+ end
+ value
+ end
+ end
+
+
+
+
+
+
+
+
+
+
+
+ ()
+
+
+Serializes current session data as a Hash. Uses Base64
+encoding for integrity.
+
+
Returns
+
+
String:
Base64 encoded dump of the session hash.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/session/cookie.rb, line 189
+ defserialize
+ Base64.encode64(Marshal.dump(self.to_hash)).chop
+ end
+
+
+
+
+
+ (data)
+
+
+Unserializes the raw cookie data to a Hash
+
+
Returns
+
+
Hash:
the session hash Base64 decoded from the data dump.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/config.rb, line 103
+ defdelete(key)
+ @configuration.delete(key)
+ end
+
+
+
+
+
+ (key, default)
+
+
+Retrieves the value of a config entry, returning the provided default if
+the key is not present
+
+
Parameters
+
+
key<Object>:
The key to retrieve the parameter for.
+
+
+
default<Object>:
The default value to return if the parameter is not set.
+
+
+
+
Returns
+
+
Object:
The value of the configuration parameter or the default.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/config.rb, line 118
+ deffetch(key, default)
+ @configuration.fetch(key, default)
+ end
+
+
+
+
+
+ (key)
+
+
+Detects whether the provided key is in the config.
+
+
Parameters
+
+
key<Object>:
The key to check.
+
+
+
+
Returns
+
+
Boolean:
True if the key exists in the config.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/config.rb, line 66
+ defkey?(key)
+ @configuration.key?(key)
+ end
+
+
+
+
+
+ (method, *args)
+
+
+Allows retrieval of single key config values via Merb.config.<key>
+Allows single key assignment via Merb.config.<key> = …
+
+
Parameters
+
+
method<~to_s>:
Method name as hash key value.
+
+
+
*args:
Value to set the configuration parameter to.
+
+
+
+
Returns
+
+The value of the entry fetched or assigned to.
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/config.rb, line 444
+ defmethod_missing(method, *args)
+ ifmethod.to_s[-1,1] =='='
+ @configuration[method.to_s.tr('=','').to_sym] = *args
+ else
+ @configuration[method]
+ end
+ end
+
+
+
+
+
+ (argv = ARGV)
+
+
+Parses the command line arguments and stores them in the config.
+
+
Parameters
+
+
argv<String>:
The command line arguments. Defaults to ARGV.
+
+
+
+
Returns
+
+The configuration as a hash.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/config.rb, line 181
+ defparse_args(argv = ARGV)
+ @configuration||= {}
+ # Our primary configuration hash for the length of this method
+ options = {}
+
+ # Environment variables always win
+ options[:environment] = ENV["MERB_ENV"] ifENV["MERB_ENV"]
+
+ # Build a parser for the command line arguments
+ opts = OptionParser.newdo|opts|
+ opts.version = Merb::VERSION
+
+ opts.banner = "Usage: merb [uGdcIpPhmailLerkKX] [argument]"
+ opts.define_head"Merb. Pocket rocket web framework"
+ opts.separator'*'*80
+ opts.separator"If no flags are given, Merb starts in the " \
+ "foreground on port 4000."
+ opts.separator'*'*80
+
+ opts.on("-u", "--user USER", "This flag is for having merb run " \
+ "as a user other than the one currently logged in. Note: " \
+ "if you set this you must also provide a --group option " \
+ "for it to take effect.") do|user|
+ options[:user] = user
+ end
+
+ opts.on("-G", "--group GROUP", "This flag is for having merb run " \
+ "as a group other than the one currently logged in. Note: " \
+ "if you set this you must also provide a --user option " \
+ "for it to take effect.") do|group|
+ options[:group] = group
+ end
+
+ opts.on("-d", "--daemonize", "This will run a single merb in the " \
+ "background.") do|daemon|
+ options[:daemonize] = true
+ end
+
+ opts.on("-N", "--no-daemonize", "This will allow you to run a " \
+ "cluster in console mode") do|no_daemon|
+ options[:daemonize] = false
+ end
+
+ opts.on("-c", "--cluster-nodes NUM_MERBS", Integer,
+ "Number of merb daemons to run.") do|nodes|
+ options[:daemonize] = trueunlessoptions.key?(:daemonize)
+ options[:cluster] = nodes
+ end
+
+ opts.on("-I", "--init-file FILE", "File to use for initialization " \
+ "on load, defaults to config/init.rb") do|init_file|
+ options[:init_file] = init_file
+ end
+
+ opts.on("-p", "--port PORTNUM", Integer, "Port to run merb on, " \
+ "defaults to 4000.") do|port|
+ options[:port] = port
+ end
+
+ opts.on("-o", "--socket-file FILE", "Socket file to run merb on, " \
+ "defaults to [Merb.root]/log/merb.sock. This is for " \
+ "web servers, like thin, that use sockets." \
+ "Specify this *only* if you *must*.") do|port|
+ options[:socket_file] = port
+ end
+
+ opts.on("-s", "--socket SOCKNUM", Integer, "Socket number to run " \
+ "merb on, defaults to 0.") do|port|
+ options[:socket] = port
+ end
+
+ opts.on("-n", "--name NAME", String, "Set the name of the application. "\
+ "This is used in the process title and log file names.") do|name|
+ options[:name] = name
+ end
+
+ opts.on("-P", "--pid PIDFILE", "PID file, defaults to " \
+ "[Merb.root]/log/merb.main.pid for the master process and" \
+ "[Merb.root]/log/merb.[port number].pid for worker " \
+ "processes. For clusters, use %s to specify where " \
+ "in the file merb should place the port number. For " \
+ "instance: -P myapp.%s.pid") do|pid_file|
+ options[:pid_file] = pid_file
+ end
+
+ opts.on("-h", "--host HOSTNAME", "Host to bind to " \
+ "(default is 0.0.0.0).") do|host|
+ options[:host] = host
+ end
+
+ opts.on("-m", "--merb-root /path/to/approot", "The path to the " \
+ "Merb.root for the app you want to run " \
+ "(default is current working directory).") do|root|
+ options[:merb_root] = File.expand_path(root)
+ end
+
+ adapters = [:mongrel, :emongrel, :thin, :ebb, :fastcgi, :webrick]
+
+ opts.on("-a", "--adapter ADAPTER",
+ "The rack adapter to use to run merb (default is mongrel)" \
+ "[#{adapters.join(', ')}]") do|adapter|
+ options[:adapter] ||=adapter
+ end
+
+ opts.on("-R", "--rackup FILE", "Load an alternate Rack config " \
+ "file (default is config/rack.rb)") do|rackup|
+ options[:rackup] = rackup
+ end
+
+ opts.on("-i", "--irb-console", "This flag will start merb in " \
+ "irb console mode. All your models and other classes will " \
+ "be available for you in an irb session.") do|console|
+ options[:adapter] = 'irb'
+ end
+
+ opts.on("-S", "--sandbox", "This flag will enable a sandboxed irb " \
+ "console. If your ORM supports transactions, all edits will " \
+ "be rolled back on exit.") do|sandbox|
+ options[:sandbox] = true
+ end
+
+ opts.on("-l", "--log-level LEVEL", "Log levels can be set to any of " \
+ "these options: debug < info < warn < error < " \
+ "fatal (default is info)") do|log_level|
+ options[:log_level] = log_level.to_sym
+ options[:force_logging] = true
+ end
+
+ opts.on("-L", "--log LOGFILE", "A string representing the logfile to " \
+ "use. Defaults to [Merb.root]/log/merb.[main].log for the " \
+ "master process and [Merb.root]/log/merb[port number].log" \
+ "for worker processes") do|log_file|
+ options[:log_file] = log_file
+ options[:force_logging] = true
+ end
+
+ opts.on("-e", "--environment STRING", "Environment to run Merb " \
+ "under [development, production, testing] " \
+ "(default is development)") do|env|
+ options[:environment] = env
+ end
+
+ opts.on("-r", "--script-runner ['RUBY CODE'| FULL_SCRIPT_PATH]",
+ "Command-line option to run scripts and/or code in the " \
+ "merb app.") do|code_or_file|
+ options[:runner_code] = code_or_file
+ options[:adapter] = 'runner'
+ end
+
+ opts.on("-K", "--graceful PORT or all", "Gracefully kill one " \
+ "merb proceses by port number. Use merb -K all to " \
+ "gracefully kill all merbs.") do|ports|
+ options[:action] = :kill
+ ports = "main"ifports=="all"
+ options[:port] = ports
+ end
+
+ opts.on("-k", "--kill PORT", "Force kill one merb worker " \
+ "by port number. This will cause the worker to" \
+ "be respawned.") do|port|
+ options[:action] = :kill_9
+ port = "main"ifport=="all"
+ options[:port] = port
+ end
+
+ opts.on("--fast-deploy", "Reload the code, but not your" \
+ "init.rb or gems") do
+ options[:action] = :fast_deploy
+ end
+
+ # @todo Do we really need this flag? It seems unlikely to want to
+ # change the mutex from the command-line.
+ opts.on("-X", "--mutex on/off", "This flag is for turning the " \
+ "mutex lock on and off.") do|mutex|
+ ifmutex=="off"
+ options[:use_mutex] = false
+ else
+ options[:use_mutex] = true
+ end
+ end
+
+ opts.on("-D", "--debugger", "Run merb using rDebug.") do
+ begin
+ require"ruby-debug"
+ Debugger.start
+
+ # Load up any .rdebugrc files we find
+ [".", ENV["HOME"], ENV["HOMEPATH"]].eachdo|script_dir|
+ script_file = "#{script_dir}/.rdebugrc"
+ Debugger.run_scriptscript_file, StringIO.newifFile.exists?(script_file)
+ end
+
+ ifDebugger.respond_to?(:settings)
+ Debugger.settings[:autoeval] = true
+ end
+ puts"Debugger enabled"
+ rescueLoadError
+ puts"You need to install ruby-debug to run the server in " \
+ "debugging mode. With gems, use `gem install ruby-debug'"
+ exit
+ end
+ end
+
+ opts.on("-V", "--verbose", "Print extra information") do
+ options[:verbose] = true
+ end
+
+ opts.on("-C", "--console-trap", "Enter an irb console on ^C") do
+ options[:console_trap] = true
+ end
+
+ opts.on("-?", "-H", "--help", "Show this help message") do
+ putsopts
+ exit
+ end
+ end
+
+ # Parse what we have on the command line
+ begin
+ opts.parse!(argv)
+ rescueOptionParser::InvalidOption =>e
+ Merb.fatal!e.message, e
+ end
+ Merb::Config.setup(options)
+ end
+
+
+
+
+
+ ()
+
+
+Returns stores list constructed from configured session stores (:session_stores config option) or default one
+(:session_store config option).
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/session.rb, line 11
+ defself.session_stores
+ @session_stores||=begin
+ config_stores = Array(
+ Merb::Config[:session_stores] ||Merb::Config[:session_store]
+ )
+ config_stores.map { |name|name.to_sym }
+ end
+ end
+
+
+
+
+
+ (settings = {})
+
+
+Sets up the configuration by storing the given settings.
+
+
Parameters
+
+
settings<Hash>:
Configuration settings to use. These are merged with the defaults.
+
+
+
+
Returns
+
+The configuration as a hash.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/config.rb, line 153
+ defsetup(settings = {})
+ config = defaults.merge(settings)
+
+ unlessconfig[:reload_classes]
+ config[:fork_for_class_load] = false
+ end
+
+ dev_mode = config[:environment] =="development"
+ unlessconfig.key?(:reap_workers_quickly)
+ config[:reap_workers_quickly] = dev_mode&!config[:cluster]
+ end
+
+ unlessconfig.key?(:bind_fail_fatal)
+ config[:bind_fail_fatal] = dev_mode
+ end
+
+ @configuration = config
+ end
+
+
+
+
+
+ ()
+
+
+Returns the configuration as a hash.
+
+
Returns
+
+
Hash:
The config as a hash.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/config.rb, line 128
+ defto_hash
+ @configuration
+ end
+
+
+
+
+
+ ()
+
+
+Returns the config as YAML.
+
+
+The data (self) is converted to a Hash first, since a
+container might choose to do a full Marshal on the data, which would make
+it persist attributes like ‘needs_new_cookie’, which it
+shouldn’t.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/session/store_container.rb, line 135
+ deffinalize(request)
+ if@_destroy
+ store.delete_session(self.session_id)
+ request.destroy_session_cookie
+ else
+ if_fingerprint!=Marshal.dump(data = self.to_hash).hash
+ begin
+ store.store_session(request.session(self.class.session_store_type).session_id, data)
+ rescue =>err
+ Merb.logger.warn!("Could not persist session to #{self.class.name}: #{err.message}")
+ end
+ end
+ ifneeds_new_cookie||Merb::SessionMixin.needs_new_cookie?
+ request.set_session_id_cookie(self.session_id)
+ end
+ end
+ end
+
+
+
+
+
+ ()
+
+
+Regenerate the session ID.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/merb_controller.rb, line 107
+ defself._callable_methods
+ callables = []
+ klass = self
+ begin
+ callables<< (klass.public_instance_methods(false) +klass._shown_actions) -klass._hidden_actions
+ klass = klass.superclass
+ enduntilklass==Merb::AbstractController||klass==Object
+ callables.flatten.reject{|action|action=~/^_.*/}
+ end
+
+
+
+
+
+ (params)
+
+
+This is a stub method so plugins can implement param filtering if they
+want.
+
+
Parameters
+
+
params<Hash{Symbol => String}>:
A list of params
+
+
+
+
Returns
+
+
Hash{Symbol => String}:
A new list of params, filtered as desired
+
+
+
+
+:api: plugin @overridable
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/merb_controller.rb, line 97
+ defself._filter_params(params)
+ params
+ end
+
+
+
+
+
+ ()
+
+
+Sets a controller to be "abstract" This controller will not be
+able to be routed to and is used for super classing only
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/merb_controller.rb, line 359
+ defself.abstract!
+ @_abstract = true
+ end
+
+
+
+
+
+ ()
+
+
+Asks a controller if it is abstract
+
+
Returns
+
+Boolean
+
+
+ true if the controller has been set as abstract
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/merb_controller.rb, line 370
+ defself.abstract?
+ !!@_abstract
+ end
+
+
+
+
+
+ ()
+
+
+The list of actions that are callable, after taking defaults,
+_hidden_actions and _shown_actions into consideration. It is calculated
+once, the first time an action is dispatched for this controller.
+
+
Returns
+
+
SimpleSet[String]:
A set of actions that should be callable.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/merb_controller.rb, line 83
+ defself.callable_actions
+ @callable_actions||=Extlib::SimpleSet.new(_callable_methods)
+ end
+
+
+
+
+
+ (*names)
+
+
+Hides each of the given methods from being callable as actions.
+
+
Parameters
+
+
*names<~to-s>:
Actions that should be added to the list.
+
+
+
+
Returns
+
+
Array[String]:
An array of actions that should not be possible to dispatch to.
+
+
An integer code for the status. Defaults to 200.
+
+
+
headers<Hash{header => value}>:
A hash of headers to start the controller with. These headers can be
+overridden later by the headers method.
+
+
+
+
+:api: plugin @overridable
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/merb_controller.rb, line 170
+ definitialize(request, status=200, headers={'Content-Type' =>'text/html; charset=utf-8'})
+ super()
+ @request, @_status, @headers = request, status, headers
+ end
+
+
+
+
+
+ (*names)
+
+
+Makes each of the given methods being callable as actions. You can use this
+to make methods included from modules callable as actions.
+
+
Parameters
+
+
*names<~to-s>:
Actions that should be added to the list.
+
+
+
+
Returns
+
+
Array[String]:
An array of actions that should be dispatched to even if they would not
+otherwise be.
+
+
+
+
Example
+
+ module Foo
+ def self.included(base)
+ base.show_action(:foo)
+ end
+
+ def foo
+ # some actiony stuff
+ end
+
+ def foo_helper
+ # this should not be an action
+ end
+ end
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/merb_controller.rb, line 71
+ defself.show_action(*names)
+ self._shown_actions = self._shown_actions|names.map {|n|n.to_s}
+ end
+
+
+
+
+
+ ()
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/merb_controller.rb, line 12
+ defself.subclasses_list() _subclassesend
+
+
+
+
+
+
+
+
+
+
+
+ (template, type)
+
+
+The location to look for a template and mime-type. This is overridden from
+AbstractController, which defines a
+version of this that does not involve mime-types.
+
+
Parameters
+
+
template<String>:
The absolute path to a template - without mime and template extension. The
+mime-type extension is optional - it will be appended from the current
+content type if it hasn’t been added already.
+
+
+
type<~to_s>:
The mime-type of the template that will be rendered. Defaults to nil.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/merb_controller.rb, line 187
+ def_dispatch(action=:index)
+ Merb.logger.info("Params: #{self.class._filter_params(request.params).inspect}")
+ start = Time.now
+ ifself.class.callable_actions.include?(action.to_s)
+ super(action)
+ else
+ raiseActionNotFound, "Action '#{action}' was not found in #{self.class}"
+ end
+ @_benchmarks[:action_time] = Time.now-start
+ self
+ end
+
+
+
+
+
+ (context, type, controller)
+
+
+The location to look for a template for a particular controller, context,
+and mime-type. This is overridden from AbstractController, which defines a
+version of this that does not involve mime-types.
+
+
Parameters
+
+
context<~to_s>:
The name of the action or template basename that will be rendered.
+
+
+
type<~to_s>:
The mime-type of the template that will be rendered. Defaults to nil.
+
+
+
controller<~to_s>:
The name of the controller that will be rendered. Defaults to
+controller_name. This will be "layout" for rendering a layout.
+
+
+
+
Notes
+
+By default, this renders ":controller/:action.:type". To change
+this, override it in your application class or in individual controllers.
+
+
+:api: public @overridable
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/merb_controller.rb, line 135
+ def_template_location(context, type, controller)
+ _conditionally_append_extension(controller? "#{controller}/#{context}":"#{context}", type)
+ end
+
+
+
+
+
+ (*args)
+
+
+Returns the absolute url including the passed protocol and host.
+
+
+This uses the same arguments as the url method, with added requirements of
+protocol and host options.
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/merb_controller.rb, line 230
+ defparams() request.paramsend
+
+
+
+
+
+ ()
+
+
+The results of the controller’s render, to be returned to Rack.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/merb_controller.rb, line 206
+ defstatus
+ @_status
+ end
+
+
+
+
+
+ (s)
+
+
+Sets the response status code.
+
+
Parameters
+
+
s<Fixnum, Symbol>:
A status-code or named http-status
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/merb_controller.rb, line 216
+ defstatus=(s)
+ ifs.is_a?(Symbol) &&STATUS_CODES.key?(s)
+ @_status = STATUS_CODES[s]
+ elsifs.is_a?(Fixnum)
+ @_status = s
+ else
+ raiseArgumentError, "Status should be of type Fixnum or Symbol, was #{s.class}"
+ end
+ end
+
+
+
+
+
+ (name, *args)
+
+
+There are three possible ways to use this method. First, if you have a
+named route, you can specify the route as the first parameter as a symbol
+and any parameters in a hash. Second, you can generate the default route by
+just passing the params hash, just passing the params hash. Finally, you
+can use the anonymous parameters. This allows you to specify the parameters
+to a named route in the order they appear in the router.
+
+
Parameters(Named Route)
+
+
name<Symbol>:
The name of the route.
+
+
+
args<Hash>:
Parameters for the route generation.
+
+
+
+
Parameters(Default Route)
+
+
args<Hash>:
Parameters for the route generation. This route will use the default route.
+
+
+
+
Parameters(Anonymous Parameters)
+
+
name<Symbol>:
The name of the route.
+
+
+
args<Array>:
An array of anonymous parameters to generate the route with. These
+parameters are assigned to the route parameters in the order that they are
+passed.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/merb_controller.rb, line 286
+ defurl(name, *args)
+ args<<params
+ name = request.routeifname==:this
+ Merb::Router.url(name, *args)
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lib/merb-core/server.rb
+
+
+
+
+ Object
+
+
+
+
+Server encapsulates the management of Merb daemons.
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (user, group=user)
+
+
+Changes privileges of the process to the specified user and group.
+
+
Parameters
+
+
user<String>:
The user to change the process to.
+
+
+
group<String>:
The group to change the process to.
+
+
+
+
Alternatives
+
+If group is left out, the user will be used as the group.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/server.rb, line 324
+ def_change_privilege(user, group=user)
+ Merb.logger.warn!"Changing privileges to #{user}:#{group}"
+
+ uid, gid = Process.euid, Process.egid
+
+ begin
+ target_uid = Etc.getpwnam(user).uid
+ rescueArgumentError =>e
+ Merb.fatal!("Failed to change to user #{user}, does the user exist?", e)
+ returnfalse
+ end
+
+ begin
+ target_gid = Etc.getgrnam(group).gid
+ rescueArgumentError =>e
+ Merb.fatal!("Failed to change to group #{group}, does the group exist?", e)
+ returnfalse
+ end
+
+ if (uid!=target_uid) || (gid!=target_gid)
+ # Change process ownership
+ Process.initgroups(user, target_gid)
+ Process::GID.change_privilege(target_gid)
+ Process::UID.change_privilege(target_uid)
+ end
+ true
+ rescueErrno::EPERM =>e
+ Merb.fatal!"Permission denied for changing user:group to #{user}:#{group}.", e
+ false
+ end
+
+
+
+
+
+ ()
+
+
+Add trap to enter IRB on SIGINT. Process exit if second SIGINT is received.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/server.rb, line 358
+ defadd_irb_trap
+ Merb.trap("INT") do
+ if@interrupted
+ Merb.logger.warn!"Interrupt received a second time, exiting!\n"
+ exit
+ end
+
+ @interrupted = true
+ Merb.logger.warn!"Interrupt a second time to quit."
+ Kernel.sleep1.5
+ ARGV.clear# Avoid passing args to IRB
+
+ if@irb.nil?
+ require"irb"
+ IRB.setup(nil)
+ @irb = IRB::Irb.new(nil)
+ IRB.conf[:MAIN_CONTEXT] = @irb.context
+ end
+
+ Merb.trap(:INT) { @irb.signal_handle }
+ catch(:IRB_EXIT) { @irb.eval_input }
+
+ Merb.logger.warn!"Exiting from IRB mode back into server mode."
+ @interrupted = false
+ add_irb_trap
+ end
+ end
+
+
+
+
+
+ (port)
+
+ Parameters
+
+ ]]>
+
+
+
+# File lib/merb-core/server.rb, line 141
+ defdaemonize(port)
+ Merb.logger.warn!"About to fork..."ifMerb::Config[:verbose]
+ forkdo
+ Process.setsid
+ exitiffork
+ Merb.logger.warn!"In #{Process.pid}"ifMerb.logger
+ File.umask0000
+ STDIN.reopen"/dev/null"
+ STDOUT.reopen"/dev/null", "a"
+ STDERR.reopenSTDOUT
+ begin
+ Dir.chdirMerb::Config[:merb_root]
+ rescueErrno::EACCES =>e
+ Merb.fatal!"You specified Merb root as #{Merb::Config[:merb_root]}, " \
+ "yet the current user does not have access to it. ", e
+ end
+ at_exit { remove_pid_file(port) }
+ Merb::Config[:port] = port
+ bootup
+ end
+ rescueNotImplementedError =>e
+ Merb.fatal!"Daemonized mode is not supported on your platform. ", e
+ end
+
+
+
+
+
+ (port, sig = "INT")
+
+ Parameters
+
The signal to send to the process, the default is 9 - SIGKILL.
+
+
+
+
+No Name Default Action Description 1 SIGHUP terminate process terminal line
+hangup 2 SIGINT terminate process interrupt program 3 SIGQUIT create core
+image quit program 4 SIGILL create core image illegal instruction 9 SIGKILL
+terminate process kill program 15 SIGTERM terminate process software
+termination signal 30 SIGUSR1 terminate process User defined signal 1 31
+SIGUSR2 terminate process User defined signal 2
+
+
Alternatives
+
+If you pass "all" as the port, the signal will be sent to all Merb processes.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/server.rb, line 88
+ defkill(port, sig = "INT")
+ ifsig.is_a?(Integer)
+ sig = Signal.list.invert[sig]
+ end
+
+ Merb::BootLoader::BuildFramework.run
+
+ # If we kill the master, then the workers should be reaped also.
+ if%w(main master all).include?(port)
+ # If a graceful exit is requested then send INT to the master process.
+ #
+ # Otherwise read pids from pid files and try to kill each process in turn.
+ kill_pid(sig, pid_file("main")) ifsig=="INT"
+ else
+ kill_pid(sig, pid_file(port))
+ end
+ end
+
+
+
+
+
+ (sig, file)
+
+
+Sends the provided signal to the process pointed at by the provided pid
+file. :api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/server.rb, line 108
+ defkill_pid(sig, file)
+ begin
+ pid = pid_in_file(file)
+ Merb.logger.fatal!"Killing pid #{pid} with #{sig}"
+ Process.kill(sig, pid)
+ FileUtils.rm(file) ifFile.exist?(file)
+ rescueErrno::EINVAL
+ Merb.logger.fatal!"Failed to kill PID #{pid} with #{sig}: '#{sig}' is an invalid " \
+ "or unsupported signal number."
+ rescueErrno::EPERM
+ Merb.logger.fatal!"Failed to kill PID #{pid} with #{sig}: Insufficient permissions."
+ rescueErrno::ESRCH
+ FileUtils.rmfile
+ Merb.logger.fatal!"Failed to kill PID #{pid} with #{sig}: Process is " \
+ "deceased or zombie."
+ rescueErrno::EACCES =>e
+ Merb.logger.fatal!e.message
+ rescueErrno::ENOENT =>e
+ # This should not cause abnormal exit, which is why
+ # we do not use Merb.fatal but instead just log with max level.
+ Merb.logger.fatal!"Could not find a PID file at #{file}. " \
+ "Most likely the process is no longer running and the pid file was not cleaned up."
+ rescueException =>e
+ if!e.is_a?(SystemExit)
+ Merb.logger.fatal!"Failed to kill PID #{pid.inspect} with #{sig.inspect}: #{e.message}"
+ end
+ end
+ end
+
+
+
+
+
+ (port)
+
+
+Gets the pid file for the specified port/socket.
+
+
Parameters
+
+
port<~to_s>:
The port/socket of the Merb process to whom the PID
+file belongs to.
+
+
+
+
Returns
+
+
String:
Location of pid file for specified port. If clustered and pid_file option is specified, it adds the port/socket
+value to the path.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/server.rb, line 290
+ defpid_file(port)
+ pidfile = Merb::Config[:pid_file] || (Merb.log_path/"merb.%s.pid")
+ pidfile%port
+ end
+
+
+
+
+
+ ()
+
+
+Gets a list of the pid files.
+
+
Returns
+
+
Array:
List of pid file paths. If not running clustered, the array contains a
+single path.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/server.rb, line 302
+ defpid_files
+ ifMerb::Config[:pid_file]
+ ifMerb::Config[:cluster]
+ Dir[Merb::Config[:pid_file] %"*"]
+ else
+ [ Merb::Config[:pid_file] ]
+ end
+ else
+ Dir[Merb.log_path/"merb.*.pid"]
+ end
+ end
+
+
+
+
+
+ (pidfile)
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/server.rb, line 66
+ defpid_in_file(pidfile)
+ File.read(pidfile).chomp.to_i
+ end
+
+
+
+
+
+ (port)
+
+
+Deletes the pidfile for the specified port/socket.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/server.rb, line 245
+ defremove_pid(port)
+ FileUtils.rm(pid_file(port)) ifFile.file?(pid_file(port))
+ end
+
+
+
+
+
+ (port)
+
+
+Removes a PID file used by the server from the filesystem. This uses :pid_file options from configuration when provided or
+merb.<port/socket>.pid in log directory by default.
+
+
Parameters
+
+
port<~to_s>:
The port of the Merb process to whom the the PID file
+belongs to.
+
+
+
+
Alternatives
+
+If Merb::Config[:pid_file] has been specified, that
+will be used instead of the port/socket based PID file.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/server.rb, line 217
+ defremove_pid_file(port)
+ pidfile = pid_file(port)
+ ifFile.exist?(pidfile)
+ Merb.logger.warn!"Removing pid file #{pidfile} (port/socket: #{port})..."
+ FileUtils.rm(pidfile)
+ end
+ end
+
+
+
+
+
+ (status = 0)
+
+
+Shut down Merb, reap any workers if necessary.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/server.rb, line 180
+ defshutdown(status = 0)
+ # reap_workers does exit but may not be called...
+ Merb::BootLoader::LoadClasses.reap_workers(status) ifMerb::Config[:fork_for_class_load]
+ # which is why we exit explicitly here
+ exit(status)
+ end
+
+
+
+
+
+ (port, cluster=nil)
+
+
+Starts a Merb server, in either foreground, daemonized
+or cluster mode.
+
+
Parameters
+
+
port<~to_i>:
The port to which the first server instance should bind to. Subsequent
+server instances bind to the immediately following ports.
+
+
+
cluster<~to_i>:
Number of servers to run in a cluster.
+
+
+
+
Alternatives
+
+If cluster is left out, then one process will be started. This process will
+be daemonized if Merb::Config[:daemonize] is true.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/server.rb, line 23
+ defstart(port, cluster=nil)
+
+ @port = port
+ @cluster = cluster
+
+ ifMerb::Config[:daemonize]
+ pidfile = pid_file(port)
+ pid = File.read(pidfile).chomp.to_iifFile.exist?(pidfile)
+
+ unlessalive?(@port)
+ remove_pid_file(@port)
+ Merb.logger.warn!"Daemonizing..."ifMerb::Config[:verbose]
+ daemonize(@port)
+ else
+ Merb.fatal!"Merb is already running on port #{port}.\n" \
+ "\e[0m \e[1;31;47mpid file: \e[34;47m#{pidfile}" \
+ "\e[1;31;47m, process id is \e[34;47m#{pid}."
+ end
+ else
+ bootup
+ end
+ end
+
+
+
+
+
+ (port = nil)
+
+
+Stores a PID file on the filesystem. This uses :pid_file options from configuration when provided or
+merb.<port/socket>.pid in log directory by default.
+
+
Parameters
+
+
port<~to_s>:
The port of the Merb process to whom the PID file
+belongs to.
+
+
+
+
Alternatives
+
+If Merb::Config[:pid_file] has been specified, that
+will be used instead of the port/socket based PID file.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/server.rb, line 262
+ defstore_details(port = nil)
+ file = pid_file(port)
+ begin
+ FileUtils.mkdir_p(File.dirname(file))
+ rescueErrno::EACCES =>e
+ Merb.fatal!"Failed to store Merb logs in #{File.dirname(file)}, " \
+ "permission denied. ", e
+ end
+ Merb.logger.warn!"Storing pid #{Process.pid} file to #{file}..."ifMerb::Config[:verbose]
+ begin
+ File.open(file, 'w'){ |f|f.write(Process.pid.to_s) }
+ rescueErrno::EACCES =>e
+ Merb.fatal!"Failed to access #{file}, permission denied.", e
+ end
+ end
+
+
+
+
+
+ (port)
+
+
+Stores a PID file on the filesystem. This uses :pid_file options from configuration when provided or
+merb.<port>.pid in log directory by default.
+
+
Parameters
+
+
port<~to_s>:
The port of the Merb process to whom the the PID file
+belongs to.
+
+
+
+
Alternatives
+
+If Merb::Config[:pid_file] has been specified, that
+will be used instead of the port/socket based PID file.
+
+Processes the return value of a deferred router block and returns the
+current route params for the current request evaluation
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/request.rb, line 126
+ def_process_block_return(retval)
+ # If the return value is an array, then it is a redirect
+ # so we must set the request as a redirect and extract
+ # the redirect params and return it as a hash so that the
+ # dispatcher can handle it
+ matched!ifretval.is_a?(Array)
+ retval
+ end
+
+
+
+
+
+ ()
+
+ Returns
+
the controller that handled the action dispatch.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/dispatcher.rb, line 52
+ defhandle
+ start = Time.now
+ Merb.logger.info"Started request handling: #{start.to_s}"
+
+ find_route!
+ returnrack_responseifhandled?
+
+ klass = controller
+ Merb.logger.debug("Routed to: #{params.inspect}")
+
+ unlessklass<Controller
+ raiseNotFound,
+ "Controller '#{klass}' not found.\n" \
+ "If Merb tries to find a controller for static files, " \
+ "you may need to check your Rackup file, see the Problems " \
+ "section at: http://wiki.merbivore.com/pages/rack-middleware"
+ end
+
+ ifklass.abstract?
+ raiseNotFound, "The '#{klass}' controller has no public actions"
+ end
+
+ controller = dispatch_action(klass, params[:action])
+ controller._benchmarks[:dispatch_time] = Time.now-start
+ Merb.logger.infocontroller._benchmarks.inspect
+ Merb.logger.flush
+ controller.rack_response
+ rescueObject =>exception
+ dispatch_exception(exception).rack_response
+ end
+
+
+
+
+
+ ()
+
+
+If @route_params is an Array, then it will be the rack response. In this
+case, the request is considered handled.
+
+
Returns
+
+
Boolean:
true if @route_params is an Array, false otherwise.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/request.rb, line 459
+ defkeep_alive
+ @env[Merb::Const::HTTP_KEEP_ALIVE]
+ end
+
+
+
+
+
+ ()
+
+
+Sets the request as matched. This will abort evaluating any further
+deferred procs.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/request.rb, line 139
+ defmatched!
+ @matched = true
+ end
+
+
+
+
+
+ ()
+
+
+Checks whether or not the request has been matched to a route.
+
+
Returns the redirect message Base64 unencoded.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/request.rb, line 303
+ defmessage
+ return {} unlessparams[:_message]
+ begin
+ Marshal.load(Merb::Parse.unescape(params[:_message]).unpack("m").first)
+ rescueArgumentError, TypeError
+ {}
+ end
+ end
+
+
+
+
+
+ ()
+
+ Returns
+
+
Symbol:
The name of the request method, e.g. :get.
+
+
+
+
Notes
+
+If the method is post, then the blocks specified in http_method_overrides
+will be checked for the masquerading method. The block will get the
+controller yielded to it. The first matching workaround wins. To disable
+this behavior, set http_method_overrides = []
+
+If the response is an Array then it is considered a direct Rack response to be sent back as a response.
+Otherwise, the route_params is a Hash with routing data
+(controller, action, et al).
+
+By using this method, a cookie key is marked for being included in the
+Set-Cookie response header.
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/cookies.rb, line 23
+ def[]=(key, value)
+ @_options_lookup[key] ||= {}
+ super
+ end
+
+
+
+
+
+ (name, options = {})
+
+
+Removes the cookie on the client machine by setting the value to an empty
+string and setting its expiration date into the past.
+
+
+In Merb, views are actually methods on controllers.
+This provides not-insignificant speed benefits, as well as preventing us
+from needing to copy over instance variables, which we think is proof that
+everything belongs in one class to begin with.
+
+
+Unfortunately, this means that view helpers need to be included into the
+<strong>Controller</strong> class. To avoid causing confusion
+when your helpers potentially conflict with our instance methods, we use an
+_ to disambiguate. As long as you don’t begin your helper methods
+with _, you only need to worry about conflicts with Merb methods that are part of the public API.
+
+
Filters
+
+before is a class method that allows you to specify
+before filters in your controllers. Filters can either be a symbol or
+string that corresponds to a method name to call, or a proc object. if it
+is a method name that method will be called and if it is a proc it will be
+called with an argument of self where self is the current controller
+object. When you use a proc as a filter it needs to take one parameter.
+
+
+after is identical, but the filters are run after
+the action is invoked.
+
+
Examples
+
+ before :some_filter
+ before :authenticate, :exclude => [:login, :signup]
+ before :has_role, :with => ["Admin"], :exclude => [:index, :show]
+ before Proc.new { some_method }, :only => :foo
+ before :authorize, :unless => :logged_in?
+
+
+You can use either :only => :actionname or :exclude =>
+[:this, :that] but not both at once. :only will only run
+before the listed actions and :exclude will run for every action
+that is not listed.
+
+
+Merb’s before filter chain is very flexible. To halt the filter chain
+you use throw :halt. If throw is called with only one
+argument of :halt the return value of the method
+filters_halted will be what is rendered to the view. You can
+override filters_halted in your own controllers to control what it
+outputs. But the throw construct is much more powerful than just
+that.
+
+
+throw :halt can also take a second argument. Here is what that
+second argument can be and the behavior each type can have:
+
+
+
String: when the second argument is a string then that string will
+be what is rendered to the browser. Since merb’s render
+method returns a string you can render a template or just use a plain
+string:
+
+
+ throw :halt, "You don't have permissions to do that!"
+ throw :halt, render(:action => :access_denied)
+
+
+
Symbol: If the second arg is a symbol, then the method named after
+that symbol will be called
+
+
+ throw :halt, :must_click_disclaimer
+
+
+
Proc: If the second arg is a Proc, it will be called and its
+return value will be what is rendered to the browser:
+
+
A list of actions that this filter should apply to
+
+
+
:exclude<Symbol, Array[Symbol]:
A list of actions that this filter should not apply to
+
+
+
:if<Symbol, Proc>:
Only apply the filter if the method named after the symbol or calling the
+proc evaluates to true
+
+
+
:unless<Symbol, Proc>:
Only apply the filter if the method named after the symbol or calling the
+proc evaluates to false
+
+
+
:with<Array[Object]>:
Arguments to be passed to the filter. Since we are talking method/proc
+calls, filter method or Proc should to have the same arity as number of
+elements in Array you pass to this option.
+
+
params[:action] and params[:controller] deprecated
+
+params[:action] and params[:controller] have been
+deprecated as of the 0.9.0 release. They are no longer set during dispatch,
+and have been replaced by action_name and controller_name respectively.
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/abstract_controller.rb, line 239
+ defself.inherited(klass)
+ _abstract_subclasses<<klass.to_s
+ helper_module_name = klass.to_s=~/^(#|Merb::)/?"#{klass}Helper":"Merb::#{klass}Helper"
+ Object.make_modulehelper_module_name
+ klass.class_eval"include Object.full_const_get(\"\#{helper_module_name}\") rescue nil\n"
+ super
+ end
+
+
+
+
+
+ (*args)
+
+
+This will initialize the controller, it is designed to be overridden in
+subclasses (like MerbController)
+
+
Parameters
+
+
*args:
The args are ignored in this class, but we need this so that subclassed
+initializes can have parameters
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/abstract_controller.rb, line 256
+ definitialize(*args)
+ @_benchmarks = {}
+ @_caught_content = {}
+ end
+
+
+
+
+
+ (filter)
+
+
+Removes a filter from the after filter chain. This removes the filter from
+the filter chain for the whole controller and does not take any options.
+
+
Parameters
+
+
filter<Symbol, String>:
A filter name to skip.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/abstract_controller.rb, line 469
+ defself.skip_after(filter)
+ skip_filter(self._after_filters, filter)
+ end
+
+
+
+
+
+ (filter)
+
+
+Removes a filter from the before filter chain. This removes the filter from
+the filter chain for the whole controller and does not take any options.
+
+
Parameters
+
+
filter<Symbol, String>:
A filter name to skip.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/abstract_controller.rb, line 481
+ defself.skip_before(filter)
+ skip_filter(self._before_filters , filter)
+ end
+
+
+
+
+
+ ()
+
+
+Returns the list of classes that have specifically subclassed AbstractController. Does not include
+all descendants.
+
+
The location to look for a template - override this method for particular
+behaviour.
+
+
+
+
Parameters
+
+
template<String>:
The absolute path to a template - without template extension.
+
+
+
type<~to_s>:
The mime-type of the template that will be rendered. Defaults to being
+called with nil.
+
+
+
+
+:api: public @overridable
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/abstract_controller.rb, line 182
+ def_absolute_template_location(template, type)
+ template
+ end
+
+
+
+
+
+ (action)
+
+
+This method exists to provide an overridable hook for ActionArgs. It uses
+send to call the action method.
+
+
Parameters
+
+
action<~to_s>:
the action method to dispatch to
+
+
+
+
+:api: plugin @overridable
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/abstract_controller.rb, line 314
+ def_call_action(action)
+ send(action)
+ end
+
+
+
+
+
+ (rule, action_name)
+
+
+Determines whether the filter should be called for the current action using
+:only and :exclude.
+
+
Parameters
+
+
rule<Hash>:
Rules for the filter (see below).
+
+
+
action_name<~to_s>:
The name of the action to be called.
+
+
+
+
Options (rule)
+
+
:only<Array>:
Optional list of actions to fire. If given, action_name must be a part of
+it for this function to return true.
+
+
+
:exclude<Array>:
Optional list of actions not to fire. If given, action_name must not be a
+part of it for this function to return true.
+
+
+
+
Returns
+
+
Boolean:
True if the action should be called.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/abstract_controller.rb, line 373
+ def_call_filter_for_action?(rule, action_name)
+ # Both:
+ # * no :only or the current action is in the :only list
+ # * no :exclude or the current action is not in the :exclude list
+ (!rule.key?(:only) ||rule[:only].include?(action_name)) &&
+ (!rule.key?(:exclude) ||!rule[:exclude].include?(action_name))
+ end
+
+
+
+
+
+ (filter_set)
+
+
+Calls a filter chain.
+
+
Parameters
+
+
filter_set<Array[Filter]>:
A set of filters in the form [[:filter, rule], [:filter, rule]]
+
+
+
+
Returns
+
+
Symbol:
:filter_chain_completed.
+
+
+
+
Notes
+
+Filter rules can be Symbols, Strings, or Procs.
+
+
+
Symbols or Strings:
Call the method represented by the Symbol or String.
+
+
+
Procs:
Execute the Proc, in the context of the controller (self will be
+the controller)
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/abstract_controller.rb, line 337
+ def_call_filters(filter_set)
+ (filter_set|| []).eachdo|filter, rule|
+ if_call_filter_for_action?(rule, action_name) &&_filter_condition_met?(rule)
+ casefilter
+ whenSymbol, String
+ ifrule.key?(:with)
+ args = rule[:with]
+ send(filter, *args)
+ else
+ send(filter)
+ end
+ whenProcthenself.instance_eval(&filter)
+ end
+ end
+ end
+ return:filter_chain_completed
+ end
+
+
+
+
+
+ (action)
+
+
+This will dispatch the request, calling internal before/after dispatch
+callbacks. If the return value of _call_filters is
+not :filter_chain_completed the action is not called, and the return from
+the filters is used instead.
+
+
Parameters
+
+
action<~to_s>:
The action to dispatch to. This will be send‘ed in _call_action.
+Defaults to :to_s.
+
+
+
+
Returns
+
+
<~to_s>:
Returns the string that was returned from the action.
+
+
+
+
Raises
+
+
ArgumentError:
Invalid result caught from before filters.
+
+
+
+
+:api: plugin
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/abstract_controller.rb, line 277
+ def_dispatch(action)
+ self.action_name = action
+ self._before_dispatch_callbacks.each { |cb|cb.call(self) }
+
+ caught = catch(:halt) do
+ start = Time.now
+ result = _call_filters(_before_filters)
+ @_benchmarks[:before_filters_time] = Time.now-startif_before_filters
+ result
+ end
+
+ @body = casecaught
+ when:filter_chain_completedthen_call_action(action_name)
+ whenStringthencaught
+ # return *something* if you throw halt with nothing
+ whennilthen"<html><body><h1>Filter Chain Halted!</h1></body></html>"
+ whenSymbolthen__send__(caught)
+ whenProcthenself.instance_eval(&caught)
+ else
+ raiseArgumentError, "Threw :halt, #{caught}. Expected String, nil, Symbol, Proc."
+ end
+ start = Time.now
+ _call_filters(_after_filters)
+ @_benchmarks[:after_filters_time] = Time.now-startif_after_filters
+
+ self._after_dispatch_callbacks.each { |cb|cb.call(self) }
+
+ @body
+ end
+
+
+
+
+
+ (condition)
+
+
+Evaluates a filter condition (:if or :unless)
+
+
Parameters
+
+
condition<Symbol, Proc>:
The condition to evaluate.
+
+
+
+
Raises
+
+
ArgumentError:
condition not a Symbol or Proc.
+
+
+
+
Returns
+
+
Boolean:
True if the condition is met.
+
+
+
+
Alternatives
+
+If condition is a symbol, it will be send’ed. If it is a Proc it will
+be called directly with self as an argument.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/abstract_controller.rb, line 419
+ def_evaluate_condition(condition)
+ casecondition
+ whenSymbol:self.send(condition)
+ whenProc:self.instance_eval(&condition)
+ else
+ raiseArgumentError,
+ 'Filter condtions need to be either a Symbol or a Proc'
+ end
+ end
+
+
+
+
+
+ (rule)
+
+
+Determines whether the filter should be run based on the conditions passed
+(:if and :unless)
+
+
Parameters
+
+
rule<Hash>:
Rules for the filter (see below).
+
+
+
+
Options (rule)
+
+
:if<Array>:
Optional conditions that must be met for the filter to fire.
+
+
+
:unless<Array>:
Optional conditions that must not be met for the filter to fire.
+
+
+
+
Returns
+
+
Boolean:
True if the conditions are met.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/abstract_controller.rb, line 395
+ def_filter_condition_met?(rule)
+ # Both:
+ # * no :if or the if condition evaluates to true
+ # * no :unless or the unless condition evaluates to false
+ (!rule.key?(:if) ||_evaluate_condition(rule[:if])) &&
+ (!rule.key?(:unless) ||!_evaluate_condition(rule[:unless]))
+ end
+
+
+
+
+
+ (context, type, controller)
+
+
+This is called after the controller is instantiated to figure out where to
+look for templates under the _template_root. Override this to define a new
+structure for your app.
+
+
Parameters
+
+
context<~to_s>:
The controller context (the action or template name).
+
+
+
type<~to_s>:
The content type. Could be nil.
+
+
+
controller<~to_s>:
The name of the controller. Defaults to being called with the
+controller_name. Set t
+
+
+
+
Returns
+
+
String:
Indicating where to look for the template for the current controller,
+context, and content-type.
+
+
+
+
Notes
+
+The type is irrelevant for controller-types that don’t support
+content-type negotiation, so we default to not include it in the
+superclass.
+
+
Examples
+
+ def _template_location
+ "#{params[:controller]}.#{params[:action]}.#{content_type}"
+ end
+
+
+This would look for templates at controller.action.mime.type instead of
+controller/action.mime.type
+
+
+:api: public @overridable
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/abstract_controller.rb, line 167
+ def_template_location(context, type, controller)
+ controller? "#{controller}/#{context}":context
+ end
+
+
+
+
+
+ (*args)
+
+
+Returns the absolute url including the passed protocol and host.
+
+
+This uses the same arguments as the url method, with added requirements of
+protocol and host options.
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/abstract_controller.rb, line 552
+ defabsolute_url(*args)
+ options = extract_options_from_args!(args) || {}
+ protocol = options.delete(:protocol)
+ host = options.delete(:host)
+
+ raiseArgumentError, "The :protocol option must be specified"unlessprotocol
+ raiseArgumentError, "The :host option must be specified"unlesshost
+
+ args<<options
+
+ protocol+"://"+host+url(*args)
+ end
+
+
+
+
+
+ (*args) {|*args| ...}
+
+
+Calls the capture method for the selected template engine.
+
+
Parameters
+
+
*args:
Arguments to pass to the block.
+
+
+
&block:
The block to call.
+
+
+
+
Returns
+
+
String:
The output of a template block or the return value of a non-template block
+converted to a string.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/abstract_controller.rb, line 609
+ defcapture(*args, &block)
+ ret = nil
+
+ captured = send("capture_#{@_engine}", *args) do|*args|
+ ret = yield*args
+ end
+
+ # return captured value only if it is not empty
+ captured.empty?? ret.to_s:captured
+ end
+
+
+
+
+
+ (str, binding)
+
+
+Calls the concatenate method for the selected template engine.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/controller/abstract_controller.rb, line 594
+ defresource(*args)
+ args<< {}
+ Merb::Router.resource(*args)
+ end
+
+
+
+
+
+ (name, *args)
+
+
+There are three possible ways to use this method. First, if you have a
+named route, you can specify the route as the first parameter as a symbol
+and any paramters in a hash. Second, you can generate the default route by
+just passing the params hash, just passing the params hash. Finally, you
+can use the anonymous parameters. This allows you to specify the parameters
+to a named route in the order they appear in the router.
+
+
Parameters(Named Route)
+
+
name<Symbol>:
The name of the route.
+
+
+
args<Hash>:
Parameters for the route generation.
+
+
+
+
Parameters(Default Route)
+
+
args<Hash>:
Parameters for the route generation. This route will use the default route.
+
+
+
+
Parameters(Anonymous Parameters)
+
+
name<Symbol>:
The name of the route.
+
+
+
args<Array>:
An array of anonymous parameters to generate the route with. These
+parameters are assigned to the route parameters in the order that they are
+passed.
+
+
Arguments to create the log from. See set_logs for specifics.
+
+
+
+ ]]>
+
+
+
+# File lib/merb-core/logger.rb, line 83
+ definitialize(*args)
+ set_log(*args)
+ end
+
+
+
+
+
+
+
+
+
+
+
+ (string = nil)
+
+
+Appends a message to the log. The methods yield to an optional block and
+the output of this block will be appended to the message.
+
+
Parameters
+
+
string<String>:
The message to be logged. Defaults to nil.
+
+
+
+
Returns
+
+
String:
The resulting message added to the log file.
+
+
+
+ ]]>
+
+
+
+# File lib/merb-core/logger.rb, line 142
+ def<<(string = nil)
+ message = ""
+ message<<delimiter
+ message<<stringifstring
+ message<<"\n"unlessmessage[-1] ==?\n
+ @buffer<<message
+ flushif@auto_flush
+
+ message
+ end
+
+
+
+
+
+ ()
+
+
+Closes and removes the current log object.
+
+ ]]>
+
+
+
+# File lib/merb-core/logger.rb, line 128
+ defclose
+ flush
+ @log.closeif@log.respond_to?(:close) &&!@log.tty?
+ @log = nil
+ end
+
+
+
+
+
+ ()
+
+
+Flush the entire buffer to the log object.
+
+ ]]>
+
+
+
+# File lib/merb-core/logger.rb, line 120
+ defflush
+ returnunless@buffer.size>0
+ @mutex.synchronizedo
+ @log.write(@buffer.slice!(0..-1).to_s)
+ end
+ end
+
+
+
+
+
+ (string = nil)
+
+
+Alias for #<<
+
+ ]]>
+
+
+
+
+
+ (stream = Merb::Config[:log_stream], log_level = Merb::Config[:log_level], delimiter = Merb::Config[:log_delimiter], auto_flush = Merb::Config[:log_auto_flush])
+
+
+Replaces an existing logger with a new one.
+
+
Parameters
+
+
log<IO, String>:
Either an IO object or a name of a logfile.
+
+
+
log_level<~to_sym>:
The log level from, e.g. :fatal or :info. Defaults to :error in the
+production environment and :debug otherwise.
+
+
+
delimiter<String>:
Delimiter to use between message sections. Defaults to " ~ ".
+
+
+
auto_flush<Boolean>:
Whether the log should automatically flush after new messages are added.
+Defaults to false.
+
+
+Then information from route is used by dispatcher to call action on the
+controller.
+
+
Routes compilation.
+
+The most interesting method of Router (and
+heart of route matching machinery) is match method generated on the fly
+from routes definitions. It is called routes compilation. Generated match
+method body contains one if/elsif statement that picks the first matching
+route definition and sets values to named parameters of the route.
+
+
+Compilation is synchronized by mutex.
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+ RW
+
+
+:api: plugin
+
+]]>
+
+
+
+
+ RW
+
+
+:api: private
+
+]]>
+
+
+
+
+ RW
+
+
+resources :users do
+
+
+ resources :comments
+
+
+end
+
+
+The show comment route will have a key of ["User",
+"Comment"]
+
+
+:api: private
+
+]]>
+
+
+
+
+ RW
+
+ Merb::Router.prepare block will defined in context of
+this behavior.
+
+
+In the previous example, all routes will have the path prefix /hello. It is
+important to note that this attribute must be set before any routes are
+defined in order for the behavior to be applied to the routes.
+
+
+:api: plugin
+
+]]>
+
+
+
+
+ RW
+
+
+:api: private
+
+]]>
+
+
+
+
+
+
+
+
+
+
+ (&block)
+
+
+Adds functionality to the router. This can be in the form of including a
+new module or directly defining new methods.
+
+
Parameters
+
+
&block<Block>:
A block of code used to extend the route builder with. This can be
+including a module or directly defining some new methods that should be
+available to building routes.
+
+
+ domain(:admin, "my-admin.com") do
+ # ... routes come here ...
+ end
+
+
+end
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router.rb, line 310
+ defextensions(&block)
+ Router::Behavior.class_eval(&block)
+ end
+
+
+
+
+
+ (first = [], last = [], &block)
+
+
+Creates a route building context and evaluates the block in it. A copy of
+root_behavior (and instance of Behavior) is copied as the context.
+
+
Parameters
+
+
first<Array>:
An array containing routes that should be prepended to the routes defined
+in the block.
+
+
+
last<Array>:
An array containing routes that should be appended to the routes defined in
+the block.
+
+
+
+
Returns
+
+
Merb::Router:
Returns self to allow chaining of methods.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router.rb, line 103
+ defprepare(first = [], last = [], &block)
+ @routes = []
+ root_behavior._with_proxy(&block)
+ @routes = first+@routes+last
+ compile
+ self
+ end
+
+
+
+
+
+ ()
+
+
+Clears the routing table. Route generation and request matching won’t
+work anymore until a new routing table is built.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router.rb, line 115
+ defreset!
+ class<<self
+ alias_method:match, :match_before_compilation
+ end
+ self.routes, self.named_routes, self.resource_routes = [], {}, {}
+ end
+
+
+
+
+
+ (*args)
+
+
+Generates a URL from the resource(s)
+
+
Parameters
+
+
resources<Symbol,Object>:
The identifiers for the resource route to generate. These can either be
+symbols or objects. Symbols denote resource collection routes and objects
+denote the members.
+
+
+
params<Hash>:
Any extra parameters needed to generate the route.
+
+
+
+
Returns
+
+
String:
The generated URL
+
+
+
+
+:api: plugin
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router.rb, line 255
+ defresource(*args)
+ defaults = args.pop
+ options = extract_options_from_args!(args) || {}
+ key = []
+ params = []
+
+ args.eachdo|arg|
+ ifarg.is_a?(Symbol) ||arg.is_a?(String)
+ key<<arg.to_s
+ else
+ key<<arg.class.to_s
+ params<<arg
+ end
+ end
+
+ unlessroute = Merb::Router.resource_routes[key]
+ raiseMerb::Router::GenerationError, "Resource route not found: #{args.inspect}"
+ end
+
+ params<<options
+
+ route.generate(params, defaults, true)
+ end
+
+
+
+
+
+ (request)
+
+
+Finds route matching URI of the request and returns a tuple of [route
+index, route params]. This method is called by the dispatcher and
+isn’t as useful in applications.
+
+
Parameters
+
+
request<Merb::Request>:
request to match.
+
+
+
+
Returns
+
+
Array[Integer, Hash]:
Two-tuple: route index and route parameters. Route parameters are
+:controller, :action and all the named segments of the route.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router.rb, line 135
+ defroute_for(request)
+ index, params = if@around_match
+ send(@around_match, request) { match(request) }
+ else
+ match(request)
+ end
+ route = routes[index] ifindex
+ if!route
+ raiseControllerExceptions::NotFound,
+ "No routes match the request: #{request.uri}"
+ end
+ [route, params]
+ end
+
+
+
+
+
+ (name, *args)
+
+
+There are three possible ways to use this method. First, if you have a
+named route, you can specify the route as the first parameter as a symbol
+and any parameters in a hash. Second, you can generate the default route by
+just passing the params hash, just passing the params hash. Finally, you
+can use the anonymous parameters. This allows you to specify the parameters
+to a named route in the order they appear in the router.
+
+
Parameters(Named Route)
+
+
name<Symbol>:
The name of the route.
+
+
+
args<Hash>:
Parameters for the route generation.
+
+
+
+
Parameters(Default Route)
+
+
args<Hash>:
Parameters for the route generation. This route will use the default route.
+
+
+
+
Parameters(Anonymous Parameters)
+
+
name<Symbol>:
The name of the route.
+
+
+
args<Array>:
An array of anonymous parameters to generate the route with. These
+parameters are assigned to the route parameters in the order that they are
+passed.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router/behavior.rb, line 664
+ def_with_proxy(&block)
+ proxy = Proxy.new
+ proxy.pushBehavior.new(proxy, @conditions, @params, @defaults, @identifiers, @options, @blocks)
+ proxy.instance_eval(&block)
+ proxy
+ end
+
+
+
+
+
+ (&block)
+
+
+Captures any new routes that have been added within the block.
+
+
+This utility method lets you track routes that have been added; it
+doesn’t affect how/which routes are added.
+
+
Parameters
+
+
&block:
A context in which routes are generated.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router/behavior.rb, line 642
+ defcapture(&block)
+ captured_routes = {}
+ name_prefix = [@options[:name_prefix]].flatten.compact.map { |p|"#{p}_"}
+ current_names = Merb::Router.named_routes.keys
+
+ behavior = Behavior.new(@proxy, @conditions, @params, @defaults, @identifiers, @options, @blocks)
+ with_behavior_context(behavior, &block)
+
+ Merb::Router.named_routes.reject { |k,v|current_names.include?(k) }.eachdo|name, route|
+ name = route.name.to_s.sub("#{name_prefix}", '').to_symunlessname_prefix.empty?
+ captured_routes[name] = route
+ end
+
+ captured_routes
+ end
+
+
+
+
+
+ (defaults = {}, &block)
+
+
+Sets default values for route parameters. If no value for the key can be
+extracted from the request, then the value provided here will be used.
+
+
Parameters
+
+
defaults<Hash>:
The default values for named segments.
+
+
+
&block:
All routes defined in the block will be scoped to the defaults defined by
+the default method.
+
+
+
+
Block parameters
+
+
r<Behavior>:
optional - The defaults behavior object.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router/behavior.rb, line 365
+ defdefault(defaults = {}, &block)
+ behavior = Behavior.new(@proxy, @conditions, @params, @defaults.merge(defaults), @identifiers, @options, @blocks)
+ with_behavior_context(behavior, &block)
+ end
+
+
+
+
+
+ (params = {}, &block)
+
+
+Creates the most common routes /:controller/:action/:id.format when called
+with no arguments. You can pass a hash or a block to add parameters or
+override the default behavior.
+
+
Parameters
+
+
params<Hash>:
This optional hash can be used to augment the default settings
+
+
+
&block:
When passing a block a new behavior is yielded and more refinement is
+possible.
+
+
+
+
Returns
+
+
Route:
the default route
+
+
+
+
Examples
+
+ # Passing an extra parameter "mode" to all matches
+ r.default_routes :mode => "default"
+
+ # specifying exceptions within a block
+ r.default_routes do |nr|
+ nr.defer_to do |request, params|
+ nr.match(:protocol => "http://").to(:controller => "login",
+ :action => "new") if request.env["REQUEST_URI"] =~ /\/private\//
+ end
+ end
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router/behavior.rb, line 515
+ defdefault_routes(params = {}, &block)
+ match("/:controller(/:action(/:id))(.:format)").to(params, &block).name(:default)
+ end
+
+
+
+
+
+ (defaults = {}, &block)
+
+
+Alias for default
+
+ ]]>
+
+
+
+
+
+ (deferred_block, &block)
+
+
+Takes a Proc as a parameter and applies it as a deferred proc for all the
+routes defined in the block. This is mostly interesting for plugin
+developers.
+
+
Examples
+
+ defered_block = proc do |r, p|
+ p.merge :controller => 'api/comments' if request.xhr?
+ end
+ defer(defered_block) do
+ resources :comments
+ end
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router/behavior.rb, line 555
+ defdefer(deferred_block, &block)
+ blocks = @blocks+ [CachedProc.new(deferred_block)]
+ behavior = Behavior.new(@proxy, @conditions, @params, @defaults, @identifiers, @options, blocks)
+ with_behavior_context(behavior, &block)
+ end
+
+
+
+
+
+ (params = {}, &block)
+
+
+Takes a block and stores it for deferred conditional routes. The block
+takes the request object and the params hash as
+parameters.
+
+
Parameters
+
+
params<Hash>:
Parameters and conditions associated with this behavior.
+
+
+
&conditional_block:
A block with the conditions to be met for the behavior to take effect.
+
+
+
+
Returns
+
+
Route :
The default route.
+
+
+
+
Examples
+
+ defer_to do |request, params|
+ params.merge :controller => 'here',
+ :action => 'there' if request.xhr?
+ end
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router/behavior.rb, line 538
+ defdefer_to(params = {}, &block)
+ defer(block).to(params)
+ end
+
+
+
+
+
+ (enable = true)
+
+
+Specifies that a route can be fixatable.
+
+
Parameters
+
+
enabled<Boolean>:
True enables fixation on the route.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router/behavior.rb, line 605
+ deffixatable(enable = true)
+ @route.fixation = enable
+ self
+ end
+
+
+
+
+
+ (name)
+
+
+Names this route in Router. Name must be a
+Symbol. The current name_prefix is ignored.
+
+
Parameters
+
+
symbol<Symbol>:
The name of the route.
+
+
+
+
Raises
+
+
ArgumentError:
symbol is not a Symbol.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router/behavior.rb, line 588
+ deffull_name(name)
+ raiseError, ":this is reserved. Please pick another name."ifname==:this
+
+ if@route
+ @route.name = name
+ self
+ else
+ register.full_name(name)
+ end
+ end
+
+
+
+
+
+ (identifiers = {}, &block)
+
+
+Sets a method for instances of specified Classes to be called before
+insertion into a route. This is useful when using models and want a
+specific method to be called on it (For example, for ActiveRecord::Base it
+would be to_param).
+
+
+The default method called on objects is to_s.
+
+
Paramters
+
+
identifiers<Hash>:
The keys are Classes and the values are the method that instances of the
+specified class should have called on.
+
+
+
&block:
All routes defined in the block will be call the specified methods during
+generation.
+
+
+
+
Block parameters
+
+
r<Behavior>:
The identify behavior object. This is optional
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router/behavior.rb, line 475
+ defidentify(identifiers = {}, &block)
+ identifiers = ifHash===identifiers
+ @identifiers.merge(identifiers)
+ else
+ { Object =>identifiers }
+ end
+
+ behavior = Behavior.new(@proxy, @conditions, @params, @defaults, identifiers.freeze, @options, @blocks)
+ with_behavior_context(behavior, &block)
+ end
+
+
+
+
+
+ (path = {}, conditions = {}, &block)
+
+
+Defines the conditions that are required to match a Request. Each condition is applied to a
+method of the Request object. Conditions can
+also be applied to segments of the path.
+
+
+If match is passed a block, it will create a new
+route scope with the conditions passed to it and yield to the block such
+that all routes that are defined in the block have the conditions applied
+to them.
+
The pattern against which Merb::Request path
+is matched.
+
+
+When path is a String, any substring that is
+wrapped in parenthesis is considered optional and any segment that begins
+with a colon, ex.: ":login", defines both a capture and a named
+param. Extra conditions can then be applied each named param individually.
+
+
+When path is a Regexp, the pattern is left untouched and the Merb::Request path is matched against it as is.
+
+
+path is optional.
+
+
+
conditions<Hash>:
Additional conditions that the request must meet in order to match. The
+keys must be the names of previously defined path segments or be methods
+that the Merb::Request instance will respond
+to. The value is the string or regexp that matched the returned value.
+Conditions are inherited by child routes.
+
+
+
&block:
All routes defined in the block will be scoped to the conditions defined by
+the match method.
+
+
+
+
Block parameters
+
+
r<Behavior>:
optional - The match behavior object.
+
+
+
+
Returns
+
+
Behavior:
A new instance of Behavior with the
+specified path and conditions.
+
+
+
+
+Tip: When nesting always make sure the most inner sub-match
+registers a Route and doesn’t just return new Behaviors.
+
+
Examples
+
+ # registers /foo/bar to controller => "foo", :action => "bar"
+ # and /foo/baz to controller => "foo", :action => "baz"
+ match("/foo") do
+ match("/bar").to(:controller => "foo", :action => "bar")
+ match("/baz").to(:controller => "foo", :action => "caz")
+ end
+
+ # Checks the format of the segments against the specified Regexp
+ match("/:string/:number", :string => /[a-z]+/, :number => /\d+/).
+ to(:controller => "string_or_numbers")
+
+ # Equivalent to the default_route
+ match("/:controller(/:action(:id))(.:format)").register
+
+ #match only if the browser string contains MSIE or Gecko
+ match("/foo", :user_agent => /(MSIE|Gecko)/ )
+ .to(:controller => 'foo', :action => 'popular')
+
+ # Route GET and POST requests to different actions (see also #resources)
+ r.match('/foo', :method => :get).to(:action => 'show')
+ r.match('/foo', :method => :post).to(:action => 'create')
+
+ # match also takes regular expressions
+
+ r.match(%r[/account/([a-z]{4,6})]).to(:controller => "account",
+ :action => "show", :id => "[1]")
+
+ r.match(%r{/?(en|es|fr|be|nl)?}).to(:language => "[1]") do
+ match("/guides/:action/:id").to(:controller => "tour_guides")
+ end
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router/behavior.rb, line 280
+ defmatch(path = {}, conditions = {}, &block)
+ path, conditions = path[:path], pathifpath.is_a?(Hash)
+
+ raiseError, "The route has already been committed. Further conditions cannot be specified"if@route
+
+ conditions.delete_if { |k, v|v.nil? }
+ conditions[:path] = merge_paths(path)
+
+ behavior = Behavior.new(@proxy, @conditions.merge(conditions), @params, @defaults, @identifiers, @options, @blocks)
+ with_behavior_context(behavior, &block)
+ end
+
+
+
+
+
+ (prefix, name = nil)
+
+
+Registers the route as a named route with the name given.
+
+
Parameters
+
+
symbol<Symbol>:
the name of the route.
+
+
+
+
Raises
+
+
ArgumentError:
symbol is not a Symbol.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router/behavior.rb, line 570
+ defname(prefix, name = nil)
+ unlessname
+ name, prefix = prefix, nil
+ end
+
+ full_name([prefix, @options[:name_prefix], name].flatten.compact.join('_'))
+ end
+
+
+
+
+
+ (name_or_path, opts = {}, &block)
+
+
+Creates a namespace for a route. This way you can have logical separation
+to your routes.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router/behavior.rb, line 317
+ defto(params = {}, &block)
+ raiseError, "The route has already been committed. Further params cannot be specified"if@route
+
+ behavior = Behavior.new(@proxy, @conditions, @params.merge(params), @defaults, @identifiers, @options, @blocks)
+
+ ifblock_given?
+ with_behavior_context(behavior, &block)
+ else
+ behavior.to_route
+ end
+ end
+
+
+
+
+
+ (params = {}, &block)
+
+
+Alias for to
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+ ()
+
+
+Returns the current route.
+
+
Returns
+
+
Route:
the route.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router/behavior.rb, line 679
+ def_route
+ @route
+ end
+
+
+
+
+
+ (route, &block)
+
+
+Allows to insert the route at a certain spot in the list of routes instead
+of appending to the list.
+
+
Parameters
+
+
route<Route>:
the route to insert before.
+
+
+
&block:
the route definition to insert.
+
+
+
+
+:api: plugin
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router/behavior.rb, line 728
+ defbefore(route, &block)
+ options(:before =>route, &block)
+ end
+
+
+
+
+
+ ()
+
+
+Turns a route definition into a Route object.
+
+
Returns
+
+
Route:
the route generated.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router/behavior.rb, line 689
+ defto_route
+ raiseError, "The route has already been committed."if@route
+
+ controller = @params[:controller]
+
+ ifprefixes = @options[:controller_prefix]
+ controller||=":controller"
+
+ prefixes.reverse_eachdo|prefix|
+ breakifcontroller=~%r{^/(.*)}&&controller = $1
+ controller = "#{prefix}/#{controller}"
+ end
+ end
+
+ @params.merge!(:controller =>controller.to_s.gsub(%r{^/}, '')) ifcontroller
+
+ # Sorts the identifiers so that modules that are at the bottom of the
+ # inheritance chain come first (more specific modules first). Object
+ # should always be last.
+ identifiers = @identifiers.sort { |(first,_),(sec,_)|first<=>sec||1 }
+
+ @route = Route.new(@conditions.dup,@params, @blocks, :defaults =>@defaults.dup, :identifiers =>identifiers)
+
+ ifbefore = @options[:before] &&@options[:before].last
+ @route.register_at(Router.routes.index(before))
+ else
+ @route.register
+ end
+ self
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lib/merb-core/dispatch/router/behavior.rb
+
+
+
+
+ Object
+
+
+
+
+Proxy catches any methods and
+proxies them to the current behavior. This allows building routes without
+constantly having to catching the yielded behavior object
+
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router/behavior.rb, line 139
+ defredirect(url, opts = {})
+ Merb::Rack::Helpers.redirect(url, opts)
+ end
+
+
+
+
+
+ (*args)
+
+
+Tests whether the top-most behavior responds to the arguments.
+
+
Notes
+
+Behaviors contain the actual functionality of the proxy.
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router/behavior.rb, line 51
+ defrespond_to?(*args)
+ super||@behaviors.last.respond_to?(*args)
+ end
+
+
+
+
+
+ (name, *args)
+
+
+There are three possible ways to use this method. First, if you have a
+named route, you can specify the route as the first parameter as a symbol
+and any parameters in a hash. Second, you can generate the default route by
+just passing the params hash, just passing the params hash. Finally, you
+can use the anonymous parameters. This allows you to specify the parameters
+to a named route in the order they appear in the router.
+
+
Parameters(Named Route)
+
+
name<Symbol>:
The name of the route.
+
+
+
args<Hash>:
Parameters for the route generation.
+
+
+
+
Parameters(Default Route)
+
+
args<Hash>:
Parameters for the route generation. This route will use the default route.
+
+
+
+
Parameters(Anonymous Parameters)
+
+
name<Symbol>:
The name of the route.
+
+
+
args<Array>:
An array of anonymous parameters to generate the route with. These
+parameters are assigned to the route parameters in the order that they are
+passed.
+
+
The CachedProc object in a format
+embeddable within a string.
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/dispatch/router/cached_proc.rb, line 25
+ defto_s
+ "CachedProc[#{@index}].cache"
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lib/merb-core/dispatch/router.rb
+
+
+
+
+ StandardError
+
+
+
+
+Raised when parameters given to generation method do not match route
+parameters.
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lib/merb-core/dispatch/router/route.rb
+
+
+
+
+ Object
+
+
+
+
+This entire class is private and should never be accessed outside of Merb::Router and Behavior
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lib/merb-core/dispatch/router/route.rb
+
+
+
+
+ Object
+
+
+
+
+The Generator class handles compiling the route down to a lambda that can
+generate the URL from a params hash and a default params hash.
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lib/merb-core/bootloader.rb
+
+
+
+
+ Object
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (klass)
+
+
+Execute this boot loader after the specified boot loader.
+
+
Parameters
+
+
klass<~to_s>:
The boot loader class after which this boot loader should be run.
+
+
+
+
Returns
+
+nil
+
+
+:api: plugin
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 42
+ defafter(klass)
+ move_klass(klass, 1)
+ nil
+ end
+
+
+
+
+
+ (&block)
+
+
+Execute a block of code after the app loads.
+
+
Parameters
+
+
&block:
A block to be added to the callbacks that will be executed after the app
+loads.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 157
+ defafter_app_loads(&block)
+ after_load_callbacks<<block
+ end
+
+
+
+
+
+ (klass)
+
+
+Execute this boot loader before the specified boot loader.
+
+
Parameters
+
+
klass<~to_s>:
The boot loader class before which this boot loader should be run.
+
+
+
+
Returns
+
+nil
+
+
+:api: plugin
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 57
+ defbefore(klass)
+ move_klass(klass, 0)
+ nil
+ end
+
+
+
+
+
+ (&block)
+
+
+Execute a block of code before the app loads but after dependencies load.
+
+
Parameters
+
+
&block:
A block to be added to the callbacks that will be executed before the app
+loads.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 169
+ defbefore_app_loads(&block)
+ before_load_callbacks<<block
+ end
+
+
+
+
+
+ (&block)
+
+
+Execute a block of code before master process is shut down. Only makes
+sense on platforms where Merb server can use forking.
+
+
Parameters
+
+
&block:
A block to be added to the callbacks that will be executed before master
+process is shut down.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 182
+ defbefore_master_shutdown(&block)
+ before_master_shutdown_callbacks<<block
+ end
+
+
+
+
+
+ (&block)
+
+
+Execute a block of code before worker process is shut down. Only makes
+sense on platforms where Merb server can use forking.
+
+
Parameters
+
+
&block:
A block to be added to the callbacks that will be executed before worker
+process is shut down.
+
+
+
+
+:api: public
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 195
+ defbefore_worker_shutdown(&block)
+ before_worker_shutdown_callbacks<<block
+ end
+
+
+
+
+
+ ()
+
+
+Set up the default framework
+
+
Returns
+
+nil
+
+
+:api: plugin @overridable
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 129
+ defdefault_framework
+ %w[view model helper controller mailer part].eachdo|component|
+ Merb.push_path(component.to_sym, Merb.root_path("app/#{component}s"))
+ end
+ Merb.push_path(:application, Merb.root_path("app"/"controllers"/"application.rb"))
+ Merb.push_path(:config, Merb.root_path("config"), nil)
+ Merb.push_path(:router, Merb.dir_for(:config), (Merb::Config[:router_file] ||"router.rb"))
+ # IMPORTANT! Enabling autoload here for lib breaks most of Rake tasks
+ # in Merb repository. If you want to enable autoload by default,
+ # do it in the generated init.rb file: Merb.push_path(Merb.root_path("lib"), "*/*.rb")
+ Merb.push_path(:lib, Merb.root_path("lib"), nil)
+ Merb.push_path(:merb_session, Merb.root_path("merb"/"session"))
+ Merb.push_path(:log, Merb.log_path, nil)
+ Merb.push_path(:public, Merb.root_path("public"), nil)
+ Merb.push_path(:stylesheet, Merb.dir_for(:public) /"stylesheets", nil)
+ Merb.push_path(:javascript, Merb.dir_for(:public) /"javascripts", nil)
+ Merb.push_path(:image, Merb.dir_for(:public) /"images", nil)
+ nil
+ end
+
+
+
+
+
+ (bootloader)
+
+
+Determines whether or not a specific bootloader has finished yet.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 118
+ deffinished?(bootloader)
+ self.finished.include?(bootloader.to_s)
+ end
+
+
+
+
+
+ (klass)
+
+
+Adds the inheriting class to the list of subclasses in a position specified
+by the before and after methods.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 27
+ definherited(klass)
+ subclasses<<klass.to_s
+ super
+ end
+
+
+
+
+
+ (klass, where)
+
+
+Move a class that is inside the bootloader to some place in the Array,
+relative to another class.
+
+
Parameters
+
+
klass<~to_s>:
The klass to move the bootloader relative to
+
+
+
where<Integer>:
0 means insert it before; 1 means insert it after
+
+
+
+
Returns
+
+nil
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 75
+ defmove_klass(klass, where)
+ index = Merb::BootLoader.subclasses.index(klass.to_s)
+ ifindex
+ Merb::BootLoader.subclasses.delete(self.to_s)
+ Merb::BootLoader.subclasses.insert(index+where, self.to_s)
+ end
+ nil
+ end
+
+
+
+
+
+ ()
+
+
+Runs all boot loader classes by calling their run methods.
+
+
+This is used in conjunction with Merb::BootLoader::ReloadClasses
+to track files that need to be reloaded, and which constants need to be
+removed in order to reload a file.
+
+
+This also adds the model, controller, and lib directories to the load path,
+so they can be required in order to avoid load-order issues.
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+ {}
+
+
+
+
+
+
+ {}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ()
+
+
+Wait for any children to exit, remove the "main" PID, and exit.
+
+
Returns
+
+(Does not return.)
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 655
+ defexit_gracefully
+ # wait all workers to exit
+ Process.waitall
+ # remove master process pid
+ Merb::Server.remove_pid("main")
+ # terminate, workers remove their own pids
+ # in on exit hook
+
+ Merb::BootLoader.before_master_shutdown_callbacks.eachdo|cb|
+ begin
+ cb.call
+ rescueException =>e
+ Merb.logger.fatal"before_master_shutdown callback crashed: #{e.message}"
+ end
+ end
+ exit
+ end
+
+
+
+
+
+ (*paths)
+
+
+Loads classes from given paths - using path/glob pattern.
+
+
Parameters
+
+
*paths<Array>:
Array of paths to load classes from - may contain glob pattern
+
+
+
+
Returns
+
+nil
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 872
+ defload_classes(*paths)
+ orphaned_classes = []
+ paths.flatten.eachdo|path|
+ Dir[path].eachdo|file|
+ begin
+ load_filefile
+ rescueNameError =>ne
+ orphaned_classes.unshift(file)
+ end
+ end
+ end
+ load_classes_with_requirements(orphaned_classes)
+ end
+
+
+
+
+
+ (file)
+
+
+Loads a file, tracking its modified time and, if necessary, the classes it
+declared.
+
+
Parameters
+
+
file<String>:
The file to load.
+
+
+
+
Returns
+
+nil
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 836
+ defload_file(file)
+ # Don't do this expensive operation unless we need to
+ unlessMerb::Config[:fork_for_class_load]
+ klasses = ObjectSpace.classes.dup
+ end
+
+ # Ignore the file for syntax errors. The next time
+ # the file is changed, it'll be reloaded again
+ begin
+ requirefile
+ rescueSyntaxError =>e
+ Merb.logger.error"Cannot load #{file} because of syntax error: #{e.message}"
+ ensure
+ ifMerb::Config[:reload_classes]
+ MTIMES[file] = File.mtime(file)
+ end
+ end
+
+ # Don't do this expensive operation unless we need to
+ unlessMerb::Config[:fork_for_class_load]
+ LOADED_CLASSES[file] = ObjectSpace.classes-klasses
+ end
+
+ nil
+ end
+
+
+
+
+
+ (status = 0, sig = reap_workers_signal)
+
+
+Reap any workers of the spawner process and exit with an appropriate status
+code.
+
+
+Note that exiting the spawner process with a status code of 128 when a
+master process exists will cause the spawner process to be recreated, and
+the app code reloaded.
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 794
+ defreap_workers(status = 0, sig = reap_workers_signal)
+ Merb.logger.info"Executed all before worker shutdown callbacks..."
+ Merb::BootLoader.before_worker_shutdown_callbacks.eachdo|cb|
+ begin
+ cb.call
+ rescueException =>e
+ Merb.logger.fatal"before worker shutdown callback crashed: #{e.message}"
+ end
+
+ end
+
+ Merb.exiting = trueunlessstatus==128
+
+ begin
+ @writer.puts(status.to_s) if@writer
+ rescueSystemCallError
+ end
+
+ threads = []
+
+ ($WORKERS|| []).eachdo|p|
+ threads<<Thread.newdo
+ begin
+ Process.kill(sig, p)
+ Process.wait2(p)
+ rescueSystemCallError
+ end
+ end
+ end
+ threads.each {|t|t.join }
+ exit(status)
+ end
+
+
+
+
+
+ ()
+
+
+
+# File lib/merb-core/bootloader.rb, line 775
+ defreap_workers_signal
+ Merb::Config[:reap_workers_quickly] ?"KILL":"ABRT"
+ end
+
+
+
+
+
+ (file)
+
+
+Reloads the classes in the specified file. If fork-based loading is used,
+this causes the current processes to be killed and all classes to be
+reloaded. If class-based loading is not in use, the classes declared in
+that file are removed and the file is reloaded.
+
+
Parameters
+
+
file<String>:
The file to reload.
+
+
+
+
Returns
+
+When fork-based loading is used:
+
+
+ (Does not return.)
+
+
+When fork-based loading is not in use:
+
+
+ nil
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 901
+ defreload(file)
+ ifMerb::Config[:fork_for_class_load]
+ reap_workers(128)
+ else
+ remove_classes_in_file(file) { |f|load_file(f) }
+ end
+ end
+
+
+
+
+
+ (file) {|file if block_given?| ...}
+
+
+Removes all classes declared in the specified file. Any hashes which use
+classes as keys will be protected provided they have been added to
+Merb.klass_hashes. These hashes have their keys substituted with
+placeholders before the file’s classes are unloaded. If a block is
+provided, it is called before the substituted keys are reconstituted.
+
+
Parameters
+
+
file<String>:
The file to remove classes for.
+
+
+
&block:
A block to call with the file that has been removed before klass_hashes are
+updated
+
+
+
+
+to use the current values of the constants they used as keys.
+
+Additionally, removes the specified class from the subclass list of every
+superclass that tracks it’s subclasses in an array returned by
+_subclasses_list. Classes that wish to use this functionality are required
+to alias the reader for their list of subclasses to _subclasses_list. Plugins for ORMs and other libraries should keep
+this in mind.
+
+
Parameters
+
+
const<Class>:
The class to remove.
+
+
+
+
Returns
+
+nil
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 947
+ defremove_constant(const)
+ # This is to support superclasses (like AbstractController) that track
+ # their subclasses in a class variable.
+ superklass = const
+ until (superklass = superklass.superclass).nil?
+ ifsuperklass.respond_to?(:_subclasses_list)
+ superklass.send(:_subclasses_list).delete(klass)
+ superklass.send(:_subclasses_list).delete(klass.to_s)
+ end
+ end
+
+ parts = const.to_s.split("::")
+ base = parts.size==1?Object:Object.full_const_get(parts[0..-2].join("::"))
+ object = parts[-1].to_s
+ begin
+ base.send(:remove_const, object)
+ Merb.logger.debug("Removed constant #{object} from #{base}")
+ rescueNameError
+ Merb.logger.debug("Failed to remove constant #{object} from #{base}")
+ end
+ nil
+ end
+
+
+
+
+
+ ()
+
+
+Load all classes from Merb’s native load paths.
+
+
+If fork-based loading is used, every time classes are loaded this will
+return in a new spawner process and boot loading will continue from this
+point in the boot loading process.
+
+
+If fork-based loading is not in use, this only returns once and does not
+fork a new process.
+
+
Returns
+
+Returns at least once:
+
+
+ nil
+
+
+:api: plugin
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 615
+ defrun
+ # process name you see in ps output
+ $0 = "merb#{" : " + Merb::Config[:name] if Merb::Config[:name]} : master"
+
+ # Log the process configuration user defined signal 1 (SIGUSR1) is received.
+ Merb.trap("USR1") do
+ require"yaml"
+ Merb.logger.fatal!"Configuration:\n#{Merb::Config.to_hash.merge(:pid => $$).to_yaml}\n\n"
+ end
+
+ ifMerb::Config[:fork_for_class_load] &&!Merb.testing?
+ start_transaction
+ else
+ Merb.trap('INT') do
+ Merb.logger.warn!"Reaping Workers"
+ reap_workers
+ end
+ end
+
+ # Load application file if it exists - for flat applications
+ load_fileMerb.dir_for(:application) ifFile.file?(Merb.dir_for(:application))
+
+ # Load classes and their requirements
+ Merb.load_paths.eachdo|component, path|
+ nextifpath.last.blank?||component==:application||component==:router
+ load_classes(path.first/path.last)
+ end
+
+ Merb::Controller.send:include, Merb::GlobalHelpers
+
+ nil
+ end
+
+
+
+
+
+ ()
+
+
+Set up the BEGIN point for fork-based loading and sets up any signals in
+the parent and child. This is done by forking the app. The child process
+continues on to run the app. The parent process waits for the child process
+to finish and either forks again
+
+
Returns
+
+Parent Process:
+
+
+ (Does not return.)
+
+
+Child Process returns at least once:
+
+
+ nil
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 686
+ defstart_transaction
+ Merb.logger.warn!"Parent pid: #{Process.pid}"
+ reader, writer = nil, nil
+
+ ifGC.respond_to?(:copy_on_write_friendly=)
+ GC.copy_on_write_friendly = true
+ end
+
+ loopdo
+ # create two connected endpoints
+ # we use them for master/workers communication
+ reader, @writer = IO.pipe
+ pid = Kernel.fork
+
+ # pid means we're in the parent; only stay in the loop if that is case
+ breakunlesspid
+ # writer must be closed so reader can generate EOF condition
+ @writer.close
+
+ # master process stores pid to merb.main.pid
+ Merb::Server.store_pid("main")
+
+ ifMerb::Config[:console_trap]
+ Merb.trap("INT") {}
+ else
+ # send ABRT to worker on INT
+ Merb.trap("INT") do
+ Merb.logger.warn!"Reaping Workers"
+ begin
+ Process.kill(reap_workers_signal, pid)
+ rescueSystemCallError
+ end
+ exit_gracefully
+ end
+ end
+
+ Merb.trap("HUP") do
+ Merb.logger.warn!"Doing a fast deploy\n"
+ Process.kill("HUP", pid)
+ end
+
+ reader_ary = [reader]
+ loopdo
+ # wait for worker to exit and capture exit status
+ #
+ #
+ # WNOHANG specifies that wait2 exists without waiting
+ # if no worker processes are ready to be noticed.
+ ifexit_status = Process.wait2(pid, Process::WNOHANG)
+ # wait2 returns a 2-tuple of process id and exit
+ # status.
+ #
+ # We do not care about specific pid here.
+ exit_status[1] &&exit_status[1].exitstatus==128?break:exit
+ end
+ # wait for data to become available, timeout in 0.25 of a second
+ ifselect(reader_ary, nil, nil, 0.25)
+ begin
+ # no open writers
+ nextifreader.eof?
+ msg = reader.readline
+ ifmsg=~/128/
+ Process.detach(pid)
+ break
+ else
+ exit_gracefully
+ end
+ rescueSystemCallError
+ exit_gracefully
+ end
+ end
+ end
+ end
+
+ reader.close
+
+ # add traps to the worker
+ ifMerb::Config[:console_trap]
+ Merb::Server.add_irb_trap
+ at_exit { reap_workers }
+ else
+ Merb.trap('INT') do
+ Merb::BootLoader.before_worker_shutdown_callbacks.each { |cb|cb.call }
+ end
+ Merb.trap('ABRT') { reap_workers }
+ Merb.trap('HUP') { reap_workers(128, "ABRT") }
+ end
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lib/merb-core/bootloader.rb
+
+
+
+
+ Merb::BootLoader
+
+
+
+
+Setup some useful defaults
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ()
+
+
+Sets up the defaults
+
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 418
+ defself.enable_json_gem
+ gem"json"
+ require"json/ext"
+ rescueLoadError
+ gem"json_pure"
+ require"json/pure"
+ end
+
+
+
+
+
+ ()
+
+
+Load each dependency that has been declared so far.
+
+
Returns
+
+nil
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 407
+ defself.load_dependencies
+ dependencies.each { |dependency|Kernel.load_dependency(dependency) }
+ nil
+ end
+
+
+
+
+
+ ()
+
+
+Load the init_file specified in Merb::Config or
+if not specified, the init.rb file from the Merb
+configuration directory, and any environment files, which register the list
+of necessary dependencies and any after_app_loads hooks.
+
+
+Dependencies can hook into
+the bootloader process itself by using before or after insertion methods.
+Since these are loaded from this bootloader (Dependencies), they can only
+adapt the bootloaders that haven’t been loaded up until this point.
+
+
Returns
+
+nil
+
+
+:api: plugin
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 385
+ defself.run
+ set_encoding
+ # this is crucial: load init file with all the preferences
+ # then environment init file, then start enabling specific
+ # components, load dependencies and update logger.
+ unlessMerb::disabled?(:initfile)
+ load_initfile
+ load_env_config
+ end
+ expand_ruby_path
+ enable_json_gemunlessMerb::disabled?(:json)
+ load_dependencies
+ update_logger
+ nil
+ end
+
+
+
+
+
+ ()
+
+
+Default encoding to UTF8 if it has not already been set to something else.
+
+
Returns
+
+nil
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 455
+ defself.set_encoding
+ $KCODE = 'UTF8'if$KCODE=='NONE'||$KCODE.blank?
+ nil
+ end
+
+
+
+
+
+ ()
+
+
+Resets the logger and sets the log_stream to Merb::Config[:log_file] if one
+is specified, falling back to STDOUT.
+
+
Returns
+
+nil
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 433
+ defself.update_logger
+ Merb.reset_logger!
+
+ # If log file is given, use it and not log stream we have.
+ ifMerb::Config[:log_file]
+ raise"log file should be a string, got: #{Merb::Config[:log_file].inspect}"unlessMerb::Config[:log_file].is_a?(String)
+ STDOUT.puts"Logging to file at #{Merb::Config[:log_file]}"unlessMerb.testing?
+ Merb::Config[:log_stream] = File.open(Merb::Config[:log_file], "w+")
+ # but if it's not given, fallback to log stream or stdout
+ else
+ Merb::Config[:log_stream] ||=STDOUT
+ end
+
+ nil
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lib/merb-core/bootloader.rb
+
+
+
+
+ Merb::BootLoader
+
+
+
+
+Precompiles all non-partial templates.
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ()
+
+
+Loads all non-partial templates into the Merb::InlineTemplates module.
+
+
Returns
+
+
Array[String]:
The list of template files which were loaded.
+
+
+
+
+:api: plugin
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 1072
+ defrun
+ template_paths.eachdo|path|
+ Merb::Template.inline_template(File.open(path))
+ end
+ end
+
+
+
+
+
+ ()
+
+
+Finds a list of templates to load.
+
+
Returns
+
+
Array[String]:
All found template files whose basename does not begin with "_".
+
+
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 1084
+ deftemplate_paths
+ extension_glob = "{#{Merb::Template.template_extensions.join(',')}}"
+
+ # This gets all templates set in the controllers template roots
+ # We separate the two maps because most of controllers will have
+ # the same _template_root, so it's silly to be globbing the same
+ # path over and over.
+ controller_view_paths = []
+ Merb::AbstractController._abstract_subclasses.eachdo|klass|
+ nextif (const = Object.full_const_get(klass))._template_root.blank?
+ controller_view_paths+=const._template_roots.map { |pair|pair.first }
+ end
+ template_paths = controller_view_paths.uniq.compact.map { |path|Dir["#{path}/**/*.#{extension_glob}"] }
+
+ # This gets the templates that might be created outside controllers
+ # template roots. eg app/views/shared/*
+ template_paths<<Dir["#{Merb.dir_for(:view)}/**/*.#{extension_glob}"] ifMerb.dir_for(:view)
+
+ # This ignores templates for partials, which need to be compiled at use time to generate
+ # a preamble that assigns local variables
+ template_paths.flatten.compact.uniq.grep(%r{^.*/[^_][^/]*$})
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lib/merb-core/bootloader.rb
+
+
+
+
+ Merb::BootLoader
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ()
+
+
+Mixin the session functionality; this is done before BeforeAppLoads so that SessionContainer and SessionStoreContainer can be
+subclassed by plugin session stores for example - these need to be loaded
+in a before_app_loads block or a BootLoader
+that runs after MixinSession.
+
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 582
+ defself.run
+ Merb::BootLoader.before_load_callbacks.each { |x|x.call }
+ nil
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lib/merb-core/bootloader.rb
+
+
+
+
+ Merb::BootLoader
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (paths)
+
+
+Reloads all files which have been modified since they were last loaded.
+
+
Returns
+
+nil
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 1350
+ defself.reload(paths)
+ paths.eachdo|file|
+ nextifLoadClasses::MTIMES[file] &&
+ LoadClasses::MTIMES[file] ==File.mtime(file)
+
+ LoadClasses.reload(file)
+ end
+
+ nil
+ end
+
+
+
+
+
+ ()
+
+
+Set up the class reloader if class reloading is enabled. This checks
+periodically for modifications to files loaded by the LoadClassesBootLoader and reloads them when they are
+modified.
+
+
+To override the default, set Merb::Config[:framework] in your
+initialization file. Merb::Config[:framework] takes a Hash whose key is the name of the path, and whose values
+can be passed into Merb.push_path (see Merb.push_path for full details).
+
+
Notes
+
+All paths will default to Merb.root, so you can get a flat-file structure
+by doing Merb::Config[:framework] = {}.
+
+That will set up a flat directory structure with the config files and
+controller files under Merb.root, but with models, views, and lib with
+their own folders off of Merb.root.
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ()
+
+
+Sets up merb paths to support the app’s file layout. First,
+config/framework.rb is checked, next we look for Merb.root/framework.rb,
+finally we use the default merb layout (Merb::BootLoader.default_framework)
+
+
+This method can be overridden to support other application layouts.
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ()
+
+
+Print a warning if the installed version of rubygems is not supported
+
+
Returns
+
+nil
+
+
+:api: private
+
+ ]]>
+
+
+
+# File lib/merb-core/bootloader.rb, line 239
+ defself.print_warnings
+ ifGem::Version.new(Gem::RubyGemsVersion) <Gem::Version.new("1.1")
+ Merb.fatal!"Merb requires Rubygems 1.1 and later. " \
+ "Please upgrade RubyGems with gem update --system."
+ end
+ end
+
+
+
+
+
+ ()
+
+
+Sets Merb.logger to a new logger created based on the config settings.
+
+
+Set it up by adding the following to your init file:
+
+
+ Merb::Config.use do |c|
+ c[:session_store] = :memory
+ c[:memory_session_ttl] = 3600 # in seconds, one hour
+ end
+
+
+Sessions will remain in memory until the server is stopped or the time as
+set in :memory_session_ttl expires. Expired sessions are cleaned up in the
+background by a separate thread. Every time reaper cleans up expired
+sessions, garbage collection is scheduled start.
+
+
+Memory session is accessed in a thread safe manner.
+
+which was based on HpricotTestHelper Author: Luke Redpath Email: contact
+@nospam@ lukeredpath.co.uk Web: www.lukeredpath.co.uk /
+opensource.agileevolved.com
+
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (value)
+
+
+
+# File lib/merb-core/test/test_ext/hpricot.rb, line 13
+ defcontain?(value)
+ self.inner_text.include?(value)
+ end
+
+
+
+
+
+ (value)
+
+
+Alias for contain?
+
+ ]]>
+
+
+
+
+
+ ()
+
+
+courtesy of ‘thomas’ from the comments of _whys blog - get in
+touch if you want a better credit!
+
+ ]]>
+
+
+
+# File lib/merb-core/test/test_ext/hpricot.rb, line 27
+ definner_text
+ self.children.collectdo|child|
+ child.is_a?(Hpricot::Text) ?child.content: ((child.respond_to?("inner_text") &&child.inner_text) ||"")
+ end.join.strip
+ end
+
+
+
+
+
+ (regex)
+
+
+
+# File lib/merb-core/test/test_ext/hpricot.rb, line 19
+ defmatch?(regex)
+ self.inner_text.match(regex)
+ end
+
+
+
+
+
+ (regex)
+
+
+Alias for match?
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lib/merb-core/tasks/gem_management.rb
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (*messages)
+
+
+red
+
+ ]]>
+
+
+
+# File lib/merb-core/tasks/gem_management.rb, line 6
+ deferror(*messages)
+ putsmessages.map { |msg|"\033[1;31m#{msg}\033[0m" }
+ end
+
+
+
+
+
+ (*messages)
+
+
+blue
+
+ ]]>
+
+
+
+# File lib/merb-core/tasks/gem_management.rb, line 28
+ definfo(*messages)
+ putsmessages.map { |msg|"\033[1;34m#{msg}\033[0m" }
+ end
+
+
+
+
+
+ (*messages)
+
+
+Alias for success
+
+ ]]>
+
+
+
+
+
+ (*messages)
+
+
+magenta
+
+ ]]>
+
+
+
+# File lib/merb-core/tasks/gem_management.rb, line 23
+ defnote(*messages)
+ putsmessages.map { |msg|"\033[1;35m#{msg}\033[0m" }
+ end
+
+
+
+
+
+ (*messages)
+
+
+green
+
+ ]]>
+
+
+
+# File lib/merb-core/tasks/gem_management.rb, line 16
+ defsuccess(*messages)
+ putsmessages.map { |msg|"\033[1;32m#{msg}\033[0m" }
+ end
+
+
+
+
+
+ (*messages)
+
+
+yellow
+
+ ]]>
+
+
+
+# File lib/merb-core/tasks/gem_management.rb, line 11
+ defwarning(*messages)
+ putsmessages.map { |msg|"\033[1;33m#{msg}\033[0m" }
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/config/environments/development.rb b/config/environments/development.rb
new file mode 100644
index 0000000..d6d4ab3
--- /dev/null
+++ b/config/environments/development.rb
@@ -0,0 +1,15 @@
+Merb.logger.info("Loaded DEVELOPMENT Environment...")
+Merb::Config.use { |c|
+ c[:exception_details] = true
+ c[:reload_templates] = true
+ c[:reload_classes] = true
+ c[:reload_time] = 0.5
+ c[:ignore_tampered_cookies] = true
+ c[:log_auto_flush ] = true
+ c[:log_level] = :debug
+
+ c[:log_stream] = STDOUT
+ c[:log_file] = nil
+ # Or redirect logging into a file:
+ # c[:log_file] = Merb.root / "log" / "development.log"
+}
diff --git a/config/environments/production.rb b/config/environments/production.rb
new file mode 100644
index 0000000..17a2d4b
--- /dev/null
+++ b/config/environments/production.rb
@@ -0,0 +1,10 @@
+Merb.logger.info("Loaded PRODUCTION Environment...")
+Merb::Config.use { |c|
+ c[:exception_details] = false
+ c[:reload_classes] = false
+ c[:log_level] = :error
+
+ c[:log_file] = Merb.root / "log" / "production.log"
+ # or redirect logger using IO handle
+ # c[:log_stream] = STDOUT
+}
diff --git a/config/environments/rake.rb b/config/environments/rake.rb
new file mode 100644
index 0000000..5e4b9a7
--- /dev/null
+++ b/config/environments/rake.rb
@@ -0,0 +1,11 @@
+Merb.logger.info("Loaded RAKE Environment...")
+Merb::Config.use { |c|
+ c[:exception_details] = true
+ c[:reload_classes] = false
+ c[:log_auto_flush ] = true
+
+ c[:log_stream] = STDOUT
+ c[:log_file] = nil
+ # Or redirect logging into a file:
+ # c[:log_file] = Merb.root / "log" / "development.log"
+}
diff --git a/config/environments/staging.rb b/config/environments/staging.rb
new file mode 100644
index 0000000..f5b5058
--- /dev/null
+++ b/config/environments/staging.rb
@@ -0,0 +1,10 @@
+Merb.logger.info("Loaded STAGING Environment...")
+Merb::Config.use { |c|
+ c[:exception_details] = false
+ c[:reload_classes] = false
+ c[:log_level] = :error
+
+ c[:log_file] = Merb.root / "log" / "staging.log"
+ # or redirect logger using IO handle
+ # c[:log_stream] = STDOUT
+}
diff --git a/config/environments/test.rb b/config/environments/test.rb
new file mode 100644
index 0000000..671ec76
--- /dev/null
+++ b/config/environments/test.rb
@@ -0,0 +1,12 @@
+Merb.logger.info("Loaded TEST Environment...")
+Merb::Config.use { |c|
+ c[:testing] = true
+ c[:exception_details] = true
+ c[:log_auto_flush ] = true
+ # log less in testing environment
+ c[:log_level] = :error
+
+ #c[:log_file] = Merb.root / "log" / "test.log"
+ # or redirect logger using IO handle
+ c[:log_stream] = STDOUT
+}
diff --git a/config/init.rb b/config/init.rb
new file mode 100644
index 0000000..aa09acf
--- /dev/null
+++ b/config/init.rb
@@ -0,0 +1,27 @@
+# Go to http://wiki.merbivore.com/pages/init-rb
+
+require 'config/dependencies.rb'
+
+use_test :rspec
+use_template_engine :haml
+
+Merb::Config.use do |c|
+ c[:use_mutex] = false
+ c[:session_store] = 'cookie' # can also be 'memory', 'memcache', 'container', 'datamapper
+
+ # cookie session store configuration
+ c[:session_secret_key] = 'f23e88da6bff058f03dfd6f3a863c33d67007f68' # required for cookie session store
+ # c[:session_id_key] = '_session_id' # cookie session id key, defaults to "_session_id"
+end
+
+Merb::BootLoader.before_app_loads do
+ DOC_XML = Nokogiri::XML.parse(File.read(Merb.root / "config" / "doc.xml", nil, 0))
+ # This will get executed after dependencies have been loaded but before your app's classes have loaded.
+end
+
+Merb::BootLoader.after_app_loads do
+ Merb::Cache.setup do
+ register(:default, Merb::Cache::PageStore[Merb::Cache::FileStore], :dir => Merb.root / :public / "cache")
+ end
+ # This will get executed after your app's classes have been loaded.
+end
diff --git a/config/rack.rb b/config/rack.rb
new file mode 100644
index 0000000..a9008cb
--- /dev/null
+++ b/config/rack.rb
@@ -0,0 +1,12 @@
+# use PathPrefix Middleware if :path_prefix is set in Merb::Config
+if prefix = ::Merb::Config[:path_prefix]
+ use Merb::Rack::PathPrefix, prefix
+end
+
+# comment this out if you are running merb behind a load balancer
+# that serves static files
+use Merb::Rack::Static, Merb.dir_for(:public)
+use Merb::Rack::Static, Merb.dir_for(:public) / "cache"
+
+# this is our main merb application
+run Merb::Rack::Application.new
\ No newline at end of file
diff --git a/config/router.rb b/config/router.rb
new file mode 100644
index 0000000..c58980e
--- /dev/null
+++ b/config/router.rb
@@ -0,0 +1,45 @@
+# Merb::Router is the request routing mapper for the merb framework.
+#
+# You can route a specific URL to a controller / action pair:
+#
+# match("/contact").
+# to(:controller => "info", :action => "contact")
+#
+# You can define placeholder parts of the url with the :symbol notation. These
+# placeholders will be available in the params hash of your controllers. For example:
+#
+# match("/books/:book_id/:action").
+# to(:controller => "books")
+#
+# Or, use placeholders in the "to" results for more complicated routing, e.g.:
+#
+# match("/admin/:module/:controller/:action/:id").
+# to(:controller => ":module/:controller")
+#
+# You can specify conditions on the placeholder by passing a hash as the second
+# argument of "match"
+#
+# match("/registration/:course_name", :course_name => /^[a-z]{3,5}-\d{5}$/).
+# to(:controller => "registration")
+#
+# You can also use regular expressions, deferred routes, and many other options.
+# See merb/specs/merb/router.rb for a fairly complete usage sample.
+
+Merb.logger.info("Compiling routes...")
+Merb::Router.prepare do
+ # RESTful routes
+ # resources :posts
+ resources :klasses, :identify => :name, :singular => "doc/class"
+
+ # Adds the required routes for merb-auth using the password slice
+ # slice(:merb_auth_slice_password, :name_prefix => nil, :path_prefix => "")
+
+ # This is the default route for /:controller/:action/:id
+ # This is fine for most cases. If you're heavily using resource-based
+ # routes, you may want to comment/remove this line to prevent
+ # clients from calling your create or destroy actions with a GET
+ default_routes
+
+ # Change this for your home page to be available at /
+ # match('/').to(:controller => 'whatever', :action =>'index')
+end
\ No newline at end of file
diff --git a/doc/rdoc/generators/merb_generator.rb b/doc/rdoc/generators/merb_generator.rb
new file mode 100644
index 0000000..544c273
--- /dev/null
+++ b/doc/rdoc/generators/merb_generator.rb
@@ -0,0 +1,1362 @@
+
+# # We're responsible for generating all the HTML files
+# from the object tree defined in code_objects.rb. We
+# generate:
+#
+# [files] an html file for each input file given. These
+# input files appear as objects of class
+# TopLevel
+#
+# [classes] an html file for each class or module encountered.
+# These classes are not grouped by file: if a file
+# contains four classes, we'll generate an html
+# file for the file itself, and four html files
+# for the individual classes.
+#
+# Method descriptions appear in whatever entity (file, class,
+# or module) that contains them.
+#
+# We generate files in a structure below a specified subdirectory,
+# normally +doc+.
+#
+# opdir
+# |
+# |___ files
+# | |__ per file summaries
+# |
+# |___ classes
+# |__ per class/module descriptions
+#
+# HTML is generated using the Template class.
+#
+
+require 'ftools'
+
+require 'rdoc/options'
+require 'rdoc/template'
+require 'rdoc/markup/simple_markup'
+require 'rdoc/markup/simple_markup/to_html'
+require 'cgi'
+
+module Generators
+
+ # Name of sub-direcories that hold file and class/module descriptions
+
+ FILE_DIR = "files"
+ CLASS_DIR = "classes"
+ CSS_NAME = "stylesheet.css"
+
+
+ ##
+ # Build a hash of all items that can be cross-referenced.
+ # This is used when we output required and included names:
+ # if the names appear in this hash, we can generate
+ # an html cross reference to the appropriate description.
+ # We also use this when parsing comment blocks: any decorated
+ # words matching an entry in this list are hyperlinked.
+
+ class AllReferences
+ @@refs = {}
+
+ def AllReferences::reset
+ @@refs = {}
+ end
+
+ def AllReferences.add(name, html_class)
+ @@refs[name] = html_class
+ end
+
+ def AllReferences.[](name)
+ @@refs[name]
+ end
+
+ def AllReferences.keys
+ @@refs.keys
+ end
+ end
+
+
+ ##
+ # Subclass of the SM::ToHtml class that supports looking
+ # up words in the AllReferences list. Those that are
+ # found (like AllReferences in this comment) will
+ # be hyperlinked
+
+ class HyperlinkHtml < SM::ToHtml
+ # We need to record the html path of our caller so we can generate
+ # correct relative paths for any hyperlinks that we find
+ def initialize(from_path, context)
+ super()
+ @from_path = from_path
+
+ @parent_name = context.parent_name
+ @parent_name += "::" if @parent_name
+ @context = context
+ end
+
+ # We're invoked when any text matches the CROSSREF pattern
+ # (defined in MarkUp). If we fine the corresponding reference,
+ # generate a hyperlink. If the name we're looking for contains
+ # no punctuation, we look for it up the module/class chain. For
+ # example, HyperlinkHtml is found, even without the Generators::
+ # prefix, because we look for it in module Generators first.
+
+ def handle_special_CROSSREF(special)
+ name = special.text
+ if name[0,1] == '#'
+ lookup = name[1..-1]
+ name = lookup unless Options.instance.show_hash
+ else
+ lookup = name
+ end
+
+ if /([A-Z].*)[.\#](.*)/ =~ lookup
+ container = $1
+ method = $2
+ ref = @context.find_symbol(container, method)
+ else
+ ref = @context.find_symbol(lookup)
+ end
+
+ if ref and ref.document_self
+ "#{name}"
+ else
+ name #it does not need to be a link
+ end
+ end
+
+
+ # Generate a hyperlink for url, labeled with text. Handle the
+ # special cases for img: and link: described under handle_special_HYPEDLINK
+ def gen_url(url, text)
+ if url =~ /([A-Za-z]+):(.*)/
+ type = $1
+ path = $2
+ else
+ type = "http"
+ path = url
+ url = "http://#{url}"
+ end
+
+ if type == "link"
+ url = path
+ end
+
+ if (type == "http" || type == "link") && url =~ /\.(gif|png|jpg|jpeg|bmp)$/
+ ""
+ elsif (type == "http" || type == "link")
+ "#{text}"
+ else
+ "#{text.sub(%r{^#{type}:/*}, '')}"
+
+ end
+ end
+
+ # And we're invoked with a potential external hyperlink mailto:
+ # just gets inserted. http: links are checked to see if they
+ # reference an image. If so, that image gets inserted using an
+ # tag. Otherwise a conventional is used. We also
+ # support a special type of hyperlink, link:, which is a reference
+ # to a local file whose path is relative to the --op directory.
+
+ def handle_special_HYPERLINK(special)
+ url = special.text
+ gen_url(url, url)
+ end
+
+ # HEre's a hypedlink where the label is different to the URL
+ #