Reputation: 10079
I have three models using inheritance, and a table named '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
When I do a create on the inherited class, it cannot find the table.
[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"
How do I get the inherited class to find the table? Keep in mind, I will need other inherited classes with different tables.
Upvotes: 0
Views: 1422
Reputation: 7014
This looks like a bug in Rails 3.2 that is fixed in Rails 4.0.0.
ETA: Actually, you might need to add abstract class to fix your immediate problem but then hit this bug ;)
Also see this related Documentation commit.
ETA again: A closed rails issue sounds related as well; having non-abstract-classes and table-per-class inheritance looks unsupported.
Upvotes: 4
Reputation: 3935
You have a lot of concepts at play here. Ruby Inheritance, Rails STI, and Namespacing.
First, it seems like you're confusing Ruby's Object Oriented Inheritance with Rails Single Table inheritance (STI) because they both confusingly use inheritance. However with STI the key takeaway is the words single table. Rails STI makes the assumption that all objects will be saved into one table and that the model will add their class name into the extra db column called type. This column needs to exist for STI to work. It also allows you to fetch them via their class_name
Telecom::Circuits::Base.all
or
Telecom::Circuits::AttVoice.all
Your code as I understand it should be
# 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
I took the liberty of making base and att_voice a subclass of circuits as I assumed that they are both independent types of circuits. If base has functionality that the other sub classes share and add on too then this class is redundant and the code would go into the Telecom::Circuit class.
If this isn't what you want, you're outside of the ActiveRecord model used in Rails. You may need to give each its own fully fledged table. Or perhaps you can utilize DataMapper or the new ROM to achieve your means.
Hope this helps!
Upvotes: 1
Reputation: 11811
You shouldnt inherit more than 1 level with rails, it becomes complicated and doesn't work very well. I had a similar structure and went back to only a single inheritance.
Im not sure if this works, but did you try it also with:
class BaseCircuit < ActiveRecord::Base
end
class Circuit < BaseCircuit
...
end
class AttVoiceCircuit < Circuit
...
end
so without namespaces? Table name should be "base_circuits"
Edit: In the answers someone suggested the problem is with more than one level of inheritance or namespaces. I tried the following:
class BaseSo < ActiveRecord::Base
end
class AttVoice < BaseSo
self.table_name = 'telecom_circuits'
end
class ComcastVoice < BaseSo
self.table_name = 'telecom_pri_circuits'
end
with these results:
[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'
Upvotes: 0