Reputation: 968
I have problem with creating proper inheritance between classes in Ruby On Rails.
Idea: There are 2 classes: Person and Client. Person is a abstract class and Client inherits Person attribute.
Problem: My solution doesn't work. I don't know why. How can I correctly implement (prefer CTI) inheritance.
Migrations:
create_persons.rb
class CreatePersons < ActiveRecord::Migration
def self.up
create_table :persons do |t|
t.string :pesel, null: false
t.string :first_name, null: false
t.string :last_name, null: false
t.string :email, null: false
t.date :data_of_birth, null: false
t.string :password_digest, null: false
# required for STI
t.string :type
t.timestamps null: false
end
end
def self.down
drop_table :persons
end
end
create_clients.rb
class CreateClients < ActiveRecord::Migration
def change
create_table :clients do |t|
add_foreign_key :persons
t.timestamps null: false
end
end
end
Model Person
class Person < ActiveRecord::Base
self.abstract_class = true
end
Model Client
class Client < Person
end
After db:migrate, when I try Client.create(pesel: "1232",....) there is error:
unknown attribute 'pesel' for Client
.
Upvotes: 1
Views: 139
Reputation: 161
Single Table Inheritance is based upon having a single table to store all the records. Your problem is that you create a table 'clients' which Rails uses by default for the Client class.
Just rake db:rollback on your last migration and it should look for the superclass table 'people' and work fine.
Edit : Oops, didn't see you mention CTI, this solution only works for STI.
Upvotes: 1
Reputation: 34774
You're getting an error because you've created a clients
table in addition to your persons
table. If you have a separate table for each class then the only thing that is inherited is the code and not the contents of the database.
Single Table Inheritance (STI) allows you to add a type
column and then instances of the parent class and subclasses will be stored in that single table provided the expected table for the subclass isn't present. You've added that type
column but you've also created a clients
table. This means that ActiveRecord is expecting you to store Client
instances in that table instead of the persons
- and when it tries to store a Client
there it cannot use the field pesel
causing your error.
So, if you want to use STI, then you need to remove your clients
table and add an client-specific fields to your persons
table.
Alternatively, you can keep your clients
table and add the fields from persons
that you want to also use for clients to the clients
table. This wouldn't then be STI but your Client
objects would inherit the methods from Person
.
I suspect from your inclusion of the type
field that you want to get rid of the clients
table.
Upvotes: 1