read_inheritable_attribute 在生产中意外修改

发布于 2024-11-29 00:50:04 字数 1240 浏览 4 评论 0原文

这种情况发生在 Rails 3.0.7 和 3.0.9、WEBrick 和 Apache 中。

我有一个模块 Reportable,它有一个编写 inheritable_attribute 的方法:

module Reportable
  module ClassMethods
    def add_report(report_name)
      instance_eval do
        write_inheritable_hash(:reportable_report_names,
          {report_name => {:dates => true, :details => 'something'})
        end
      end
    end
  end

  def self.included(base)
    base.extend(ClassMethods)
  end
end

Reportable 加载到 config/initializers 中,并且一个类使用它:

class User < ActiveRecord::Base
  include Reportable
  add_report :report1
  add_report :report2
end

在生产模式下,服务器启动后第一次加载页面时,属性加载正确:

User.read_inheritable_attribute(:reportable_report_names)
# => {:report1 => {:dates => true, :details => 'something'},
      :report2 => {:dates => true, :details => 'something'}}

但在第二次页面加载时:

User.read_inheritable_attribute(:reportable_report_names)
# => {:report1 => {:dates => true},
      :report2 => {:dates => true}}

它在开发中按预期工作,在生产模式下在控制台中按预期工作。该问题仅出现在生产模式下 Web 服务器上的 POST 请求中。什么给?

This is happening in Rails 3.0.7 and 3.0.9, WEBrick and Apache.

I have a module Reportable that has a method that writes an inheritable_attribute:

module Reportable
  module ClassMethods
    def add_report(report_name)
      instance_eval do
        write_inheritable_hash(:reportable_report_names,
          {report_name => {:dates => true, :details => 'something'})
        end
      end
    end
  end

  def self.included(base)
    base.extend(ClassMethods)
  end
end

Reportable is loaded in config/initializers and a class uses it:

class User < ActiveRecord::Base
  include Reportable
  add_report :report1
  add_report :report2
end

In production mode, the first time I load a page after the server starts, the attribute loads correctly:

User.read_inheritable_attribute(:reportable_report_names)
# => {:report1 => {:dates => true, :details => 'something'},
      :report2 => {:dates => true, :details => 'something'}}

But on the second page load:

User.read_inheritable_attribute(:reportable_report_names)
# => {:report1 => {:dates => true},
      :report2 => {:dates => true}}

It works as expected in development, and in the console in production mode. The problem only appears in a POST request on the web server in production mode. What gives?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

淡淡绿茶香 2024-12-06 00:50:04

刚刚尝试过,在所有环境下都可以正常工作。还有其他细节吗?


否则:

  • 既然您正在处理模型本身,为什么要使用 instance_eval

  • 你应该使用 splat 来传递参数

这将导致:

module ClassMethods
  def add_reports(*report_names)
    report_names.each do |report_name|
      write_inheritable_hash(:loggable_report_names,
        {report_name => {:dates => true, :details => 'something'})
      end
    end
  end
end

在模型中:

include Reportable
add_reports :report1, :report2

Just tried, it works in all environments without problem. Any other details?


Otherwise:

  • why do you use instance_eval since you're working on the model itself?

  • you should use a splat to pass arguments

This would lead to:

module ClassMethods
  def add_reports(*report_names)
    report_names.each do |report_name|
      write_inheritable_hash(:loggable_report_names,
        {report_name => {:dates => true, :details => 'something'})
      end
    end
  end
end

And in model:

include Reportable
add_reports :report1, :report2
背叛残局 2024-12-06 00:50:04

经过一番头痛之后,原因是 read_inheritable_attribute 返回的是引用而不是值。

引发错误的操作重定向到另一个操作,这是问题的真正原因。该模块还有另一个方法:

def available_reports
  read_inheritable_attribute(:reportable_report_names)
end

另一个操作执行了以下操作:

# @model_reports = a hash of 'model_class_name'.to_sym => model.available_reports.dup
@model_reports.each do |model, model_reports|
  model_reports.each do |name, properties|
    properties = properties.keep_if... # remove per the view's requirements
  end
end

因为 available_reports 返回了一个引用,所以 dup 没有执行任何操作,并且 keep_if 删除了我的宝贵资源来自类变量的值。

解决方法是:

properties = properties.dup.keep_if...

感谢那些花时间检查这个问题的人,尽管其中没有足够的信息来正确回答。

After a lot of headaches, the cause was that read_inheritable_attribute returned a reference rather than value.

The action throwing the error redirected to another action, which was the true cause of the problem. The module had another method:

def available_reports
  read_inheritable_attribute(:reportable_report_names)
end

And the other action did this:

# @model_reports = a hash of 'model_class_name'.to_sym => model.available_reports.dup
@model_reports.each do |model, model_reports|
  model_reports.each do |name, properties|
    properties = properties.keep_if... # remove per the view's requirements
  end
end

Because available_reports returned a reference, the dup did nothing and the keep_if deleted my precious values from the class variable.

The fix was:

properties = properties.dup.keep_if...

Thanks to those who took the time to check this question out even though there wasn't enough information in it to be answered properly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文