我需要一些帮助来重组Rails应用程序。您可以在下面找到额外的细节。主要问题:
我在@Nathan建议之后修改了代码。向天堂迈进一步,但仍能闻到一些硫磺。
环境:
错误详情:
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
答案 0 :(得分:0)
您正在3个单独的文件中打开/定义Report
类。
在report.rb
中,您指定::Spock::SpockConnector
作为Report
的超类,但在bridge.rb
和metric.rb
中,您不是指定显式超类,因此Ruby使用Object
作为其超类。
您不能同时拥有Object
和 ::Spock::SpockConnector
作为Report
的直接超类。
解决方案:
在所有3个文件中,您需要使用class Report < ::Spock::SpockConnector
一旦你解决了这个问题,你就会遇到类似的错误,因为你在几个文件中打开SpockConnector
,一次用::ActiveRecord::Base
作为超类,有时用隐式{{1}打开作为超类。
这是另一个矛盾,因此在所有打开/定义Object
的文件中,您需要使用SpockConnector
作为超类。
至于你的命名空间问题,这是基于意见的,但我会说在Ruby中没有需要在命名空间内嵌套子类。
例如,您可以将::ActiveRecord::Base
,Report
,SpockConnector
和Metric
全部保留在同一命名空间级别:
Bridge
完全范围的名称是:
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
答案 1 :(得分:0)
行。经过一天的反复试验后,我找到了自动加载问题的原因。
如果您发现自己触摸自动加载结构,那么这是一个错误路径的好兆头。 所以我从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文件中明确包含该文件夹。 缺点是类绝对路径变得更长......