0

我有三个使用继承的模型,以及一个名为“telecom_circuits”的表。

class Telecom::Circuits::BaseCircuit < ActiveRecord::Base
end

class Telecom::Circuit < ::Telecom::Circuits::BaseCircuit
  ...
end

class Telecom::Circuits::AttVoiceCircuit < ::Telecom::Circuit
  self.table_name = 'telecom_circuits'
end

当我对继承的类进行创建时,它找不到表。

[1] pry(main)> Telecom::Circuits::AttVoiceCircuit
=> Telecom::Circuits::AttVoiceCircuit(id: integer, user_id: integer, division_id: integer, raw_site_id: integer, install_date: date, saville_account_number: string, account_number: string, meg8_account_number: string, main_circuit_id: string, d_channel: string, d_channel_type: string, ds3_access_circuit_id: string, lec_circuit_id: string, cli: string, lso: string, apn_ct1: string, dchan_cost: decimal, monthly_recurring_cost: decimal, created_at: datetime, updated_at: datetime, circuit_provision_type: string, trunk_group: string, apn_ct2: string, slot: string, disconnect_date: datetime, disconnect_requester_id: integer, disconnect_processor_id: integer, telecom_site_id: integer)
[2] pry(main)> Telecom::Circuits::AttVoiceCircuit.create
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'itrc_dev.telecom_base_circuits' doesn't exist: SHOW FULL FIELDS FROM `telecom_base_circuits`
from /Users/mpierc200/.rvm/gems/ruby-1.9.3-p327@itrc/gems/activerecord-3.2.14/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:245:in `query'
[3] pry(main)> Telecom::Circuits::AttVoiceCircuit.table_name
=> "telecom_circuits"

如何让继承的类找到表?请记住,我将需要具有不同表的其他继承类。

4

4 回答 4

4

这看起来像是 Rails 3.2 中的错误,已在 Rails 4.0.0 中修复

ETA:实际上,您可能需要添加抽象类来解决您当前的问题,然后遇到这个错误;)

另请参阅此相关文档提交

ETA 再次:关闭的轨道问题听起来也很相关;具有非抽象类和每类表的继承看起来不受支持。

于 2013-09-18T20:39:57.780 回答
1

你在这里有很多概念在起作用。Ruby 继承、Rails STI 和命名空间。

首先,您似乎将 Ruby 的面向对象继承与 Rails 单表继承 (STI) 混淆了,因为它们都混淆了继承。然而,对于 STI,关键的要点是单词single table。Rails STI 假设所有对象都将保存到一个表中,并且模型会将它们的类名添加到名为type的额外 db 列中。此列需要存在才能使 STI 正常工作。它还允许您通过它们的class_name获取它们

Telecom::Circuits::Base.all

或者

Telecom::Circuits::AttVoice.all

据我了解,您的代码应该是

# in app/telecom/circuit.rb
class Telecom::Circuit < ActiveRecord::Base
  ...
end

# in app/telecom/circuits/base.rb
class Telecom::Circuits::Base < Telecom::Circuit
  ...
end

# in app/telecom/circuits/att_voice.rb    
class Telecom::Circuits::AttVoice < Telecom::Circuit
  ... 
end

我冒昧地将 base 和 att_voice 设为电路的子类,因为我假设它们都是独立的电路类型。如果 base 具有其他子类共享和添加的功能,那么这个类是多余的,代码将进入 Telecom::Circuit 类。

如果这不是您想要的,那么您就超出了 Rails 中使用的 ActiveRecord 模型。您可能需要为每个人提供自己的完整表格。或者,也许您可​​以利用DataMapper或新的ROM来实现您的目的。

希望这可以帮助!

于 2013-09-18T20:09:50.967 回答
0

模块和 mixins 会为您处理这个问题吗?

这里

于 2013-09-18T20:19:07.397 回答
0

你不应该用 Rails 继承超过 1 级,它会变得复杂并且不能很好地工作。我有一个类似的结构,然后回到只有一个继承。

我不确定这是否有效,但您是否也尝试过:

class BaseCircuit < ActiveRecord::Base
end

class Circuit < BaseCircuit
  ...
end

class AttVoiceCircuit < Circuit
  ...
end

所以没有命名空间?表名应为“base_circuits”

编辑:在有人建议的答案中,问题出在不止一层继承或命名空间上。我尝试了以下方法:

class BaseSo < ActiveRecord::Base
end

class AttVoice < BaseSo
  self.table_name = 'telecom_circuits'
end

class ComcastVoice < BaseSo
  self.table_name = 'telecom_pri_circuits'
end

这些结果:

[1]pry(main)> AttVoice
=> AttVoice(id: integer, user_id: integer, division_id: integer, raw_site_id: integer, install_date: date, saville_account_number: string, account_number: string, meg8_account_number: string, main_circuit_id: string, d_channel: string, d_channel_type: string, ds3_access_circuit_id: string, lec_circuit_id: string, cli: string, lso: string, apn_ct1: string, dchan_cost: decimal, monthly_recurring_cost: decimal, created_at: datetime, updated_at: datetime, circuit_provision_type: string, trunk_group: string, apn_ct2: string, slot: string, disconnect_date: datetime, disconnect_requester_id: integer, disconnect_processor_id: integer, telecom_site_id: integer)
[2] pry(main)> AttVoice.table_name
=> "telecom_circuits"
[3] pry(main)> ComcastVoice
=> ComcastVoice(id: integer, created_at: datetime, updated_at: datetime, order_submitter: string, division_id: integer, lead_id: integer, pin: integer, raw_site_id: integer, site_poc: string, install_date: date, csg_billing_number: string, gl_code: string, pri_count: integer, pri_type: string, port_native: boolean, did_range: string, did_count: integer, comments: string, telecom_site_id: integer)
[4] pry(main)> ComcastVoice.table_name
=> "telecom_pri_circuits"
[5] pry(main)> AttVoice.count
(41.8ms)  SELECT COUNT(*) FROM `telecom_circuits` 
=> 2247
[6] pry(main)> AttVoice.create
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'itrc_dev.base_sos' doesn't exist: SHOW FULL FIELDS FROM `base_sos`
from /Users/mpierc200/.rvm/gems/ruby-1.9.3-p327@itrc/gems/activerecord-3.2.14/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:245:in `query'
[7] pry(main)> ComcastVoice.count
(0.4ms)  SELECT COUNT(*) FROM `telecom_pri_circuits` 
=> 155
[8] pry(main)> ComcastVoice.create
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'itrc_dev.base_sos' doesn't exist: SHOW FULL FIELDS FROM `base_sos`
from /Users/mpierc200/.rvm/gems/ruby-1.9.3-p327@itrc/gems/activerecord-3.2.14/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:245:in `query'
于 2013-09-10T21:14:14.417 回答