Rails 活动支持通知 - 错误的数据库运行时值



我正在尝试记录对我的 REST API 应用程序的请求。我为此使用轨道通知,就像这里一样 http://railscasts.com/episodes/249-notifications-in-rails-3

我不明白如何解决轨道通知的一个问题。

我的初始值设定项代码

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}

如您所见:d b_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}

:d b_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时,它似乎不起作用!有人可以告诉我为什么吗?谢谢

好的,这似乎是一个错误。让我们看看,发生了什么:

首先,我们有用于控制器动作的AR导轨及其通过使用钩子设置db_runtime cleanup_view_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

这里似乎代码太多,但您应该看到此问题的调用堆栈:respond_with -> self.class.responder.response -> 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 检测的工作原理是在机架金属级别包装请求并记录不同指标的事件。 在这两种情况下,整个块都应由标准仪器包装和跟踪。

挖掘源代码后我能看到的唯一区别是调用 save() 与 save!(). 看起来 ActiveRecord 中的基础方法事件订阅的行为可能有所不同。

尝试更改您的 respond_with() 示例以使用保存与保存! 看看它是否正确记录了db_runtime? 如果是这样,那就是一个 Rails 错误,您可以通过模仿保存来解决它!使用保存的功能。

更新:

这并不简单,需要一些调整。

除非你编写自己的 Railtie 来像Active Record一样钩入这个,但它比复制Active Record拥有的东西要复杂一些......

但这是它是如何做到的:

1) 日志订阅者

2) 导轨

3) 控制器运行时

我希望你得到了如何开始进入它的提示。

干杯!

相关内容

  • 没有找到相关文章

最新更新