【问题标题】:ActiveAdmin and CircleCI: autoloader causes Postgres to failActiveAdmin 和 CircleCI:自动加载器导致 Postgres 失败
【发布时间】:2013-10-02 17:11:28
【问题描述】:

我们在 Postgres 和 Rails 3 中使用 ActiveAdmin 和 CircleCI。它运行良好,但在添加新的 ActiveAdmin 模型后,我们在 rake db:create db:schema:load 中得到了这个:

PG::UndefinedTable: ERROR:  relation "external_videos" does not exist
...
/home/ubuntu/Swearnet/app/models/external_video.rb:11:in `<class:ExternalVideo>'
/home/ubuntu/Swearnet/app/models/external_video.rb:1:in `<top (required)>'
...
/home/ubuntu/Swearnet/vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:190:in `const_missing'
/home/ubuntu/Swearnet/app/admin/external_video.rb:1:in `<top (required)>'
...
/home/ubuntu/Swearnet/config/routes.rb:54:in `block in <top (required)>'

如果我们删除新文件(即使该文件与我们的任何其他 ActiveAdmin 文件没有本质区别),错误就会消失。

这个错误似乎是路由导致 ActiveAdmin 加载,这导致 ExternalVideo 模型被自动加载,这导致它查找尚未创建的 external_videos 表。为什么我们的其他 ActiveAdmin 文件不会发生这种情况?有没有其他人遇到过这种问题?

我们的新文件是app/admin/external_videos.rb,看起来像:

ActiveAdmin.register ExternalVideo do
  menu :parent => "Shows"

  form do |f|
    f.inputs nil do
      f.input :title
      f.input :description
      f.input :published_at
      f.input :expires_at
    end
    f.actions
  end
end

编辑:我们发现了问题... ExternalVideo 上有一个名为find_by_sxg_id 的范围。当我们将该范围重命名为 get_by_sxg_id 时,一切正常。我不知所措...我知道find_by 通常是一个神奇的 ActiveRecord 前缀,但不确定在 rake 任务中创建表之前,仅仅是定义如何导致表被访问...

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 postgresql activeadmin circleci


    【解决方案1】:

    为了让任何想了解更多信息的人受益,我希望这些信息对您有所帮助。在 activeadmin 的上下文中,我们在两个地方遇到了这个问题。

    1.在搜索过滤器上定义集合时未能声明 proc {}。

    例如:

    filter :association_id, as: :select, collection: Association.all, label: "Association"
    

    应该是

    filter :association_id, as: :select, collection: proc { Association.all }, label: "Association"
    

    延迟模型加载直到索引页面实际加载,并允许 Circle CI 完成 db:schema:load(或执行 db:schema:load 的 rake 任务)

    2。注册资源会加载模型定义,因此如果有任何方法定义需要模型实例化,Circle CI 会给您 Postgres 错误,您将一无所获。

    这是一个比较棘手的发现,尽管事后看来它应该是显而易见的。因此,例如,如果您有一个状态为“initial、active、inactive”的“roll-your-own”状态机,并且您想定义一组查询方法,您可以这样做:

    def states
      [ :initial, :active, :inactive ]
    end
    
    def self.included(Model)
      states = Model.new.states
      states.each do |state|
      base.send(:define_method, "#{state}?") do
        self.state == state
    end
    

    因此,为了加载资源,我们需要实例化模型(Model.new 行)。为了解决这个问题,我们将其更改为:

    def self.states
      [ :initial, :active, :inactive ]
    end
    
    def self.included(Model)
      states = Model.states
      states.each do |state|
      base.send(:define_method, "#{state}?") do
        self.state == state
    end
    

    希望这对某人有所帮助!

    【讨论】:

      【解决方案2】:

      这是使用 ActiveRecord 时的常见问题,您不是第一个遇到此错误的人!这很常见,我们在上面写了一个文档:https://circleci.com/docs/ruby-exception-during-schema-load

      【讨论】:

      • 我当然看过那个文档。问题是:仅仅是作用域的名称是如何导致这个问题的?
      • 嗯,我想这有点不清楚。使用 activerecord 中的名称加载模型,模型依赖于数据库模式自省。由于数据库不存在,它会中断。有意义吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-16
      • 2022-08-17
      • 2013-07-07
      • 2011-11-24
      • 2021-06-22
      • 2017-03-07
      相关资源
      最近更新 更多