继承的类找不到表

时间:2013-09-10 13:22:41

标签: ruby-on-rails inheritance activerecord ruby-on-rails-3.2

我有三个使用继承的模型,以及一个名为'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 个答案:

答案 0 :(得分:4)

这看起来像Rails 3.2中的一个错误是fixed in Rails 4.0.0

ETA:实际上,你可能需要add abstract class来解决你的问题然后点击这个bug;)

另请参阅此相关Documentation commit

再次发出ETA:A closed rails issue听起来也很相关;具有非抽象类和每类表继承看起来不受支持。

答案 1 :(得分: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'

答案 2 :(得分:0)

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

首先,您似乎将Ruby的面向对象继承与Rails单表继承(STI)混淆,因为它们都混淆地使用了继承。然而,对于STI而言,关键点是单表。 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来实现自己的能力。

希望这有帮助!

答案 3 :(得分:0)

模块和mixins会为你处理这个吗?

请参阅here