Class: Gin::Controller
- Inherits:
-
Object
- Object
- Gin::Controller
- Extended by:
- GinClass
- Includes:
- Constants, Errorable, Filterable
- Defined in:
- lib/gin/controller.rb
Overview
Gin controllers follow only a few rules:
* ALL instance methods are actions (put your helper methods in a module or
parent class not mounted to the app).
* Filters are defined by blocks passed to special class methods.
* Controller-level error handlers are defined by blocks passed to the 'error'
class method.
Gin controller actions are any instance method defined on the controller
class. The HTTP response body takes the value of the method's return value.
If the instance method takes arguments, matching params will be assigned to
them. A required argument with a missing param triggers a Gin::BadRequest
error, resulting in a 400 response.
class UserController < Gin::Controller
# Get params id and email
def show id, email=nil
...
end
end
Gin actions also support Ruby 2.0 keyed arguments, which are more flexible
for assigning default values when dealing with missing params.
class UserController < Gin::Controller
def show(id, email: nil, full: false)
...
end
end
Views are rendered by calling the 'view' method from a controller instance.
Views don't halt the action but return a String of the rendered view.
If a layout was set, the rendered view will include the layout.
class UserController < Gin::Controller
layout :user
def show id
# Renders <app.views_dir>/show_user.* with the layout <app.layouts_dir>/user.*
view :show_user
end
def tos
# Renders <app.views_dir>/tos.* with no layout
view :tos, :layout => false
end
end
Constant Summary
Constants included from Constants
Gin::Constants::ASYNC_CALLBACK, Gin::Constants::CACHE_CTRL, Gin::Constants::CNT_DISPOSITION, Gin::Constants::CNT_LENGTH, Gin::Constants::CNT_TYPE, Gin::Constants::ENV_DEV, Gin::Constants::ENV_PROD, Gin::Constants::ENV_STAGE, Gin::Constants::ENV_TEST, Gin::Constants::EPOCH, Gin::Constants::ETAG, Gin::Constants::EXPIRES, Gin::Constants::FWD_FOR, Gin::Constants::FWD_HOST, Gin::Constants::GIN_ACTION, Gin::Constants::GIN_CTRL, Gin::Constants::GIN_ERRORS, Gin::Constants::GIN_PATH_PARAMS, Gin::Constants::GIN_RELOADED, Gin::Constants::GIN_ROUTE, Gin::Constants::GIN_STACK, Gin::Constants::GIN_STATIC, Gin::Constants::GIN_TEMPLATES, Gin::Constants::GIN_TIMESTAMP, Gin::Constants::HTTP_VERSION, Gin::Constants::IF_MATCH, Gin::Constants::IF_MOD_SINCE, Gin::Constants::IF_NONE_MATCH, Gin::Constants::IF_UNMOD_SINCE, Gin::Constants::LAST_MOD, Gin::Constants::LOCATION, Gin::Constants::PATH_INFO, Gin::Constants::PRAGMA, Gin::Constants::QUERY_STRING, Gin::Constants::REMOTE_ADDR, Gin::Constants::REMOTE_USER, Gin::Constants::REQ_METHOD, Gin::Constants::SESSION_SECRET
Instance Attribute Summary collapse
-
#action ⇒ Object
readonly
The action that the HTTP request resolved to, based on the App’s router.
-
#app ⇒ Object
readonly
The Gin::App instance used by the controller.
-
#env ⇒ Object
readonly
The Rack env hash.
-
#request ⇒ Object
readonly
Gin::Request instance representing the HTTP request.
-
#response ⇒ Object
readonly
Gin::Response instance representing the HTTP response.
Class Method Summary collapse
-
.actions ⇒ Object
Array of action names for this controller.
-
.content_type(new_type = nil) ⇒ Object
Set or get the default content type for this Gin::Controller.
-
.controller_name(new_name = nil) ⇒ Object
String representing the controller name.
-
.exec(app, env, &block) ⇒ Object
Execute arbitrary code in the context of a Gin::Controller instance.
- .inherited(subclass) ⇒ Object
-
.layout(name = nil) ⇒ Object
Get or set a layout for a given controller.
-
.setup ⇒ Object
:nodoc:.
Instance Method Summary collapse
-
#asset(path) ⇒ Object
Check if an asset exists.
-
#asset_url(name) ⇒ Object
Returns the url to an asset, including predefined asset cdn hosts if set.
-
#body(body = nil) ⇒ Object
Get or set the HTTP response body.
-
#cache_control(*values) ⇒ Object
Specify response freshness policy for HTTP caches (Cache-Control header).
-
#call_action(action) ⇒ Object
:nodoc:.
-
#config ⇒ Object
Accessor for @app.config.
-
#content_type(type = nil, params = {}) ⇒ Object
Get or set the HTTP response Content-Type header.
-
#cookies ⇒ Object
Access the request cookies.
-
#delete_cookie(name) ⇒ Object
Delete the response cookie with the given name.
-
#dispatch(action) ⇒ Object
Dispatch the call to the action, calling before and after filers, and including error handling.
-
#error(code, body = nil) ⇒ Object
Halt processing and return the error status provided.
-
#etag(value, opts = {}) ⇒ Object
Set the ETag header.
-
#etag_matches?(list, new_resource = @request.post?) ⇒ Boolean
:nodoc:.
-
#expire_cache_control ⇒ Object
Sets Cache-Control, Expires, and Pragma headers to tell the browser not to cache the response.
-
#expires(amount, *values) ⇒ Object
Set the Expires header and Cache-Control/max-age directive.
-
#h(obj) ⇒ Object
HTML-escape the given String.
-
#halt(*resp) ⇒ Object
Stop the execution of an action and return the response.
-
#headers(hash = nil) ⇒ Object
Set multiple response headers with Hash.
-
#html_error_page(err, code = nil) ⇒ Object
In development mode, returns an HTML page displaying the full error and backtrace, otherwise shows a generic error page.
-
#initialize(app, env) ⇒ Controller
constructor
A new instance of Controller.
-
#invoke ⇒ Object
Taken from Sinatra.
-
#last_modified(time) ⇒ Object
Set the last modified time of the resource (HTTP ‘Last-Modified’ header) and halt if conditional GET matches.
-
#layout ⇒ Object
Value of the layout to use for rendering.
-
#logger ⇒ Object
Accessor for main application logger.
-
#mime_type(type) ⇒ Object
Get the normalized mime-type matching the given input.
-
#params ⇒ Object
Get the request params.
-
#path_to(*args) ⇒ Object
Build a path to the given controller and action or route name, with any expected params.
-
#redirect(uri, *args) ⇒ Object
Send a 301, 302, or 303 redirect and halt.
-
#send_file(path, opts = {}) ⇒ Object
Assigns a file to the response body and halts the execution of the action.
-
#session ⇒ Object
Access the request session.
-
#set_cookie(name, value = nil, opts = {}) ⇒ Object
Set a cookie on the Rack response.
-
#status(code = nil) ⇒ Object
Set or get the HTTP response status code.
-
#stream(keep_open = false, &block) ⇒ Object
Assigns a Gin::Stream to the response body, which is yielded to the block.
-
#template_path(template, is_layout = false) ⇒ Object
Returns the path to where the template is expected to be.
- #url_to(*args) ⇒ Object (also: #to)
-
#view(template, opts = {}, &block) ⇒ Object
Render a template with the given view template.
Methods included from Errorable
#handle_error, #handle_status, included
Methods included from Filterable
Constructor Details
#initialize(app, env) ⇒ Controller
Returns a new instance of Controller.
158 159 160 161 162 163 164 |
# File 'lib/gin/controller.rb', line 158 def initialize app, env @app = app @action = nil @env = env @request = Gin::Request.new env @response = Gin::Response.new end |
Instance Attribute Details
#action ⇒ Object (readonly)
The action that the HTTP request resolved to, based on the App’s router.
152 153 154 |
# File 'lib/gin/controller.rb', line 152 def action @action end |
#app ⇒ Object (readonly)
The Gin::App instance used by the controller. The App instance is meant for read-only use. Writes are not thread-safe and at your own risk.
143 144 145 |
# File 'lib/gin/controller.rb', line 143 def app @app end |
#env ⇒ Object (readonly)
The Rack env hash.
155 156 157 |
# File 'lib/gin/controller.rb', line 155 def env @env end |
#request ⇒ Object (readonly)
Gin::Request instance representing the HTTP request.
146 147 148 |
# File 'lib/gin/controller.rb', line 146 def request @request end |
#response ⇒ Object (readonly)
Gin::Response instance representing the HTTP response.
149 150 151 |
# File 'lib/gin/controller.rb', line 149 def response @response end |
Class Method Details
.actions ⇒ Object
Array of action names for this controller.
86 87 88 |
# File 'lib/gin/controller.rb', line 86 def self.actions instance_methods(false) end |
.content_type(new_type = nil) ⇒ Object
Set or get the default content type for this Gin::Controller. Default value is “text/html”. This attribute is inherited.
107 108 109 110 111 112 |
# File 'lib/gin/controller.rb', line 107 def self.content_type new_type=nil @content_type = new_type if new_type return @content_type if defined?(@content_type) && @content_type self.superclass.respond_to?(:content_type) && self.superclass.content_type || "text/html" end |
.controller_name(new_name = nil) ⇒ Object
String representing the controller name. Underscores the class name and removes mentions of ‘controller’.
MyApp::FooController.controller_name
#=> "my_app/foo"
97 98 99 100 |
# File 'lib/gin/controller.rb', line 97 def self.controller_name new_name=nil @ctrl_name = new_name if new_name @ctrl_name end |
.exec(app, env, &block) ⇒ Object
Execute arbitrary code in the context of a Gin::Controller instance. Returns a Rack response Array.
119 120 121 122 123 |
# File 'lib/gin/controller.rb', line 119 def self.exec app, env, &block inst = new(app, env) inst.invoke{ inst.instance_exec(&block) } inst.response.finish end |
.inherited(subclass) ⇒ Object
69 70 71 72 |
# File 'lib/gin/controller.rb', line 69 def self.inherited subclass subclass.setup super end |
.layout(name = nil) ⇒ Object
Get or set a layout for a given controller. Value can be a symbol or filepath. Layout file is expected to be in the Gin::App.layout_dir directory Defaults to the parent class layout, or Gin::App.layout.
132 133 134 135 136 |
# File 'lib/gin/controller.rb', line 132 def self.layout name=nil @layout = name if name return @layout if @layout return self.superclass.layout if self.superclass.respond_to?(:layout) end |
.setup ⇒ Object
:nodoc:
75 76 77 78 |
# File 'lib/gin/controller.rb', line 75 def self.setup # :nodoc: @layout = nil @ctrl_name = Gin.underscore(self.to_s).gsub(/_?controller_?/,'') end |
Instance Method Details
#asset(path) ⇒ Object
Check if an asset exists. Returns the full system path to the asset if found, otherwise nil.
617 618 619 |
# File 'lib/gin/controller.rb', line 617 def asset path @app.asset path end |
#asset_url(name) ⇒ Object
Returns the url to an asset, including predefined asset cdn hosts if set.
606 607 608 609 610 |
# File 'lib/gin/controller.rb', line 606 def asset_url name url = File.join(@app.asset_host_for(name).to_s, name) url = [url, *@app.asset_version(url)].join("?") if url !~ %r{^https?://} url end |
#body(body = nil) ⇒ Object
Get or set the HTTP response body.
187 188 189 190 |
# File 'lib/gin/controller.rb', line 187 def body body=nil @response.body = body if body @response.body end |
#cache_control(*values) ⇒ Object
Specify response freshness policy for HTTP caches (Cache-Control header). Any number of non-value directives (:public, :private, :no_cache, :no_store, :must_revalidate, :proxy_revalidate) may be passed along with a Hash of value directives (:max_age, :min_stale, :s_max_age).
cache_control :public, :must_revalidate, :max_age => 60
#=> Cache-Control: public, must-revalidate, max-age=60
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 |
# File 'lib/gin/controller.rb', line 546 def cache_control *values if Hash === values.last hash = values.pop hash.reject!{|k,v| v == false || v == true && values << k } else hash = {} end values.map! { |value| value.to_s.tr('_','-') } hash.each do |key, value| key = key.to_s.tr('_', '-') value = value.to_i if key == "max-age" values << [key, value].join('=') end @response[CACHE_CTRL] = values.join(', ') if values.any? end |
#call_action(action) ⇒ Object
:nodoc:
167 168 169 170 171 172 |
# File 'lib/gin/controller.rb', line 167 def call_action action #:nodoc: invoke{ dispatch action } invoke{ handle_status(@response.status) } content_type self.class.content_type unless @response[CNT_TYPE] @response.finish end |
#config ⇒ Object
Accessor for @app.config.
196 197 198 |
# File 'lib/gin/controller.rb', line 196 def config @app.config end |
#content_type(type = nil, params = {}) ⇒ Object
Get or set the HTTP response Content-Type header.
content_type :json
content_type 'application/json;charset=us-ascii'
content_type :json, charset: 'us-ascii'
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/gin/controller.rb', line 215 def content_type type=nil, params={} return @response[CNT_TYPE] unless type default = params.delete(:default) mime_type = mime_type(type) || default raise "Unknown media type: %p" % type if mime_type.nil? mime_type = mime_type.dup unless params.include? :charset params[:charset] = params.delete('charset') || 'UTF-8' end params.delete :charset if mime_type.include? 'charset' unless params.empty? mime_type << (mime_type.include?(';') ? ', ' : ';') mime_type << params.map do |key, val| val = val.inspect if val =~ /[";,]/ "#{key}=#{val}" end.join(', ') end @response[CNT_TYPE] = mime_type end |
#cookies ⇒ Object
Access the request cookies.
357 358 359 |
# File 'lib/gin/controller.rb', line 357 def @request. end |
#delete_cookie(name) ⇒ Object
Delete the response cookie with the given name. Does not affect request cookies.
383 384 385 |
# File 'lib/gin/controller.rb', line 383 def name @response. name end |
#dispatch(action) ⇒ Object
Dispatch the call to the action, calling before and after filers, and including error handling.
742 743 744 745 746 747 748 749 750 751 752 753 754 755 |
# File 'lib/gin/controller.rb', line 742 def dispatch action @action = action invoke do filter(*before_filters_for(action)) args = action_arguments action __send__(action, *args) end rescue => err invoke{ handle_error err } ensure filter(*after_filters_for(action)) end |
#error(code, body = nil) ⇒ Object
Halt processing and return the error status provided.
261 262 263 264 265 |
# File 'lib/gin/controller.rb', line 261 def error code, body=nil code, body = 500, code if code.respond_to? :to_str @response.body = body unless body.nil? halt code end |
#etag(value, opts = {}) ⇒ Object
Set the ETag header. If the ETag was set in a previous request and matches the current one, halts the action and returns a 304 on GET and HEAD requests.
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 |
# File 'lib/gin/controller.rb', line 273 def etag value, opts={} opts = {:kind => opts} unless Hash === opts kind = opts[:kind] || :strong new_resource = opts.fetch(:new_resource) { @request.post? } unless [:strong, :weak].include?(kind) raise ArgumentError, ":strong or :weak expected" end value = '"%s"' % value value = 'W/' + value if kind == :weak @response[ETAG] = value if (200..299).include?(status) || status == 304 if etag_matches? @env[IF_NONE_MATCH], new_resource halt(@request.safe? ? 304 : 412) end if @env[IF_MATCH] halt 412 unless etag_matches? @env[IF_MATCH], new_resource end end end |
#etag_matches?(list, new_resource = @request.post?) ⇒ Boolean
:nodoc:
298 299 300 301 |
# File 'lib/gin/controller.rb', line 298 def etag_matches? list, new_resource=@request.post? #:nodoc: return !new_resource if list == '*' list.to_s.split(/\s*,\s*/).include? response[ETAG] end |
#expire_cache_control ⇒ Object
Sets Cache-Control, Expires, and Pragma headers to tell the browser not to cache the response.
597 598 599 600 |
# File 'lib/gin/controller.rb', line 597 def expire_cache_control @response[PRAGMA] = 'no-cache' expires EPOCH, :no_cache, :no_store, :must_revalidate, max_age: 0 end |
#expires(amount, *values) ⇒ Object
Set the Expires header and Cache-Control/max-age directive. Amount can be an integer number of seconds in the future or a Time object indicating when the response should be considered “stale”. The remaining “values” arguments are passed to the #cache_control helper:
expires 500, :public, :must_revalidate
=> Cache-Control: public, must-revalidate, max-age=60
=> Expires: Mon, 08 Jun 2009 08:50:17 GMT
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 |
# File 'lib/gin/controller.rb', line 575 def expires amount, *values values << {} unless Hash === values.last if Integer === amount time = Time.now + amount.to_i max_age = amount else time = String === amount ? Time.parse(amount) : amount max_age = time - Time.now end values.last.merge!(:max_age => max_age) unless values.last[:max_age] cache_control(*values) @response[EXPIRES] = time.httpdate end |
#h(obj) ⇒ Object
HTML-escape the given String.
794 795 796 |
# File 'lib/gin/controller.rb', line 794 def h obj CGI.escapeHTML obj.to_s end |
#halt(*resp) ⇒ Object
Stop the execution of an action and return the response. May be given a status code, string, header Hash, or a combination:
halt 400, "Badly formed request"
halt "Done early! WOOO!"
halt 302, {'Location' => 'http://example.com'}, "You are being redirected"
247 248 249 250 251 252 253 254 255 |
# File 'lib/gin/controller.rb', line 247 def halt *resp if @app.development? line = caller.find{|l| !l.start_with?(Gin::LIB_DIR) && !l.include?("/ruby/gems/")} logger << "[HALT] #{line}\n" if line end resp = resp.first if resp.length == 1 throw :halt, resp end |
#headers(hash = nil) ⇒ Object
Set multiple response headers with Hash.
309 310 311 312 |
# File 'lib/gin/controller.rb', line 309 def headers hash=nil @response.headers.merge! hash if hash @response.headers end |
#html_error_page(err, code = nil) ⇒ Object
In development mode, returns an HTML page displaying the full error and backtrace, otherwise shows a generic error page.
Production error pages are first looked for in the public directory as <status>.html or 500.html. If none is found, falls back on Gin’s internal error html pages.
766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 |
# File 'lib/gin/controller.rb', line 766 def html_error_page err, code=nil if @app.development? fulltrace = err.backtrace.join("\n") fulltrace = "<pre>#{h(fulltrace)}</pre>" apptrace = Gin.app_trace(err.backtrace).join("\n") apptrace = "<pre>#{h(apptrace)}</pre>" unless apptrace.empty? DEV_ERROR_HTML % [h(err.class), h(err.class), h(err.), apptrace, fulltrace] else code ||= status filepath = asset("#{code}.html") || asset("500.html") unless filepath filepath = File.join(Gin::PUBLIC_DIR, "#{code}.html") filepath = File.join(Gin::PUBLIC_DIR, "500.html") if !File.file?(filepath) end File.open(filepath, "rb") end end |
#invoke ⇒ Object
Taken from Sinatra.
Run the block with ‘throw :halt’ support and apply result to the response.
723 724 725 726 727 728 729 730 731 732 733 734 735 |
# File 'lib/gin/controller.rb', line 723 def invoke res = catch(:halt) { yield } res = [res] if Fixnum === res || String === res if Array === res && Fixnum === res.first res = res.dup status(res.shift) body(res.pop) headers(*res) elsif res.respond_to? :each body res end nil # avoid double setting the same response tuple twice end |
#last_modified(time) ⇒ Object
Set the last modified time of the resource (HTTP ‘Last-Modified’ header) and halt if conditional GET matches. The time argument is a Time, DateTime, or other object that responds to to_time or httpdate.
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 |
# File 'lib/gin/controller.rb', line 510 def last_modified time return unless time time = Time.at(time) if Integer === time time = Time.parse(time) if String === time time = time.to_time if time.respond_to?(:to_time) @response[LAST_MOD] = time.httpdate return if @env[IF_NONE_MATCH] if status == 200 && @env[IF_MOD_SINCE] # compare based on seconds since epoch since = Time.httpdate(@env[IF_MOD_SINCE]).to_i halt 304 if since >= time.to_i end if @env[IF_UNMOD_SINCE] && ((200..299).include?(status) || status == 412) # compare based on seconds since epoch since = Time.httpdate(@env[IF_UNMOD_SINCE]).to_i halt 412 if since < time.to_i end rescue ArgumentError end |
#layout ⇒ Object
Value of the layout to use for rendering. See also Gin::Controller.layout and Gin::App.layout.
626 627 628 |
# File 'lib/gin/controller.rb', line 626 def layout self.class.layout || @app.layout end |
#logger ⇒ Object
Accessor for main application logger.
333 334 335 |
# File 'lib/gin/controller.rb', line 333 def logger @app.logger end |
#mime_type(type) ⇒ Object
Get the normalized mime-type matching the given input.
204 205 206 |
# File 'lib/gin/controller.rb', line 204 def mime_type type @app.mime_type type end |
#params ⇒ Object
Get the request params.
341 342 343 |
# File 'lib/gin/controller.rb', line 341 def params @request.params end |
#path_to(*args) ⇒ Object
Build a path to the given controller and action or route name, with any expected params. If no controller is specified and the current controller responds to the symbol given, uses the current controller for path lookup.
path_to FooController, :show, :id => 123
#=> "/foo/123"
# From FooController
path_to :show, :id => 123
#=> "/foo/123"
# Default named route
path_to :show_foo, :id => 123
#=> "/foo/123"
405 406 407 408 409 |
# File 'lib/gin/controller.rb', line 405 def path_to *args return "#{args[0]}#{"?" << Gin.build_query(args[1]) if args[1]}" if String === args[0] args.unshift(self.class) if Symbol === args[0] && respond_to?(args[0]) @app.router.path_to(*args) end |
#redirect(uri, *args) ⇒ Object
Send a 301, 302, or 303 redirect and halt. Supports passing a full URI, partial path.
redirect "http://google.com"
redirect "/foo"
redirect "/foo", 301, "You are being redirected..."
redirect to(MyController, :action, :id => 123)
redirect to(:show_foo, :id => 123)
462 463 464 465 466 467 468 469 470 471 |
# File 'lib/gin/controller.rb', line 462 def redirect uri, *args if @env[HTTP_VERSION] == 'HTTP/1.1' && @env[REQ_METHOD] != 'GET' status 303 else status 302 end @response[LOCATION] = url_to(uri.to_s) halt(*args) end |
#send_file(path, opts = {}) ⇒ Object
Assigns a file to the response body and halts the execution of the action. Produces a 404 response if no file is found.
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 |
# File 'lib/gin/controller.rb', line 478 def send_file path, opts={} if opts[:type] || !@response[CNT_TYPE] content_type opts[:type] || File.extname(path), :default => 'application/octet-stream' end disposition = opts[:disposition] filename = opts[:filename] disposition = 'attachment' if disposition.nil? && filename filename = File.basename(path) if filename.nil? if disposition @response[CNT_DISPOSITION] = "%s; filename=\"%s\"" % [disposition, filename] end last_modified opts[:last_modified] || File.mtime(path).httpdate halt 200 if @request.head? @response[CNT_LENGTH] = File.size?(path).to_s halt 200, File.open(path, "rb") rescue Errno::ENOENT halt 404 end |
#session ⇒ Object
Access the request session.
349 350 351 |
# File 'lib/gin/controller.rb', line 349 def session @request.session end |
#set_cookie(name, value = nil, opts = {}) ⇒ Object
Set a cookie on the Rack response.
"mycookie", "FOO", :expires => 600, :path => "/"
"mycookie", :expires => 600
368 369 370 371 372 373 374 375 376 |
# File 'lib/gin/controller.rb', line 368 def name, value=nil, opts={} if Hash === value opts = value else opts[:value] = value end @response. name, opts end |
#status(code = nil) ⇒ Object
Set or get the HTTP response status code.
178 179 180 181 |
# File 'lib/gin/controller.rb', line 178 def status code=nil @response.status = code if code @response.status end |
#stream(keep_open = false, &block) ⇒ Object
Assigns a Gin::Stream to the response body, which is yielded to the block. The block execution is delayed until the action returns.
stream do |io|
file = File.open "somefile", "rb"
io << file.read(1024) until file.eof?
file.close
end
324 325 326 327 |
# File 'lib/gin/controller.rb', line 324 def stream keep_open=false, &block scheduler = env[ASYNC_CALLBACK] ? EventMachine : Gin::Stream body Gin::Stream.new(scheduler, keep_open){ |out| yield(out) } end |
#template_path(template, is_layout = false) ⇒ Object
Returns the path to where the template is expected to be.
template_path :foo
#=> "<views_dir>/foo"
template_path "sub/foo"
#=> "<views_dir>/sub/foo"
template_path "sub/foo", :layout
#=> "<layouts_dir>/sub/foo"
template_path "/other/foo"
#=> "<root_dir>/other/foo"
645 646 647 648 649 650 651 652 653 654 655 656 657 |
# File 'lib/gin/controller.rb', line 645 def template_path template, is_layout=false dir = if template[0] == ?/ @app.root_dir elsif is_layout @app.layouts_dir else @app.views_dir end path = File.join(dir, template.to_s) path.gsub!('*', controller_name) File.(path) end |
#url_to(*args) ⇒ Object Also known as: to
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 |
# File 'lib/gin/controller.rb', line 431 def url_to *args path = path_to(*args) return path if path =~ /\A[A-z][A-z0-9\+\.\-]*:/ uri = [host = ""] host << "http#{'s' if @request.ssl?}://" if @request.forwarded? || @request.port != (@request.ssl? ? 443 : 80) host << @request.host_with_port else host << @request.host end uri << @request.script_name.to_s uri << path File.join uri end |
#view(template, opts = {}, &block) ⇒ Object
Render a template with the given view template. Options supported:
- :locals
-
Hash - local variables used in template
- :layout
-
Symbol/String - a custom layout to use
- :scope
-
Object - The scope in which to render the template: default self
- :content_type
-
Symbol/String - Content-Type header to set
- :engine
-
String - Tilt rendering engine to use
- :layout_engine
-
String - Tilt layout rendering engine to use
The template argument may be a String or a Symbol. By default the template location will be looked for under Gin::App.views_dir, but the directory may be specified as any directory under Gin::App.root_dir by using the ‘/’ prefix:
view 'foo/template'
#=> Renders file "<views_dir>/foo/template"
view '/foo/template'
#=> Renders file "<root_dir>/foo/template"
# Render without layout
view 'foo/template', layout: false
684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 |
# File 'lib/gin/controller.rb', line 684 def view template, opts={}, &block content_type(opts.delete(:content_type)) if opts[:content_type] scope = opts[:scope] || self locals = opts[:locals] || {} template = template_path(template) v_template = @app.template_for template, opts[:engine] raise Gin::TemplateMissing, "No such template `#{template}'" unless v_template if opts[:layout] != false r_layout = template_path((opts[:layout] || layout), true) r_template = @app.template_for r_layout, opts[:layout_engine] if r_layout end if !@response[CNT_TYPE] mime_type = v_template.class.default_mime_type || r_template && r_template.class.default_mime_type content_type(mime_type) if mime_type end @env[GIN_TEMPLATES] ||= [] if r_template @env[GIN_TEMPLATES] << r_template.file << v_template.file r_template.render(scope, locals){ v_template.render(scope, locals, &block) } else @env[GIN_TEMPLATES] << v_template.file v_template.render(scope, locals, &block) end end |