【问题标题】:Rails 3.1: how to run an initializer only for the web app (rails server/unicorn/etc)Rails 3.1:如何仅为 Web 应用程序运行初始化程序(rails server/unicorn/etc)
【发布时间】:2011-09-22 00:15:22
【问题描述】:

我的 webapp 需要加密其会话数据。我设置的是:

config/initializers/encryptor.rb:

require 'openssl'
require 'myapp/encryptor'

MyApp::Encryptor.config[ :random_key ] = OpenSSL::Random.random_bytes( 128 )
Session.delete_all

app/models/session.rb:

require 'attr_encrypted'

class Session < ActiveRecord::Base
  attr_accessible :session_id, :data
  attr_encryptor :data, :key => proc { MyApp::Encryptor.config[ :random_key ] }, :marshal => true

  # Rest of model stuff
end

这一切都很好,并且保证了会话数据的安全。这是问题所在:当我运行自定义 rake 任务时,它会加载初始化程序并清除所有会话。不好!

我可以在我的初始化程序中添加什么以确保它仅在 webapp 初始化时运行?或者,我可以在我的初始化程序中添加什么以使其不为 rake 任务运行?

更新:好的,我目前所做的是将MYAPP_IN_RAKE = true unless defined? MYAPP_IN_RAKE 添加到我的.rake 文件中。然后在我的初始化程序中:

unless defined?( MYAPP_IN_RAKE ) && MYAPP_IN_RAKE
    # Web only initialization
end

似乎有效。但我愿意接受其他建议。

【问题讨论】:

  • 这似乎会在未来以其他方式咬你。每次重新启动服务器时,您都会丢失所有会话(这似乎是预期的行为),但这包括服务器因使用过多内存、请求运行时间过长等而自动终止。跨度>
  • 我理解缺点,但我认为这是值得的。正在重新启动应用程序重置会话:可以接受。内存太大或请求太长?在独角兽下,这些情况应该只发生在工作进程中。因为我设置了preload_app = true,所以初始化只发生在主服务器中。所以独角兽可以在不重新初始化的情况下重生工人。

标签: ruby-on-rails ruby rake initializer rake-task


【解决方案1】:

您可以像这样在 `config/application.rb' 中对您的应用程序进行修改:

module MyApp
  def self.rake?
    !!@rake
  end

  def self.rake=(value)
    @rake = !!value
  end

然后在您的Rakefile 中添加以下内容:

MyApp.rake = true

最好使用方法而不是常量,因为有时您希望稍后更改或重新定义它们。另外,它们不会污染根命名空间。

这是一个示例config/initializers/rake_environment_test.rb 脚本:

if (MyApp.rake?)
  puts "In rake"
else
  puts "Not in rake"
end

Rakefile 的可编程特性为您提供了极大的灵活性。

【讨论】:

  • 好的,我喜欢这个。我已将设置器更改为 @rake = !!value unless defined? @rake 以确保它只设置一次。然后我还添加了 environment.rb MyApp.rake = false。听起来合理吗?
  • 你为什么要担心只设置一次呢?比简单地忽略重复集更好的做法是至少发出警告,或者更好的做法是抛出异常,以便追踪问题的根源。
  • 我想我担心在作为 webapp 代码运行时,Rakefile 会以某种方式被加载。我的想法是对称的:作为 rake,加载了 webapp 环境,所以我还应该处理作为 webapp 加载 rake 的情况。
  • 如果你从你的应用程序中加载你的Rakefile,你正在做一些非常特殊的事情。我认为这甚至行不通。
  • 谢谢,我正在找这个。感觉有点hacky,这是实现这一目标的唯一方法吗?
【解决方案2】:

还有另一种解决方法:

unless ENV["RAILS_ENV"].nil? || ENV["RAILS_ENV"] == 'test'

当您使用 rake 启动时,您的 ENV["RAILS_ENV"] 将为零。 'test' 的测试是为了避免在使用 rspec 时运行。

我知道可以使用 Rails.env,但它在未初始化时返回“开发”。

http://apidock.com/rails/Rails/env/class

# File railties/lib/rails.rb, line 55
def env
  @_env ||= ActiveSupport::StringInquirer.new(ENV["RAILS_ENV"] 
     || ENV["RACK_ENV"] || "development")
end

【讨论】:

  • 谢谢!正是我需要的!
猜你喜欢
  • 1970-01-01
  • 2012-09-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-29
  • 1970-01-01
  • 1970-01-01
  • 2012-01-23
  • 1970-01-01
相关资源
最近更新 更多