【问题标题】:Issue with Rails namespaces and STI - Spiced up with autoloadingRails 命名空间和 STI 的问题 - 自动加载
【发布时间】:2015-10-22 15:36:06
【问题描述】:

我需要一些帮助来重组 Rails 应用程序。您可以在下面找到更多详细信息。主要问题:

我根据@Nathan 的建议修改了代码。离天堂更远了,但仍能闻到一些硫磺味。

  • 已解决:为什么会出现错误:“类报告的超类不匹配”
  • 已解决:我能否提供一些指导方针,如何在 Rails4 中构建复杂的命名空间、扩展和 STI?
  • 服务器重新启动后,我在 Spock 主页上收到错误消息:--“无法自动加载常量 Bridge,预期...路由在这里... app/models/spock/report/bridge.rb 定义它"--刷新页面后,错误消失了。但是,仍然表明一些问题。每次服务器重新启动后,这都是可重现的。提示:可能是自动加载问题...欢迎提出任何想法。

环境:

  • WEBrick 1.3.1
  • Rails 4.0.9
  • Ruby 2.1.5

错误详情:

Unable to autoload constant Bridge, expected ...route goes here... bridge.rb to define it

app/views/spock/spock/index.html.erb:11:in `block in _app_views_spock_spock_index_html_erb___3895075684249237486_132397353980'
app/views/spock/spock/index.html.erb:6:in `map'
app/views/spock/spock/index.html.erb:6:in `_app_views_spock_spock_index_html_erb___3895075684249237486_132397353980'

文件结构:

/app/controllers/spock/spock_controller.rb
/app/controllers/spock/marketplaces_controller.rb
/app/controllers/spock/reports_controller.rb

/app/modules/spock/spock_connector.rb
/app/modules/spock/report.rb
/app/modules/spock/report/bridge.rb
/app/modules/spock/report/metric.rb

文件:

# application.rb
...
config.autoload_paths += Dir[Rails.root.join('app', 'models', 'spock', '{**}')]
...

# routes.rb
namespace :spock do
  get '/', :to => 'spock#index'
  resources :marketplaces, only: [] do
    resources :reports,    only: [:show]
end

# spock_controller.rb
module Spock
  class SpockController < ApplicationController
    def index
      @report_categories = Spock::Report.distinct.pluck(:category)
...

# marketplaces_controller
module Spock
  class MarketplacesController < SpockController
  end
end

# reports_controller
module Spock
  class ReportsController < MarketplacesController
    helper SpockHelper
...

# spock_connector.rb
module Spock
  class SpockConnector < ::ActiveRecord::Base
    self.abstract_class = true
    establish_connection "spock_#{Rails.env}"
  end
end

# report.rb
module Spock
  class Report < SpockConnector
    attr_accessor :legal_entity
  end
end

# bridge.rb
module Spock
  class Bridge < Report
...

# metric.rb
module Spock
  class Metric < Report
...

数据库:

/* reports table */
id, type,           category,
1   Spock::Bridge  Bridge
2   Spock::Metric  Metric

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4


    【解决方案1】:

    您在 3 个单独的文件中打开/定义 Report 类。

    report.rb 中,您将::Spock::SpockConnector 指定为Report 的超类,但在bridge.rbmetric.rb 中,您没有指定显式超类,因此Ruby 使用@ 987654327@ 作为它的超类。

    你不能同时拥有Object ::Spock::SpockConnector 作为Report 的直接超类。

    解决方案: 在所有 3 个文件中,您需要使用 class Report &lt; ::Spock::SpockConnector

    一旦你解决了这个问题,你就会遇到类似的错误,因为你在几个文件中打开SpockConnector,一次以::ActiveRecord::Base 作为超类,其他时候以隐式Object 作为超类。

    这是另一个矛盾,所以在所有打开/定义SpockConnector的文件中,你需要使用::ActiveRecord::Base作为超类。

    至于您的命名空间问题,这是基于意见的,但我会说,在 Ruby 中,没有需要在命名空间内嵌套子类。

    例如,您可以ReportSpockConnectorMetricBridge 都保留在同一命名空间级别:

    module Spock
      class SpockConnector < ActiveRecord::Base
      end
    end
    
    module Spock
      class Report < SpockConnector
      end
    end
    
    module Spock
      class Metric < Report
      end
    end
    
    module Spock
      class Bridge < Report
      end
    end
    

    全范围名称为:

    Spock::SpockConnector
    Spock::Report
    Spock::Bridge
    Spock::Metric
    

    【讨论】:

    • 是的,我将类范围与超类名称混合在一起......这是一件愚蠢的事情。
    【解决方案2】:

    好的。经过一天的反复试验,我找到了自动加载问题的原因。

    如果您发现自己接触了自动加载结构,则表明您走错了路。 所以我从 application.rb 文件中删除了自动加载路径。

    并稍微修改了 STI 类,以匹配 Rails 自动加载逻辑;

    # bridge.rb
    module Spock
      class Report
        class Bridge < Report
    ...
    
    # metric.rb
    module Spock
      class Report
        class Metric < Report
    ...
    

    数据库:

    /* reports table */
    id, type,           category,
    1   Spock::Report::Bridge  Bridge
    2   Spock::Report::Metric  Metric
    

    在超类中包含 STI 类使它们能够从子文件夹中自动加载,而无需在 application.rb 文件中显式包含文件夹。 缺点是类的绝对路径会变长...

    【讨论】:

      猜你喜欢
      • 2015-06-11
      • 2020-02-17
      • 2013-06-01
      • 2011-11-19
      • 2019-02-22
      • 2013-02-12
      • 1970-01-01
      • 2011-08-06
      相关资源
      最近更新 更多