Class: EBuilder
- Inherits:
-
Object
- Object
- EBuilder
- Includes:
- EConstants, EUtils
- Defined in:
- lib/e-builder/base.rb,
lib/e-builder/setup.rb,
lib/e-more/view/e-builder.rb
Defined Under Namespace
Classes: ExtendedRack
Constant Summary
Constants included from EConstants
EConstants::CONTENT_TYPE__DEFAULT, EConstants::CONTENT_TYPE__EVENT_STREAM, EConstants::ENV__AUTHORIZATION_KEYS, EConstants::ENV__ESPRESSO_ACTION, EConstants::ENV__ESPRESSO_FORMAT, EConstants::ENV__ESPRESSO_PATH_INFO, EConstants::ENV__HTTP_ACCEPT, EConstants::ENV__HTTP_HOST, EConstants::ENV__HTTP_IF_MODIFIED_SINCE, EConstants::ENV__HTTP_IF_NONE_MATCH, EConstants::ENV__HTTP_IF_UNMODIFIED_SINCE, EConstants::ENV__HTTP_X_FORWARDED_HOST, EConstants::ENV__HTTP_X_REQUESTED_WITH, EConstants::ENV__PATH_INFO, EConstants::ENV__QUERY_STRING, EConstants::ENV__RACK_ENV, EConstants::ENV__REMOTE_USER, EConstants::ENV__REQUEST_METHOD, EConstants::ENV__REQUEST_URI, EConstants::ENV__SCRIPT_NAME, EConstants::ENV__SERVER_NAME, EConstants::ENV__SERVER_PORT, EConstants::ENV__XML_HTTP_REQUEST, EConstants::HEADER__AUTHENTICATE, EConstants::HEADER__CACHE_CONTROL, EConstants::HEADER__CONTENT_DISPOSITION, EConstants::HEADER__CONTENT_TYPE, EConstants::HEADER__EXPIRES, EConstants::HEADER__LAST_MODIFIED, EConstants::HEADER__LOCATION, EConstants::HEADER__TRANSFER_ENCODING, EConstants::HTTP__DEFAULT_PORT, EConstants::HTTP__DEFAULT_REQUEST_METHOD, EConstants::HTTP__DEFAULT_SERVER, EConstants::HTTP__REQUEST_METHODS, EConstants::INDEX_ACTION, EConstants::PATH_MODIFIERS, EConstants::PATH_RULES, EConstants::RACK__WEBSOCKET, EConstants::STATUS__BAD_REQUEST, EConstants::STATUS__NOT_FOUND, EConstants::STATUS__NOT_IMPLEMENTED, EConstants::STATUS__OK, EConstants::STATUS__PERMANENT_REDIRECT, EConstants::STATUS__PROTECTED, EConstants::STATUS__REDIRECT, EConstants::STATUS__SERVER_ERROR, EConstants::VIEW__DEFAULT_ENGINE, EConstants::VIEW__DEFAULT_ENGINE_NAME, EConstants::VIEW__DEFAULT_PATH, EConstants::VIEW__ENGINE_BY_SYM, EConstants::VIEW__ENGINE_MAPPER, EConstants::VIEW__EXTRA_ENGINES, EConstants::VIEW__EXT_BY_ENGINE
Instance Attribute Summary collapse
-
#controllers ⇒ Object
readonly
Returns the value of attribute controllers.
-
#mounted_controllers ⇒ Object
readonly
Returns the value of attribute mounted_controllers.
Class Method Summary collapse
Instance Method Summary collapse
- #app ⇒ Object
-
#automount! ⇒ Object
auto-mount auto-discovered controllers.
- #base_url ⇒ Object
-
#basic_auth(opts = {}, &proc) ⇒ Object
(also: #auth)
set authorization at app level.
- #call(env) ⇒ Object
-
#clear_compiler(*keys) ⇒ Object
same as clear_compiler! except it work only on current process.
-
#clear_compiler! ⇒ Object
clearing compiler cache.
-
#compiler_pool(pool = nil) ⇒ Object
for most apps, most expensive operations are fs operations and template compilation.
-
#digest_auth(opts = {}, &proc) ⇒ Object
set authorization at app level.
- #environment ⇒ Object
-
#global_setup(&proc) ⇒ Object
(also: #setup_controllers, #controllers_setup, #setup)
proc given here will be executed inside all controllers.
-
#initialize(automount = false, &proc) ⇒ EBuilder
constructor
creates new Espresso app.
-
#map(url, opts = {}) ⇒ Object
set base URL to be prepended to all controllers.
- #middleware ⇒ Object
-
#mount(*args, &setup) ⇒ Object
mount given/discovered controllers into current app.
-
#on_boot(&proc) ⇒ Object
block(s) to run just before application starts.
-
#rewrite(rule, &proc) ⇒ Object
(also: #rewrite_rule)
declaring rewrite rules.
-
#root(path = nil) ⇒ Object
(also: #app_root)
set/get app root.
-
#run(opts = {}) ⇒ Object
by default, Espresso will use WEBrick server.
-
#session(use, *args) ⇒ Object
allow app to use sessions.
-
#streaming_backend ⇒ Object
by default Espresso will use EventMachine for streaming, but it also supports Celluloid, when Reel web-server used.
- #to_app ⇒ Object (also: #to_app!, #boot!)
-
#url_map(opts = {}) ⇒ Object
(also: #urlmap)
displays URLs the app will respond to, with controller and action that serving each URL.
-
#use(ware, *args, &block) ⇒ Object
middleware declared here will be used on all controllers.
Methods included from EUtils
action_to_route, build_path, canonical_to_route, class_to_route, deRESTify_action, encode_token_auth_credentials, extract_hosts, indifferent_hash, indifferent_params, is_app?, method_arity, normalize_path, register_extra_engines!, rootify_url, route_to_regexp, underscore
Constructor Details
#initialize(automount = false, &proc) ⇒ EBuilder
creates new Espresso app.
19 20 21 22 23 24 25 26 |
# File 'lib/e-builder/base.rb', line 19 def initialize automount = false, &proc @controllers, @subcontrollers = {}, [] @routes, @hosts, @controllers_hosts = {}, {}, {} @automount = automount proc && self.instance_exec(&proc) use ExtendedRack compiler_pool(Hash.new) end |
Instance Attribute Details
#controllers ⇒ Object (readonly)
Returns the value of attribute controllers.
9 10 11 |
# File 'lib/e-builder/base.rb', line 9 def controllers @controllers end |
#mounted_controllers ⇒ Object (readonly)
Returns the value of attribute mounted_controllers.
9 10 11 |
# File 'lib/e-builder/base.rb', line 9 def mounted_controllers @mounted_controllers end |
Class Method Details
.call(env) ⇒ Object
5 6 7 |
# File 'lib/e-builder/base.rb', line 5 def self.call env new(:automount).call(env) end |
Instance Method Details
#app ⇒ Object
157 158 159 160 161 162 163 164 165 |
# File 'lib/e-builder/base.rb', line 157 def app @app ||= begin on_boot! mount_controllers! @sorted_routes = sorted_routes.freeze @routes.freeze middleware.reverse.inject(lambda {|env| call!(env)}) {|a,e| e[a]} end end |
#automount! ⇒ Object
auto-mount auto-discovered controllers. call this only after all controllers defined and app ready to start! leaving it in public zone for better control over mounting.
67 68 69 70 71 72 |
# File 'lib/e-builder/base.rb', line 67 def automount! controllers = [Class, Module, Regexp].include?(@automount.class) ? extract_controllers(@automount) : discover_controllers mount controllers.select {|c| c.accept_automount?} end |
#base_url ⇒ Object
10 11 12 |
# File 'lib/e-builder/setup.rb', line 10 def base_url @base_url || '' end |
#basic_auth(opts = {}, &proc) ⇒ Object Also known as: auth
set authorization at app level. any controller/action will be protected.
86 87 88 |
# File 'lib/e-builder/setup.rb', line 86 def basic_auth opts = {}, &proc use Rack::Auth::Basic, opts[:realm] || 'AccessRestricted', &proc end |
#call(env) ⇒ Object
153 154 155 |
# File 'lib/e-builder/base.rb', line 153 def call env app.call env end |
#clear_compiler(*keys) ⇒ Object
same as clear_compiler! except it work only on current process
33 34 35 |
# File 'lib/e-more/view/e-builder.rb', line 33 def clear_compiler *keys compiler_pool && compiler_pool.clear end |
#clear_compiler! ⇒ Object
clearing compiler cache
27 28 29 30 |
# File 'lib/e-more/view/e-builder.rb', line 27 def clear_compiler! clear_compiler ipcm_trigger :clear_compiler end |
#compiler_pool(pool = nil) ⇒ Object
for most apps, most expensive operations are fs operations and template compilation. to avoid these operations, templates are compiled and stored into memory. on consequent requests they are just rendered.
by default, compiler are disabled. to enable it, set compiler pool at app level.
if you want to use a custom pool, make sure your pool behaves just like a Hash, meant it responds to []=, [], and clear methods.
20 21 22 23 |
# File 'lib/e-more/view/e-builder.rb', line 20 def compiler_pool pool = nil @compiler_pool = pool if pool @compiler_pool end |
#digest_auth(opts = {}, &proc) ⇒ Object
set authorization at app level. any controller/action will be protected.
92 93 94 95 96 |
# File 'lib/e-builder/setup.rb', line 92 def digest_auth opts = {}, &proc opts[:realm] ||= 'AccessRestricted' opts[:opaque] ||= opts[:realm] use Rack::Auth::Digest::MD5, opts, &proc end |
#environment ⇒ Object
109 110 111 |
# File 'lib/e-builder/base.rb', line 109 def environment ENV[ENV__RACK_ENV] || :development end |
#global_setup(&proc) ⇒ Object Also known as: setup_controllers, controllers_setup, setup
proc given here will be executed inside all controllers. used to setup multiple controllers at once.
76 77 78 79 |
# File 'lib/e-builder/base.rb', line 76 def global_setup &proc @global_setup = proc self end |
#map(url, opts = {}) ⇒ Object
set base URL to be prepended to all controllers
4 5 6 7 8 |
# File 'lib/e-builder/setup.rb', line 4 def map url, opts = {} url.is_a?(Hash) && (opts = url) && (url = '') @base_url = rootify_url(url).freeze @hosts = extract_hosts(opts) end |
#middleware ⇒ Object
144 145 146 |
# File 'lib/e-builder/setup.rb', line 144 def middleware @middleware ||= [] end |
#mount(*args, &setup) ⇒ Object
mount given/discovered controllers into current app. any number of arguments accepted. String arguments are treated as roots/canonicals. any other arguments are used to discover controllers. controllers can be passed directly or as a Module that contain controllers or as a Regexp matching controller’s name.
proc given here will be executed inside given/discovered controllers
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/e-builder/base.rb', line 37 def mount *args, &setup root, controllers, applications = nil, [], [] opts = args.last.is_a?(Hash) ? args.pop : {} args.flatten.each do |a| if a.is_a?(String) root = rootify_url(a) elsif is_app?(a) controllers << a elsif a.respond_to?(:call) applications << a else controllers.concat extract_controllers(a) end end controllers.each do |c| @controllers[c] = [root, opts, setup] c.subcontrollers.each do |sc| mount(sc, root.to_s + c.base_url, opts) @subcontrollers << sc end end mount_applications applications, root, opts self end |
#on_boot(&proc) ⇒ Object
block(s) to run just before application starts
234 235 236 |
# File 'lib/e-builder/setup.rb', line 234 def on_boot &proc (@on_boot ||= []).push(proc) end |
#rewrite(rule, &proc) ⇒ Object Also known as: rewrite_rule
any method available to controller instance are also available inside rule proc. so you can fine tune the behavior of any rule. ex. redirect on GET requests and pass control on POST requests. or do permanent redirect for robots and simple redirect for browsers etc.
declaring rewrite rules.
first argument should be a regex and a proc should be provided.
the regex(actual rule) will be compared against Request-URI, i.e. current URL without query string. if some rule depend on query string, use params inside proc to determine either some param was or not set.
the proc will decide how to operate when rule matched. you can do: ‘redirect(’location’)‘
redirect to new location using 302 status code
‘permanent_redirect(’location’)‘
redirect to new location using 301 status code
‘pass(controller, action, any, params, with => opts)`
pass control to given controller and action without redirect.
consequent params are used to build URL to be sent to given controller.
‘halt(status|body|headers|response)`
send response to browser without redirect.
accepts an arbitrary number of arguments.
if arg is an Integer, it will be used as status code.
if arg is a Hash, it is treated as headers.
if it is an array, it is treated as Rack response and are sent immediately, ignoring other args.
any other args are treated as body.
211 212 213 214 |
# File 'lib/e-builder/setup.rb', line 211 def rewrite rule, &proc proc || raise(ArgumentError, "Rewrite rules requires a block to run") @routes[rule] = {'GET' => {:rewriter => proc}} end |
#root(path = nil) ⇒ Object Also known as: app_root
set/get app root
15 16 17 18 |
# File 'lib/e-builder/setup.rb', line 15 def root path = nil @root = ('%s/' % path).sub(/\/+\Z/, '/').freeze if path @root ||= (::Dir.pwd << '/').freeze end |
#run(opts = {}) ⇒ Object
by default, Espresso will use WEBrick server. pass :server option and any option accepted by selected(or default) server:
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/e-builder/base.rb', line 126 def run opts = {} boot! handler = opts.delete(:server) (handler && Rack::Handler.const_defined?(handler)) || (handler = HTTP__DEFAULT_SERVER) port = opts.delete(:port) opts[:Port] ||= port || HTTP__DEFAULT_PORT host = opts.delete(:host) || opts.delete(:bind) opts[:Host] = host if host $stderr.puts "\n--- Starting Espresso for %s on %s port backed by %s server ---\n\n" % [ environment, opts[:Port], handler ] Rack::Handler.const_get(handler).run app, opts do |server| %w[INT TERM].each do |sig| Signal.trap(sig) do $stderr.puts "\n--- Stopping Espresso... ---\n\n" server.respond_to?(:stop!) ? server.stop! : server.stop end end server.threaded = opts[:threaded] if server.respond_to? :threaded= yield server if block_given? end end |
#session(use, *args) ⇒ Object
allow app to use sessions.
70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/e-builder/setup.rb', line 70 def session use, *args args.unshift case use when :memory Rack::Session::Pool when :cookies Rack::Session::Cookie when :memcache Rack::Session::Memcache else use end use(*args) end |
#streaming_backend ⇒ Object
by default Espresso will use EventMachine for streaming, but it also supports Celluloid, when Reel web-server used. use this method to set Celluloid as streaming backend.
226 227 228 229 230 231 |
# File 'lib/e-builder/setup.rb', line 226 def streaming_backend backend = nil @streaming_backend = backend def streaming_backend @streaming_backend end end |
#to_app ⇒ Object Also known as: to_app!, boot!
167 168 169 170 |
# File 'lib/e-builder/base.rb', line 167 def to_app app self end |
#url_map(opts = {}) ⇒ Object Also known as: urlmap
displays URLs the app will respond to, with controller and action that serving each URL.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/e-builder/base.rb', line 86 def url_map opts = {} mount_controllers! map = sorted_routes.inject({}) do |m,r| @routes[r].each_pair {|rm,rs| (m[r] ||= {})[rm] = rs.dup}; m end def map.to_s out = '' self.each_pair do |route, request_methods| next if route.source.size == 0 out << "%s\n" % route.source request_methods.each_pair do |rm,rs| out << " %s%s" % [rm, ' ' * (10 - rm.to_s.size)] out << "%s\n" % (rs[:app] || [rs[:controller], rs[:action]]*'#') end out << "\n" end out end map end |
#use(ware, *args, &block) ⇒ Object
middleware defined inside some controller will run only for that controller. to have global middleware, define it at app level.
middleware declared here will be used on all controllers.
especially, here should go middleware that changes app state, which wont work if defined inside controller.
you can of course define any type of middleware at app level, it is even recommended to do so to avoid redundant middleware declaration at controllers level.
Any middleware that does not change app state, i.e. non-upfront middleware, can be defined inside controllers.
140 141 142 |
# File 'lib/e-builder/setup.rb', line 140 def use ware, *args, &block middleware << proc { |app| ware.new(app, *args, &block) } end |