rails activesupport通知 – 错误的db运行时值
我正在尝试记录我的REST API应用程序的请求。 我正在使用rails通知,例如http://railscasts.com/episodes/249-notifications-in-rails-3
我无法理解如何解决rails通知的一个问题。
我的初始化代码
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |name, start, finish, id, payload| p name p start p finish p id p payload end Controller respond section class PostsController < ApplicationController # GET /posts # GET /posts.json respond_to :json, :html .... end
控制器创建动作
def create @post = Post.new(params[:post]) @post.save! respond_with(@post, :location => nil) end
控制台输出
"process_action.action_controller" 2013-02-02 20:13:11 +0200 2013-02-02 20:13:11 +0200 "951b8999e9b71d4a8949" {:controller=>"PostsController", :action=>"create", :params=>{"utf8"=>"✓", "authenticity_token"=>"1WugY9gh6ZCRXjfBTuckye3c9XDvtCqMQ2JdBpCo88s=", "post"=>{"name"=>"post3", "title"=>"post3", "content"=>"post3"}, "commit"=>"Create Post", "action"=>"create", "controller"=>"posts"}, :format=>:html, :method=>"POST", :path=>"/posts", :status=>302, :view_runtime=>nil, :db_runtime=>0}
如您所见:db_runtime => 0
但是,如果我将控制器操作代码更改为默认支架
def create @post = Post.new(params[:post]) #@post.save! #respond_with(@post) respond_to do |format| if @post.save format.html { redirect_to @post, notice: 'Post was successfully created.' } format.json { render json: @post, status: :created, location: @post } else format.html { render action: "new" } format.json { render json: @post.errors, status: :unprocessable_entity } end end end
我可以看到
"process_action.action_controller" 2013-02-02 20:22:51 +0200 2013-02-02 20:22:51 +0200 "bf2a3173c08a0fd9008e" {:controller=>"PostsController", :action=>"create", :params=>{"utf8"=>"✓", "authenticity_token"=>"1WugY9gh6ZCRXjfBTuckye3c9XDvtCqMQ2JdBpCo88s=", "post"=>{"name"=>"post3", "title"=>"post3", "content"=>"post3"}, "commit"=>"Create Post", "action"=>"create", "controller"=>"posts"}, :format=>:html, :method=>"POST", :path=>"/posts", :status=>302, :view_runtime=>nil, :db_runtime=>4.727}
:db_runtime => 4.727
这是什么原因以及我如何解决它以使其在第一个例子中起作用? 谢谢 !
UPD
bundle show rails /Users/admin/.rvm/gems/ruby-1.9.3-p125/gems/rails-3.2.11 rvm current ruby-1.9.3-p125
UPD2
当我使用respond_with时,它似乎不起作用! 有人可以告诉我为什么吗? 谢谢
好吧,这似乎是一个bug。 让我们看看,发生了什么:
首先,我们有控制器动作的AR railtie及其使用cleanup_view_runtime钩子设置db_runtime的实现
def cleanup_view_runtime if ActiveRecord::Base.connected? db_rt_before_render = ActiveRecord::LogSubscriber.reset_runtime runtime = super db_rt_after_render = ActiveRecord::LogSubscriber.reset_runtime self.db_runtime = db_rt_before_render + db_rt_after_render runtime - db_rt_after_render else super end end
应用程序调用控制器操作 – >执行某些数据库查询并呈现一些内容 – >在呈现AR Logger之前和之后保存运行时数据。 好。
让我们看看如何工作respond_with
def respond_with(*resources, &block) raise "In order to use respond_with, first you need to declare the formats your " << "controller responds to in the class level" if self.class.mimes_for_respond_to.empty? if collector = retrieve_collector_from_mimes(&block) options = resources.size == 1 ? {} : resources.extract_options! options[:default_response] = collector.response (options.delete(:responder) || self.class.responder).call(self, resources, options) end end def self.call(*args) new(*args).respond end def to_format if get? || !has_errors? || response_overridden? default_render else display_errors end rescue ActionView::MissingTemplate => e api_behavior(e) end
这里似乎有太多代码,但你应该看到这个问题的callstack:respond_with – > self.class.responder.respond – > self.class.responder.to_format – > default_render – > default_renderer引发ActionView :: MissingTemplate(因为我们没有任何)。 此时我们可以通过捕获ActionView :: MissingTemplate看到渲染的实现:json和:xml(api_behaviour)。
现在我们知道respond_with是如何工作的,但是AR Logger不知道.. cleanup_view_runtime钩子被调用两次:对于default_renderer(那时模板数据已经准备好并且调用了一些数据库查询,但我们在渲染过程中捕获了ActionView :: MissingTemplate)
db_rt_before_render = ActiveRecord::LogSubscriber.reset_runtime runtime = super # <-- here db_rt_after_render = ActiveRecord::LogSubscriber.reset_runtime
并为api_behavour(当时所有模板数据都准备好渲染,没有数据库查询)
一些凌乱的解释,但我希望它会有所帮助:)
Rails工具通过将请求包装在Rack金属级别并记录不同指标的事件来工作。 在这两种情况下,整个块应该由标准仪器包装和跟踪。
在深入挖掘源代码后,我能看到的唯一区别是调用save()与save!()。 看起来ActiveRecord中的基础方法事件订阅可能表现不同。
尝试更改您的respond_with()示例以使用save vs. save! 并查看它是否正确记录了db_runtime? 如果是这样,那就是一个Rails错误,你可以通过模仿保存来解决它! function使用保存。
更新:
这不是直截了当的,需要一些调整..
除非你把自己的Railtie编写成像Active Record
一样挂钩,但它比复制Active Record
有的复杂一点……
但这是它如何做到的:
1) 日志订户
2) 铁路
3) 控制器运行时
我希望你能得到如何开始进入它的暗示。
干杯!
- 未初始化的常量TZInfo :: InvalidTimezoneIdentifier(NameError) – Rails 4
- 覆盖ActiveSupport :: Concern模块中的方法,这些方法由同一模块中的类方法定义
- 样式化Rails date_select的日期字段
- 两个ActiveSupport :: TimeWithZone对象之间的比较失败
- Ruby没有找到新版本的OpenSSL
- 如何解决activesupport 3.0.0与2.x相比的行为差异?
- 如何在Rails的开发模式下自动为每个请求重新加载gem代码?
- 如何从过时的TZInfo标识符中获取Rails TimeZone名称?
- 你如何处理ActiveSupport :: JSON和JSON gem之间的冲突?