原创作者: hideto
阅读:2059次
评论:0条
更新时间:2011-05-26
1,action_controller.rb:
和active_record.rb很类似,加载当前文件,加载activesupport,加载一坨一坨的组件
2,base.rb:
节选了部分代码,调用流程为process -> perform_action => action || method_missing || template || raise UnknownAction
其中需要注意的几点:
1,@@default_charset = "utf-8"
2,attr_internal的属性有request、params、response、session、headers
3,cattr_accessor的属性有default_charset、logger、consider_all_requests_local等
catter_accessor标识的是Class Attributes,见这篇BlogSo, cattr_accessor doesn’t work like it should?
catter_accessor方法的定义在active_support\core_ext\class\attribute_accessors.rb:
4,render方法的参数有:
1)nil -> render_file
2):text -> render_text
3):file -> render_file
4):template -> render_file
5):inline -> render_template
6):action -> render_action
7):xml -> render_xml
8):json -> render_json
9):partial -> render_partial || render_partial_collection
10):update -> render_javascript
11):noting -> render_text
5,redirect_to方法的参数有:
1)Hash -> redirect_to(url_for(options))
2)URL -> response.redirect(options)
3)String -> redirect_to(request.protocol + request.host_with_port + options)
4):back -> redirect_to(request.env["HTTP_REFERER"])
$:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__))) unless defined?(ActiveSupport) begin $:.unshift(File.dirname(__FILE__) + "/../../activesupport/lib") require 'active_support' rescue LoadError require 'rubygems' gem 'activesupport' end end require 'action_controller/base' require 'action_controller/deprecated_redirects' require 'action_controller/request' require 'action_controller/deprecated_request_methods' require 'action_controller/rescue' require 'action_controller/benchmarking' require 'action_controller/flash' require 'action_controller/filters' require 'action_controller/layout' require 'action_controller/deprecated_dependencies' require 'action_controller/mime_responds' require 'action_controller/pagination' require 'action_controller/scaffolding' require 'action_controller/helpers' require 'action_controller/cookies' require 'action_controller/cgi_process' require 'action_controller/caching' require 'action_controller/verification' require 'action_controller/streaming' require 'action_controller/session_management' require 'action_controller/components' require 'action_controller/macros/auto_complete' require 'action_controller/macros/in_place_editing' require 'action_view' ActionController::Base.template_class = ActionView::Base ActionController::Base.class_eval do include ActionController::Flash include ActionController::Filters include ActionController::Layout include ActionController::Benchmarking include ActionController::Rescue include ActionController::Dependencies include ActionController::MimeResponds include ActionController::Pagination include ActionController::Scaffolding include ActionController::Helpers include ActionController::Cookies include ActionController::Caching include ActionController::Verification include ActionController::Streaming include ActionController::SessionManagement include ActionController::Components include ActionController::Macros::AutoComplete include ActionController::Macros::InPlaceEditing end
和active_record.rb很类似,加载当前文件,加载activesupport,加载一坨一坨的组件
2,base.rb:
require 'action_controller/mime_type' require 'action_controller/request' require 'action_controller/response' require 'action_controller/routing' require 'action_controller/resources' require 'action_controller/url_rewriter' require 'action_controller/status_codes' require 'drb' require 'set' module ActionController class Base DEFAULT_RENDER_STATUS_CODE = "200 OK" include StatusCodes @@default_charset = "utf-8" cattr_accessor :default_charset class_inheritable_accessor :template_root cattr_accessor :logger attr_internal :request attr_internal :params attr_internal :response attr_internal :session attr_internal :headers attr_accessor :action_name class << self def controller_class_name @controller_class_name ||= name.demodulize end def controller_name @controller_name ||= controller_class_name.sub(/Controller$/, '').underscore end end public def process(request, response, method = :perform_action, *arguments) initialize_template_class(response) assign_shortcuts(request, response) initialize_current_url assign_names forget_variables_added_to_assigns log_processing send(method, *arguments) assign_default_content_type_and_charset response ensure process_cleanup end def url_for(options = {}, *parameters_for_method_reference) case options when String options when Symbol ActiveSupport::Deprecation.warn( "You called url_for(:#{options}), which is a deprecated API call. Instead you should use the named " + "route directly, like #{options}(). Using symbols and parameters with url_for will be removed from Rails 2.0.", caller ) send(options, *parameters_for_method_reference) when Hash @url.rewrite(rewrite_options(options)) end end def controller_class_name self.class.controller_class_name end def controller_name self.class.controller_name end def session_enabled? request.session_options && request.session_options[:disabled] != false end protected def render(options = nil, deprecated_status = nil, &block) raise DoubleRenderError, "Can only render or redirect once per action" if performed? if options.nil? return render_file(default_template_name, deprecated_status, true) else unless options.is_a?(Hash) if options == :update options = { :update => true } else ActiveSupport::Deprecation.warn( "You called render('#{options}'), which is a deprecated API call. Instead you use " + "render :file => #{options}. Calling render with just a string will be removed from Rails 2.0.", caller ) return render_file(options, deprecated_status, true) end end end if content_type = options[:content_type] response.content_type = content_type.to_s end if text = options[:text] render_text(text, options[:status]) else if file = options[:file] render_file(file, options[:status], options[:use_full_path], options[:locals] || {}) elsif template = options[:template] render_file(template, options[:status], true) elsif inline = options[:inline] render_template(inline, options[:status], options[:type], options[:locals] || {}) elsif action_name = options[:action] ActiveSupport::Deprecation.silence do render_action(action_name, options[:status], options[:layout]) end elsif xml = options[:xml] render_xml(xml, options[:status]) elsif json = options[:json] render_json(json, options[:callback], options[:status]) elsif partial = options[:partial] partial = default_template_name if partial == true if collection = options[:collection] render_partial_collection(partial, collection, options[:spacer_template], options[:locals], options[:status]) else render_partial(partial, ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals], options[:status]) end elsif options[:update] add_variables_to_assigns @template.send :evaluate_assigns generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(@template, &block) render_javascript(generator.to_s) elsif options[:nothing] render_text(" ", options[:status]) else render_file(default_template_name, options[:status], true) end end end def render_action(action_name, status = nil, with_layout = true) template = default_template_name(action_name.to_s) if with_layout && !template_exempt_from_layout?(template) render_with_layout(:file => template, :status => status, :use_full_path => true, :layout => true) else render_without_layout(:file => template, :status => status, :use_full_path => true) end end def render_file(template_path, status = nil, use_full_path = false, locals = {}) add_variables_to_assigns assert_existence_of_template_file(template_path) if use_full_path logger.info("Rendering #{template_path}" + (status ? " (#{status})" : '')) if logger render_text(@template.render_file(template_path, use_full_path, locals), status) end def render_template(template, status = nil, type = :rhtml, local_assigns = {}) add_variables_to_assigns render_text(@template.render_template(type, template, nil, local_assigns), status) end def render_text(text = nil, status = nil, append_response = false) @performed_render = true response.headers['Status'] = interpret_status(status || DEFAULT_RENDER_STATUS_CODE) if append_response response.body ||= '' response.body << text else response.body = text end end def render_javascript(javascript, status = nil, append_response = true) response.content_type = Mime::JS render_text(javascript, status, append_response) end def render_xml(xml, status = nil) response.content_type = Mime::XML render_text(xml, status) end def render_json(json, callback = nil, status = nil) json = "#{callback}(#{json})" unless callback.blank? response.content_type = Mime::JSON render_text(json, status) end def render_nothing(status = nil) render_text(' ', status) end def render_partial(partial_path = default_template_name, object = nil, local_assigns = nil, status = nil) add_variables_to_assigns render_text(@template.render_partial(partial_path, object, local_assigns), status) end def render_partial_collection(partial_name, collection, partial_spacer_template = nil, local_assigns = nil, status = nil) add_variables_to_assigns render_text(@template.render_partial_collection(partial_name, collection, partial_spacer_template, local_assigns), status) end def render_with_layout(template_name = default_template_name, status = nil, layout = nil) render_with_a_layout(template_name, status, layout) end def render_without_layout(template_name = default_template_name, status = nil) render_with_no_layout(template_name, status) end def head(*args) if args.length > 2 raise ArgumentError, "too many arguments to head" elsif args.empty? raise ArgumentError, "too few arguments to head" elsif args.length == 2 status = args.shift options = args.shift elsif args.first.is_a?(Hash) options = args.first else status = args.first options = {} end raise ArgumentError, "head requires an options hash" if !options.is_a?(Hash) status = interpret_status(status || options.delete(:status) || :ok) options.each do |key, value| headers[key.to_s.dasherize.split(/-/).map { |v| v.capitalize }.join("-")] = value.to_s end render :nothing => true, :status => status end def erase_render_results response.body = nil @performed_render = false end def erase_redirect_results @performed_redirect = false response.redirected_to = nil response.redirected_to_method_params = nil response.headers['Status'] = DEFAULT_RENDER_STATUS_CODE response.headers.delete('Location') end def erase_results erase_render_results erase_redirect_results end def redirect_to(options = {}, *parameters_for_method_reference) case options when %r{^\w+://.*} raise DoubleRenderError if performed? logger.info("Redirected to #{options}") if logger response.redirect(options) response.redirected_to = options @performed_redirect = true when String redirect_to(request.protocol + request.host_with_port + options) when :back request.env["HTTP_REFERER"] ? redirect_to(request.env["HTTP_REFERER"]) : raise(RedirectBackError) else if parameters_for_method_reference.empty? redirect_to(url_for(options)) response.redirected_to = options else redirect_to(url_for(options, *parameters_for_method_reference)) response.redirected_to, response.redirected_to_method_params = options, parameters_for_method_reference end end end def expires_in(seconds, options = {}) cache_options = { 'max-age' => seconds, 'private' => true }.symbolize_keys.merge!(options.symbolize_keys) cache_options.delete_if { |k,v| v.nil? or v == false } cache_control = cache_options.map{ |k,v| v == true ? k.to_s : "#{k.to_s}=#{v.to_s}"} response.headers["Cache-Control"] = cache_control.join(', ') end def expires_now response.headers["Cache-Control"] = "no-cache" end def reset_session request.reset_session @_session = request.session response.session = @_session end private def perform_action if self.class.action_methods.include?(action_name) send(action_name) render unless performed? elsif respond_to? :method_missing send(:method_missing, action_name) render unless performed? elsif template_exists? && template_public? render else raise UnknownAction, "No action responded to #{action_name}", caller end end end end
节选了部分代码,调用流程为process -> perform_action => action || method_missing || template || raise UnknownAction
其中需要注意的几点:
1,@@default_charset = "utf-8"
2,attr_internal的属性有request、params、response、session、headers
3,cattr_accessor的属性有default_charset、logger、consider_all_requests_local等
catter_accessor标识的是Class Attributes,见这篇BlogSo, cattr_accessor doesn’t work like it should?
catter_accessor方法的定义在active_support\core_ext\class\attribute_accessors.rb:
class Class def cattr_reader(*syms) syms.flatten.each do |sym| next if sym.is_a?(Hash) class_eval(<<-EOS, __FILE__, __LINE__) unless defined? @@#{sym} @@#{sym} = nil end def self.#{sym} @@#{sym} end def #{sym} @@#{sym} end EOS end end def cattr_writer(*syms) options = syms.last.is_a?(Hash) ? syms.pop : {} syms.flatten.each do |sym| class_eval(<<-EOS, __FILE__, __LINE__) unless defined? @@#{sym} @@#{sym} = nil end def self.#{sym}=(obj) @@#{sym} = obj end #{" def #{sym}=(obj) @@#{sym} = obj end " unless options[:instance_writer] == false } EOS end end def cattr_accessor(*syms) cattr_reader(*syms) cattr_writer(*syms) end end
4,render方法的参数有:
1)nil -> render_file
2):text -> render_text
3):file -> render_file
4):template -> render_file
5):inline -> render_template
6):action -> render_action
7):xml -> render_xml
8):json -> render_json
9):partial -> render_partial || render_partial_collection
10):update -> render_javascript
11):noting -> render_text
5,redirect_to方法的参数有:
1)Hash -> redirect_to(url_for(options))
redirect_to :action => "show", :id => 5
2)URL -> response.redirect(options)
redirect_to "http://www.rubyonrails.org"
3)String -> redirect_to(request.protocol + request.host_with_port + options)
redirect_to "/images/screenshot.jpg"
4):back -> redirect_to(request.env["HTTP_REFERER"])
redirect_to :back
评论 共 0 条 请登录后发表评论