Module: Merb::ControllerMixin

Included in:
Controller
Defined in:
merb-core/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.



307
308
309
# File 'merb-core/lib/merb-core/controller/mixins/controller.rb', line 307

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

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

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



318
319
320
# File 'merb-core/lib/merb-core/controller/mixins/controller.rb', line 318

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

#messageObject

Retreives the redirect message either locally or from the request.



149
150
151
# File 'merb-core/lib/merb-core/controller/mixins/controller.rb', line 149

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

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

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

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

For more information, see:



274
275
276
277
278
279
280
281
282
# File 'merb-core/lib/merb-core/controller/mixins/controller.rb', line 274

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 = {}) ⇒ String

Returns Explanation of redirect.

Examples:

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

Options Hash (opts):

  • :message (Hash) — default: nil

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

  • :permanent (Boolean) — default: false

    When true, return status 301 Moved Permanently

  • :notice (String)

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

  • :error (String)

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

  • :success (String)

    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.



131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'merb-core/lib/merb-core/controller/mixins/controller.rb', line 131

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.

Examples:

def stream
  prefix = '<p>'
  suffix = "</p>\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


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

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) ⇒ Proc

Returns A block that the server can call later, allowing Merb to release the thread lock and render another request.



79
80
81
82
83
# File 'merb-core/lib/merb-core/controller/mixins/controller.rb', line 79

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

#render_then_call(str, &blk) ⇒ Proc

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



96
97
98
99
100
101
# File 'merb-core/lib/merb-core/controller/mixins/controller.rb', line 96

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

#run_later(&blk) ⇒ Object

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

Examples:

run_later do
  SomeBackgroundTask.run
end


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

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.



66
67
68
69
70
# File 'merb-core/lib/merb-core/controller/mixins/controller.rb', line 66

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 = {}) ⇒ String

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.

Options Hash (opts):

  • :disposition (String) — default: "attachment"

    The disposition of the file send.

  • :filename (String)

    The name to use for the file.

  • :type (String)

    The content type.



204
205
206
207
208
209
210
211
212
213
214
# File 'merb-core/lib/merb-core/controller/mixins/controller.rb', line 204

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 = {}) ⇒ IO

TODO:

Docs, correctness: is the return type correct?

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.

Options Hash (opts):

  • :disposition (String) — default: "attachment"

    The disposition of the file send.

  • :filename (String) — default: File.basename(file)

    The name to use for the file.

  • :type (String)

    The content type.



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'merb-core/lib/merb-core/controller/mixins/controller.rb', line 169

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.



294
295
296
297
# File 'merb-core/lib/merb-core/controller/mixins/controller.rb', line 294

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.

Examples:

Use with Amazon S3:

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

Options Hash (opts):

  • :disposition (String) — default: "attachment"

    The disposition of the file send.

  • :type (String)

    The content type.

  • :content_length (Numeric)

    The length of the content to send.

  • :filename (String)

    The name to use for the streamed file.



239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'merb-core/lib/merb-core/controller/mixins/controller.rb', line 239

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