浏览 1665 次
|
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
|---|---|
| 作者 | 正文 |
|
时间:2007-06-27 关键字: ActionController mime_responds 源码
Rails从HTTP Accept header得到客户端需要的response format信息
默认的MIME types见mime_type.rb: ALL = Type.new "*/*", :all TEXT = Type.new "text/plain", :text HTML = Type.new "text/html", :html, %w( application/xhtml+xml ) JS = Type.new "text/javascript", :js, %w( application/javascript application/x-javascript ) ICS = Type.new "text/calendar", :ics CSV = Type.new "text/csv", :csv XML = Type.new "application/xml", :xml, %w( text/xml application/x-xml ) RSS = Type.new "application/rss+xml", :rss ATOM = Type.new "application/atom+xml", :atom YAML = Type.new "application/x-yaml", :yaml, %w( text/yaml ) JSON = Type.new "application/json", :json, %w( text/x-json ) SET = [ ALL, TEXT, HTML, JS, ICS, XML, RSS, ATOM, YAML, JSON ] def register(string, symbol, synonyms = []) Mime.send :const_set, symbol.to_s.upcase, Type.new(string, symbol, synonyms) SET << Mime.send(:const_get, symbol.to_s.upcase) LOOKUP[string] = EXTENSION_LOOKUP[symbol.to_s] = SET.last end 我们可以在environment.rb里注册自己的MIME type: Mime::Type.register "image/jpg", :jpg 看看源码mime_responds.rb:
module ActionController
module MimeResponds
def self.included(base)
base.send(:include, ActionController::MimeResponds::InstanceMethods)
end
module InstanceMethods
def respond_to(*types, &block)
raise ArgumentError, "respond_to takes either types or a block, never both" unless types.any? ^ block
block ||= lambda { |responder| types.each { |type| responder.send(type) } }
responder = Responder.new(block.binding)
block.call(responder)
responder.respond
end
end
class Responder
def initialize(block_binding)
@block_binding = block_binding
@mime_type_priority = eval(
"(params[:format] && Mime::EXTENSION_LOOKUP[params[:format]]) ? " +
"[ Mime::EXTENSION_LOOKUP[params[:format]] ] : request.accepts",
block_binding
)
@order = []
@responses = {}
end
def custom(mime_type, &block)
mime_type = mime_type.is_a?(Mime::Type) ? mime_type : Mime::Type.lookup(mime_type.to_s)
@order << mime_type
if block_given?
@responses[mime_type] = Proc.new do
eval "response.content_type = '#{mime_type.to_s}'", @block_binding
block.call
end
else
if source = DEFAULT_BLOCKS[mime_type.to_sym]
@responses[mime_type] = eval(source, @block_binding)
else
raise ActionController::RenderError, "Expected a block but none was given for custom mime handler #{mime_type}"
end
end
end
def method_missing(symbol, &block)
mime_constant = symbol.to_s.upcase
if Mime::SET.include?(Mime.const_get(mime_constant))
custom(Mime.const_get(mime_constant), &block)
else
super
end
end
def respond
for priority in @mime_type_priority
if priority == Mime::ALL
@responses[@order.first].call
return
else
if priority === @order
@responses[priority].call
return
end
end
end
if @order.include?(Mime::ALL)
@responses[Mime::ALL].call
else
eval 'render(:nothing => true, :status => "406 Not Acceptable")', @block_binding
end
end
end
end
end
我们看到,respond_to方法调用responder.send(type),如format.js,但是Responder类没有js方法,所以调用了method_missing方法 method_missing调用了custom方法,custom则eval了response.content_type的设置,然后block.call 最后调用responder.respond,@responses[priority].call调用了content_type的设置以及参数给的block 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
时间:2007-06-27
代码太多了,看得头大,很想问问hideto,怎么样在controller里面取得view里面的内容呢,比如def a end
对应view里面a.rhtml,在a里面要怎么样取到a.rhtml的生成后的html内容 |
|
| 返回顶楼 | |
|
时间:2007-06-27
yNoooo 写道 代码太多了,看得头大,很想问问hideto,怎么样在controller里面取得view里面的内容呢,比如def a end
对应view里面a.rhtml,在a里面要怎么样取到a.rhtml的生成后的html内容 render_to_string |
|
| 返回顶楼 | |
|
时间:2007-06-27
太帅了,谢谢gigix
|
|
| 返回顶楼 | |







