20

我的 rails 应用程序有一个网站爬虫,它加载爬虫在config/initializers. 初始化程序通过调用 SiteLogin 模型中的模型方法来加载身份验证。

当我运行rake db:migrate创建SiteLogin模型表时,它失败了,因为初始化程序期望数据库表已经存在。我可以简单地注释掉初始化器中的代码,运行迁移以创建表,然后取消注释初始化器代码,而不必担心问题。

问题是,我正在使用 Capistrano 进行部署,这意味着我必须先在没有初始化代码的情况下进行部署才能运行迁移,然后再使用初始化代码再次部署。有没有更好的方法可以做到这一点,或者在这种情况下我的方法完全错误。

这是一些代码示例,可以更好地解释我的情况:

# config/initializers/site_crawler_init.rb
SiteCrawler.setup do |config|
  config.hostname = "www.example.com"
end

# model/site_crawler.rb
class SiteCrawler
  ...
  class << self
    attr_accessor :configuration

    def setup
      self.configuration ||= Configuration.new
      yield(configuration)
    end
  end

  class Configuration

    attr_accessor :hostname, :login_credentials

    def initialize
      @login_credentials = SiteLogin.admin_user
      ...
    end
  end
end
4

2 回答 2

19

它可能不是更好的解决方案,但您可以检查表是否存在:

if ActiveRecord::Base.connection.tables.include?('your_table_name')
  # your code goes here
end

但它通常还不够,因为可能会有待处理的迁移。

现在,您还可以检查您是否处于 rake 任务中:

if ActiveRecord::Base.connection.tables.include?('your_table_name') and !defined?(::Rake)
  # your code goes here
end

而且在启动测试时可能还不够,因为在rake任务中执行,因此您还可以检查Rails环境是否为test(Rails.env.test?)。

于 2012-08-28T11:32:37.617 回答
13

我有一个类似的问题,我需要在运行特定的 rake 任务时跳过特定的初始化程序(对于延迟的作业,这需要存在延迟的作业表) - 在本例中为 db:migrate。

我在我的 Rakefile 中添加了以下内容:

def running_tasks
  @running_tasks ||= Rake.application.top_level_tasks
end

def is_running_migration?
  running_tasks.include?("db:migrate")
end

然后是我有问题的初始化程序中的以下内容:

unless defined?(is_running_migration?) && is_running_migration?
  ... do whatever
end
于 2015-05-11T15:51:09.773 回答