- 浏览: 1247154 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (729)
- Java_about (144)
- Spring_Hibernate_Struts_OpenSource (27)
- linux_unix (62)
- life_sth (21)
- js_css_html_xml_nodejs (69)
- design_pattens (1)
- Perl (8)
- php_ecshop (4)
- DB_Mysql_Oracle_Informix_SqlServer (43)
- JSTL (8)
- Testing_自动化测试 (42)
- DB_ID_UUID (4)
- SEM_SEO (1)
- english_study_improvement (4)
- SVN_Git (9)
- WebService_SOA_CloudComputing (3)
- E-Commerce (1)
- Lucene_Solr (7)
- others (2)
- Regex (2)
- tomcat_jetty (8)
- zeroc-ice (1)
- java_excel (5)
- ant_maven_gradle (5)
- Unity_VR_AR_C# (2)
- jmeter (1)
- XPath_dom4j (1)
- Ruby_and_Rails (68)
- write_a_rails (17)
- manage_and_team (1)
- getting_real (1)
- ubuntu (20)
- git_and_git_flow (7)
- TODO (1)
- PM_design (2)
- Python_and_Django (8)
- NoSql_mongo_redis (24)
- C/C++ (3)
- vi_vim_gvim (0)
- c#_.Net_windows编程_dll (10)
- Php_and_Yii (9)
- Android_IOS (31)
- Mysql (5)
- sa_运维_network_硬件 (37)
- lua (2)
- c_cpp_VisualStudio (21)
- 硬件-RM-Arduino (6)
最新评论
-
shenkun58:
...
NoClassDefFoundError: Could not initialize springframework.BeanCreationException -
liaojia1:
正解,感谢
NoClassDefFoundError: Could not initialize springframework.BeanCreationException -
flingfox63:
谢谢分享,电脑上有IPV6,导致了Guard启动不了……
ruby错误解决: Address family not supported by protocol - connect(2) -
c39274936:
s = "hello_world_ruby" ...
驼峰格式和下划线格式转换_translation between camel and snake format -
yfj300:
学习了学习了学习了学习了
硬盘基本知识(磁道、扇区、柱面、磁头数、簇、MBR、DBR)
Rails源码阅读(八)ActionController::Base_用户请求在rails中的处理流程(3)
执行流程从路由找到真正要执行的XXXController后,会执行super方法,即ActionController::Base.process方法
class << self # ActionController::Base.process代码: # Factory for the standard create, process loop where the controller is discarded after processing. def process(request, response) #:nodoc: new.process(request, response) end end
这个方法的细微之处在于:new.process
new是去新建一个当前Controller的实例,之后执行这个实例的process方法。
这里有个重要的结论:每个请求都会new一个Controller的实例。这个结论将实质上影响以后的设计和扩展。
例如,每个请求的action中的实例变量,只在当前请求中存在,多个请求不会存在实例变量共享的问题。
对于熟练java人,尤其要注意这一点,与servlet的多线程区别很大。
XXXController的实例方法以及详细分析:
# Extracts the action_name from the request parameters and performs that action. def process(request, response, method = :perform_action, *arguments) #:nodoc: response.request = request #在response里可以直接使用request initialize_template_class(response) #初始化模板相关信息,后面会详细看 assign_shortcuts(request, response) #定义了很多实例变量,作用就是shotcuts了 initialize_current_url #一句内容:@url = UrlRewriter.new(request, params.clone) assign_names #@action_name = (params['action'] || 'index') #应该叫assign_action_name log_processing #记日志 send(method, *arguments) #执行实例的perform_action方法,后面详细看 send_response #返回结果,下面会详细看 ensure process_cleanup end
# 初始化模板相关信息
def initialize_template_class(response) response.template = ActionView::Base.new(self.class.view_paths, {}, self) response.template.helpers.send :include, self.class.master_helper_module response.redirected_to = nil @performed_render = @performed_redirect = false end
这里也是用到了ActionController::Response的方法,这个好理解,因为response的主要任务就是组装字符串。
response初始化的template是个ActionView::Base的实例,到这里就与ActionView联系起来了。
response.template.helpers.send :include, self.class.master_helper_module
这里???暂时没有找到??? 猜测是把controller里用helper声明的方法加入了helpers里[补充:这个的确如猜测的一样,详细以后再分析,代码在action_controller/helpers.rb里。这个master_helper_module是虚拟出来的中间代理对象,目的就是把很多方法放入其中,之后再混入view的helper中,以使得这些方法在view中直接使用]
# shorcuts
def assign_shortcuts(request, response) @_request, @_params = request, request.parameters @_response = response @_response.session = request.session @_session = @_response.session @template = @_response.template @_headers = @_response.headers end
这里就是为了简单使用,把一些常用量放在了实例变量里。
好处:好用,而不需要每次都xxx.yyy.zzz,直接用@zzz就好了
坏处:几乎没有,因为每次请求都new一个controller,用完就回收了
# 进入action的执行
经过了这么长的流程,终于到了执行action了,即执行perform_action
def perform_action if action_methods.include?(action_name) send(action_name) default_render unless performed? elsif respond_to? :method_missing method_missing action_name default_render unless performed? else begin default_render rescue ActionView::MissingTemplate => e # Was the implicit template missing, or was it another template? if e.path == default_template_name raise UnknownAction, "No action responded to #{action_name}. Actions: #{action_methods.sort.to_sentence(:locale => :en)}", caller else raise e end end end end
这么长的代码,大部分都在处理特殊情况。
真正的核心是找到action,执行action,执行action时,我们有时候写render,有时候不写。
如果不写,则调用default_render(从if条件可以推测,render中一定会设置这个实例变量的)
#代码很短,直接交给了render去处理所有情况。
#这也挺好的,最怕的是有很多特例,写在很多地方,改的人就入雷区了。
def default_render #:nodoc: render end
# render的代码真长,做的事情也很复杂,看看注释也这么长
主要做的事请,生成要response的body,即生成字符串:
a:找到layout
一般就用默认的了;
可以直接传递layout参数,比如传false就可以不用layout了,等
b:根据render的参数不同,调用不同的view
比如json格式,xml格式,等
c:erb渲染
简单来说是:@template.render()
@template是ActionView::Base的实例
d:其他的细节,暂略作下回分析
归纳一下Controller里面render做的事情:不论是直接返回(例如:text),还是调用View的render来返回erb页面的结果,最终得到的都是text,把这个text字符串存入body。body在response的时候给客户端看。
代码:
def render_for_text(text = nil, status = nil, append_response = false) #略一部分 if append_response response.body ||= '' response.body << text.to_s #就是这里! else response.body = case text #这里 when Proc then text when nil then " " # Safari doesn't pass the headers of the return if the response is zero length else text.to_s end end end
# 返回结果用send_response
#send_response的代码
def send_response response.prepare! response end
(1):这里的细节,需要去看ActionController::Response的代码,大致的是在设置response的控制信息,例如语言,编码,类型,cookie等。
#大致的工作都是在设置response的控制信息,例如语言,编码,类型,cookie等
def prepare! assign_default_content_type_and_charset! handle_conditional_get! set_content_length! convert_content_type! convert_language! convert_cookies! end
(2):send_response的返回结果就是response本身,这个好像不符合Rack的标准返回结果是:
[200, {"Content-Type" => "text/html"}, "Hello Rack!"]
回到请求的入口处:app.call(env).to_a
从这里应该推测出,response应该有to_a方法,返回符合rack标准的接口。
找了找Response里没有,应该去看看其super-class,果然是:
class Response < Rack::Response
在Rack::Response中定义了to_a方法,代码如下:
def finish(&block) @block = block if [204, 304].include?(status.to_i) header.delete "Content-Type" [status.to_i, header.to_hash, []] else [status.to_i, header.to_hash, self] end end alias to_a finish # For *response
# render_to_string的介绍
直接使用render方法,render的返回值即response.body
但是在controller里直接得到body,有些麻烦:必须确保显式调用了render之后才可以
如何解决,用的方法是先调用render,之后清除render的残留物:render完成标志+body值+assigns的值+等【思考下这里:这个方法提前知道来render做了哪些改变当前环境的事情,设计的不好!】
# Renders according to the same rules as <tt>render</tt>, but returns the result in a string instead # of sending it as the response body to the browser. def render_to_string(options = nil, &block) #:doc: render(options, &block) ensure response.content_type = nil erase_render_results reset_variables_added_to_assigns end
这个方法很好用,尤其是在处理js和ajax 的时候,不再需要在controller里面写太多拼凑字符串了,直接用erb模板,就如同写view一样;再例如,需要动态的定制页面生成等给编辑使用,这个时候手写erb不划算。
总结:
#1 介绍了XXXController的process方法做了哪些操作以及涉及到的步骤:
new一个当前Controller的实例,调用实例的process方法,
process执行perform_action方法,
perform_action用反射(action名字是路由来的)调用了当前实例的action方法(我们真正编码实现的地方)
之后render,也就是根据页面的得到字符串,状态等信息,response给http的用户
#2 erb页面内容的生成是由@template.render做的。@template是ActionView::Base的实例
这里调用的接力棒到了action_view里
====结束====
=== ===
== ==
= =
| |
发表评论
-
Rails外如何启动rails的类自动加载_activates autoloading using ActiveSupport 3.x
2016-06-22 12:08 548The following cod ... -
Rails源码阅读(13)rails中的autoload和ruby的autoload
2014-07-30 17:13 1850Rails源码阅读(13)rails中的autoload和 ... -
Rails源码阅读(12)叫Rails的模块module_Rails常量使用
2014-07-02 09:35 981The module nams "Rail ... -
Rails源码阅读(11)Rails使用bundle保持多机器环境gem版本的一致性
2013-09-05 19:21 1385Rails源码阅读(11)Rails使用bundle ... -
Rails源码阅读(十)在console 使用ActionController::Integration::Session
2012-05-05 14:48 1698Rails源码阅读(十)在console 使用Actio ... -
Rails源码阅读(九)ActionView::Base_用户请求在rails中的处理流程(4)
2012-04-08 18:19 2125Rails源码阅读(九)ActionView::Base_用户 ... -
Rails源码阅读(七)ActionController::Dispatcher_用户请求在rails中的处理流程(2)
2012-04-06 22:25 1295Rails源码阅读(七)Actio ... -
动手写rails(二)Rails_Ruby_ERB使用_模板_定制
2012-04-07 20:46 2481动手写rails(二)Rails_Ruby_ERB使用_模板_ ... -
Rails源码阅读(六)ActionController::Dispatcher_用户请求在rails中的处理流程(1)
2012-03-28 00:17 1635Rails源码阅读(六)ActionController::D ... -
Rails源码阅读(零)_config/boot
2012-03-15 11:56 1710不论是script/console 还是 script/ser ... -
动手写rails(一)_Rack标准和HttpServer之WEBrick
2012-03-15 07:22 2018无论如何,最终的结果是要启动一个server来接受请求, ... -
Rails源码阅读(五)with_scope 和 named_scope
2012-02-02 15:24 1359Rails源码阅读(四)with_scope and name ... -
Rails源码阅读(四)gem_rubygems之require_Rails_require_深入理解(一)
2011-11-16 10:39 2053Rails源码阅读(四)rubygems之require_Ra ... -
Rails源码阅读(三)Rails::Initializer
2011-10-14 10:58 2099启动的落脚点 不论启动console还是启动serve ... -
Rails源码阅读(二)_script/server
2011-09-17 18:51 1384Rails源码阅读(二)_script/server ... -
Rails源码阅读(一)_script/console
2011-09-05 11:13 2081Rails源码阅读_script/console启动 ...
相关推荐
Rails::API 是 Rails 的精简版本,针对不需要使用完整 Rails 功能的开发者。 Rails::API 移除了 ActionView 和其他一些渲染功能,不关心Web前端的开发者可更容易、快速地开发应用程序,因此运行速度比正常的 Rails ...
For-Rails-Beginners::Japanese_symbol_for_beginner:Ruby on Rails的初学者有福了
ActionController :: Base token_authentication_for :user_account end 辅助方法 检查用户是否已登录并获取当前已登录用户,可以使用以下类似 Devise 的帮助程序: user_account_signed_in? current_user_...
基本CSS框架base_css-rails是一个将添加到应用程序的资产管道的瑰宝安装将此行添加到您的应用程序的Gemfile中: gem 'base_css-rails'然后执行: $ bundle或将其自己安装为: $ gem install base_css-rails用法使用...
对Rails的扩展,以允许使用绕道而行,返回简单的工作流浏览器导航。 特征 将您的“ link_to”行切换为“ detour_to”,并将您的控制器“ redirect_to”切换为“ back_or_redirect_to”,以允许用户从其来访者返回。 ...
延迟加载整个血腥路由,因此应用程序可以快速启动:sign_of_the_horns:route_lazy_routes route_lazy_routes是一个邪恶的Rails插件,它延迟加载整个血腥路由,直到服务器获得第一个请求,因此应用程序可以旋转快起来...
在您的config/initializers/rails_admin.rb初始化程序中添加配置: RailsAdmin . config do | config | config . model Post do list do sort_by :position # Add Default sorting sort_reverse false # sort p
注意,该宝石适用于Rails,其中ApplicationController继承了ActiveController :: Base。 ActiveController :: API对Rails应用程序的支持即将推出。 用法 运行Rails服务器或运行rspec并检查log/action_tracer.log 。...
语言引擎 language_engine 是一个用于语言的 rails 引擎: 控制器帮手视图和资产没有定义,因为我们认为每个人都想在... ActionController :: Base protect_from_forgery helper LanguageEngine :: Engine . helpers
Rails Admin枚举4 Rails Admin插件,用于正确查看Rails 4.1枚举 安装 gem 'rails_admin_enum4', github: 'sibext/rails_admin_enum4' bundle install 用法 通过生成器生成新模型: rails g model Sibext service:...
持续移动且不破坏事物 :factory: :building_construction: :construction: :construction_worker: 正在建设中-请稍后再回来!
主存储库已移至gitlab,所有新代码将在其中: 它的外观和感觉完全类似于但是使用了jQuery Nested Sortable和或而不是Nestable和Ancestry 。 与和awesome_nested_set一起使用。 奖励功能: 对带有rails_admin_...
允许您使用为Rails应用程序的前端供电。 是将前端工具像Ruby一样进行编程,纯属喜悦! :smiling_face_with_heart-eyes: 或在运行的检查。 产品特点 :high_voltage: :light_bulb: 即时服务器启动 :high_voltage: ...
在Rails应用程序的根目录中,运行: rails_best_practices . 或用于HTML输出: rails_best_practices -f html . 默认情况下,rails_best_practices将解析vendor , spec , test和features目录中的代码。 排除目录...
其余都是可选的) 更简单的提示修改(类似于你已经熟悉的默认提示) 无需担心配置(因为反正没有太多选择)安装宝石档案: gem 'awesome_rails_console' 在终端: bundlerails g awesome_rails_console:install # ...
自述文件 该自述文件通常会记录启动和运行应用程序所需的所有步骤。 您可能要讲的内容: Ruby版本 系统依赖 配置 数据库创建 数据库初始化 如何运行测试套件 服务(作业队列,缓存服务器,搜索引擎等) ...
它建立在Ruby的EventMachine库之上,主要用于处理一些大量的开放连接 (如Comet系统或streaming APIs),整个过程都使用event-driven I/O。 Cramp使用Rails 3.0的ActiveSupport 和 ActiveModel库, 它会显示两层用于...
Rails管理员状态机 主存储库已移至gitlab,所有新代码将在其中: 从rails_admin正确管理状态 允许从Rails Admin轻松地将state_machine事件发送到模型,包括对ActiveRecord \ Mongoid和自定义状态字段名称的支持以及...
这是从rails中提取的auto_link方法。 `auto_link`方法已从Rails 3.1版本的Rails中删除。 该宝石旨在弥合移民人群的鸿沟。 特点: 默认情况下,auto_link返回已清理的html_safe字符串。 可以通过将:sanitize选项...
使用Ruby on Rails中的Kickbox.io API验证电子邮件,如果Kickbox.io API由于任何原因失败,则退回到基本语法电子邮件验证 安装 将此行添加到您的应用程序的Gemfile中: gem 'kickbox_rails' 然后执行: $ bundle ...