Module: Merb::ControllerMixin

Included in:
Controller
Defined in:
lib/merb-core/controller/mixins/controller.rb

Overview

Module that is mixed in to all implemented controllers.

Instance Method Summary collapse

Instance Method Details

Marks a cookie as deleted and gives it an expires stamp in the past. This method is used primarily internally in Merb.

Use the cookies hash to manipulate cookies instead.

Parameters

name<~to_s>

A name for the cookie to delete.

:api: public



328
329
330
# File 'lib/merb-core/controller/mixins/controller.rb', line 328

def delete_cookie(name)
  set_cookie(name, nil, Merb::Const::COOKIE_EXPIRED_TIME)
end

#escape_xml(obj) ⇒ Object Also known as: h, escape_html

Escapes the string representation of obj and escapes it for use in XML.

Parameter

obj<~to_s>

The object to escape for use in XML.

Returns

String

The escaped object.

:api: public



341
342
343
# File 'lib/merb-core/controller/mixins/controller.rb', line 341

def escape_xml(obj)
  Merb::Parse.escape_xml(obj.to_s)
end

#messageObject

Retreives the redirect message either locally or from the request.

:api: public



161
162
163
# File 'lib/merb-core/controller/mixins/controller.rb', line 161

def message
  @_message = defined?(@_message) ? @_message : request.message
end

#nginx_send_file(path, content_type = "") ⇒ Object

Uses the nginx specific X-Accel-Redirect header to send a file directly from nginx.

Notes

Unless Content-Disposition is set before calling this method, it is set to attachment with streamed file name.

For more information, see the nginx wiki: http://wiki.codemongers.com/NginxXSendfile

and the following sample gist: http://gist.github.com/11225

there's also example application up on GitHub:

http://github.com/michaelklishin/nginx-x-accel-redirect-example-application/tree/master

Parameters

path

Path to file to send to the client.

content_type

content type header value. By default is set to empty string to let Nginx detect it.

Return

String

precisely a single space.

:api: public



294
295
296
297
298
299
300
301
302
# File 'lib/merb-core/controller/mixins/controller.rb', line 294

def nginx_send_file(path, content_type = "")
  # Let Nginx detect content type unless it is explicitly set
  headers['Content-Type']        = content_type
  headers["Content-Disposition"] ||= "attachment; filename=#{path.split('/').last}"
  
  headers['X-Accel-Redirect']    = path
  
  return ' '
end

#redirect(url, opts = {}) ⇒ Object

Parameters

url

URL to redirect to. It can be either a relative or fully-qualified URL.

opts

An options hash (see below)

Options (opts)

:message::

Messages to pass in url query string as value for "_message"

:permanent::

When true, return status 301 Moved Permanently

:notice::

Shorthand for common usage :message => {:notice => "..."}

:error::

Shorthand for common usage :message => {:error => "..."}

:success::

Shorthand for common usage :message => {:success => "..."}

:status<String, Symbol>::

Status code to set for the response. Can be any valid redirect
status. Has precedence over the :permanent parameter, which is
retained for convenience.

Returns

String

Explanation of redirect.

Examples

redirect("/posts/34") redirect("/posts/34", :message => { :notice => 'Post updated successfully!' }) redirect("http://www.merbivore.com/&quot;) redirect("http://www.merbivore.com/&quot;, :permanent => true) redirect("/posts/34", :notice => 'Post updated successfully!')

:api: public



143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/merb-core/controller/mixins/controller.rb', line 143

def redirect(url, opts = {})
  default_redirect_options = { :message => nil, :permanent => false }
  opts = default_redirect_options.merge(opts)

  url = handle_redirect_messages(url,opts)

  _status   = opts[:status] if opts[:status]
  _status ||= opts[:permanent] ? 301 : 302
  self.status = _status

  Merb.logger.info("Redirecting to: #{url} (#{self.status})")
  headers['Location'] = url
  "<html><body>You are being <a href=\"#{url}\">redirected</a>.</body></html>"
end

#render_chunked(&blk) ⇒ Object

Renders the block given as a parameter using chunked encoding.

Parameters

&blk

A block that, when called, will use send_chunks to send chunks of data down to the server. The chunking will terminate once the block returns.

Examples

def stream prefix = '

' suffix = "

\r\n" render_chunked do IO.popen("cat /tmp/test.log") do |io| done = false until done sleep 0.3 line = io.gets.chomp

      if line == 'EOF'
        done = true
      else
        send_chunk(prefix + line + suffix)
      end
    end
  end
end
end

:api: public



50
51
52
53
54
55
56
57
58
59
60
# File 'lib/merb-core/controller/mixins/controller.rb', line 50

def render_chunked(&blk)
  must_support_streaming!
  headers['Transfer-Encoding'] = 'chunked'
  Proc.new { |response|
    @response = response
    response.send_status_no_connection_close('')
    response.send_header
    blk.call
    response.write("0\r\n\r\n")
  }
end

#render_deferred(&blk) ⇒ Object

Parameters

&blk

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



86
87
88
89
90
# File 'lib/merb-core/controller/mixins/controller.rb', line 86

def render_deferred(&blk)
  Proc.new do |response|
    response.write(blk.call)
  end
end

#render_then_call(str, &blk) ⇒ Object

Renders the passed in string, then calls the block outside the mutex and after the string has been returned to the client.

Parameters

str

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



104
105
106
107
108
109
# File 'lib/merb-core/controller/mixins/controller.rb', line 104

def render_then_call(str, &blk)
  Proc.new do |response|
    response.write(str)
    blk.call
  end
end

#run_later(&blk) ⇒ Object

Enqueu a block to run in a background thread outside of the request response dispatch

Parameters

&blk

proc to run later

Example

run_later do SomeBackgroundTask.run end

:api: public



17
18
19
# File 'lib/merb-core/controller/mixins/controller.rb', line 17

def run_later(&blk)
  Merb.run_later(&blk)
end

#send_chunk(data) ⇒ Object

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

a chunk of data to return.

:api: public



69
70
71
72
73
# File 'lib/merb-core/controller/mixins/controller.rb', line 69

def send_chunk(data)
  only_runs_on_mongrel!
  @response.write('%x' % data.size + "\r\n")
  @response.write(data + "\r\n")
end

#send_data(data, opts = {}) ⇒ Object

Send 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

Path to file to send to the client.

opts

Options for sending the data (see below).

Options (opts)

:disposition::

The disposition of the file send. Defaults to "attachment".

:filename::

The name to use for the file. Defaults to the filename of file.

:type:: The content type.

:api: public



216
217
218
219
220
221
222
223
224
225
226
# File 'lib/merb-core/controller/mixins/controller.rb', line 216

def send_data(data, opts={})
  opts.update(Merb::Const::DEFAULT_SEND_FILE_OPTIONS.merge(opts))
  disposition = opts[:disposition].dup || 'attachment'
  disposition << %(; filename="#{opts[:filename]}") if opts[:filename]
  headers.update(
    'Content-Type'              => opts[:type].strip,  # fixes a problem with extra '\r' with some browsers
    'Content-Disposition'       => disposition,
    'Content-Transfer-Encoding' => 'binary'
  )
  data
end

#send_file(file, opts = {}) ⇒ Object

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

Path to file to send to the client.

opts

Options for sending the file (see below).

Options (opts)

:disposition::

The disposition of the file send. Defaults to "attachment".

:filename::

The name to use for the file. Defaults to the filename of file.

:type:: The content type.

Returns

IO

An I/O stream for the file.

:api: public



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/merb-core/controller/mixins/controller.rb', line 183

def send_file(file, opts={})
  opts.update(Merb::Const::DEFAULT_SEND_FILE_OPTIONS.merge(opts))
  disposition = opts[:disposition].dup || 'attachment'
  disposition << %(; filename="#{opts[:filename] ? opts[:filename] : File.basename(file)}")
  headers.update(
    'Content-Type'              => opts[:type].strip,  # fixes a problem with extra '\r' with some browsers
    'Content-Disposition'       => disposition,
    'Content-Transfer-Encoding' => 'binary'
  )
  Proc.new do |response|
    file = File.open(file, 'rb')
    while chunk = file.read(16384)
      response.write chunk
    end
    file.close
  end
end

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.

:api: public



314
315
316
317
# File 'lib/merb-core/controller/mixins/controller.rb', line 314

def set_cookie(name, value, expires)
  options = expires.is_a?(Hash) ? expires : {:expires => expires}
  cookies.set_cookie(name, value, options)
end

#stream_file(opts = {}, &stream) ⇒ Object

Streams a file over HTTP.

Parameters

opts

Options for the file streaming (see below).

&stream

A block that, when called, will return an object that responds to get_lines for streaming.

Options

:disposition::

The disposition of the file send. Defaults to "attachment".

:type:: The content type. :content_length:: The length of the content to send. :filename:: The name to use for the streamed file.

Examples

stream_file({ :filename => file_name, :type => content_type, :content_length => content_length }) do |response| AWS::S3::S3Object.stream(user.folder_name + "-" + user_file.unique_id, bucket_name) do |chunk| response.write chunk end end

:api: public



252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/merb-core/controller/mixins/controller.rb', line 252

def stream_file(opts={}, &stream)
  opts.update(Merb::Const::DEFAULT_SEND_FILE_OPTIONS.merge(opts))
  disposition = opts[:disposition].dup || 'attachment'
  disposition << %(; filename="#{opts[:filename]}")
  headers.update(
    'Content-Type'              => opts[:type].strip,  # fixes a problem with extra '\r' with some browsers
    'Content-Disposition'       => disposition,
    'Content-Transfer-Encoding' => 'binary',
    # Rack specification requires header values to respond to :each
    'CONTENT-LENGTH'            => opts[:content_length].to_s
  )
  Proc.new do |response|
    stream.call(response)
  end
end