#97
Single Table Inheritance
9-10-2017
Summary
Learn to use single table inheritance to allow multiple classes to be stored in the same database table.
17
rails
model
8:33
Summary
Learn to use single table inheritance to allow multiple classes to be stored in the same database table.
17
Resources
Source - https://github.com/driftingruby/097-single-table-inheritance
Summary
20170910010823_create_contacts.rb# rails g model contact user_id:integer type first_name last_name phone_number address city state zip birthday
class CreateContacts < ActiveRecord::Migration[5.1]
def change
create_table :contacts do |t|
t.integer :user_id
t.string :type
t.string :first_name
t.string :last_name
t.string :phone_number
t.string :address
t.string :city
t.string :state
t.string :zip
t.date :birthday
t.timestamps
end
add_index :contacts, [:type, :user_id]
end
endcontact.rbclass Contact < ApplicationRecord
scope :friends, -> { where(type: 'Friend') }
scope :emergencies, -> { where(type: 'Emergency') }
endemergency.rbclass Emergency < Contact
belongs_to :user
validates :first_name, presence: true
validates :last_name, presence: true
validates :phone_number, presence: true
endfriend.rbclass Friend < Contact
belongs_to :user
validates :first_name, presence: true
validates :last_name, presence: true
validates :birthday, presence: true
enduser.rbclass User < ApplicationRecord
has_many :emergencies, class_name: 'Emergency'
has_many :friends, class_name: 'Friend'
endroutes.rbRails.application.routes.draw do
resources :users do
resources :emergencies, controller: :contacts, type: 'Emergency'
resources :friends, controller: :contacts, type: 'Friend'
end
root to: 'users#index'
endshow.html.erb<h1>Emergency Contacts</h1> <%= link_to 'New', new_user_emergency_path(@user) %> <table class='table'> <thead> <tr> <th></th> <th>First Name</th> <th>Last Name</th> <th>Phone Number</th> <th>Birthday</th> </tr> </thead> <tbody> <% @user.emergencies.each do |contact| %> <tr> <td><%= link_to 'delete', [@user, contact], method: :delete %></td> <td><%= contact.first_name %></td> <td><%= contact.last_name %></td> <td><%= contact.phone_number %></td> <td><%= contact.birthday %></td> </tr> <% end %> </tbody> </table> <h1>Friends Contacts</h1> <%= link_to 'New', new_user_friend_path(@user) %> <table class='table'> <thead> <tr> <th></th> <th>First Name</th> <th>Last Name</th> <th>Phone Number</th> <th>Birthday</th> </tr> </thead> <tbody> <% @user.friends.each do |contact| %> <tr> <td><%= link_to 'delete', [@user, contact], method: :delete %></td> <td><%= contact.first_name %></td> <td><%= contact.last_name %></td> <td><%= contact.phone_number %></td> <td><%= contact.birthday %></td> </tr> <% end %> </tbody> </table>
_form.html.erb<%= form_with model: [@user, contact], local: contact do |form| %>
...
<% end %>contacts_controller.rbclass ContactsController < ApplicationController
before_action :set_contact, only: [:show, :edit, :update, :destroy]
def new
@user = User.find(params[:user_id])
@contact = @user.send(set_type.pluralize).new
end
def edit
end
def create
@user = User.find(params[:user_id])
@contact = @user.send(set_type.pluralize).new(contact_params)
if @contact.save
redirect_to @user, notice: "#{params[:type]} Contact was successfully created."
else
render :new
end
end
def update
if @contact.update(contact_params)
redirect_to @user, notice: "#{params[:type]} Contact was successfully updated."
else
render :edit
end
end
def destroy
@contact.destroy
redirect_to @user, notice: "#{params[:type]} was successfully destroyed."
end
private
def set_contact
@user = User.find(params[:user_id])
@contact = @user.send(set_type.pluralize).find(params[:id])
end
def set_type
case params[:type]
when 'Friend'
'friend'
when 'Emergency'
'emergency'
end
end
def contact_params
params.require(set_type.to_sym).permit(:type, :first_name, :last_name, :phone_number, :address, :city, :state, :zip, :birthday)
end
end
Hi,
Nice cast! But would it not be possible to dry out the class definitions a little bit more? As Emergency and Friend anyway inherits from Contact, it would also be possible to declare the association and the "similar" validations in there:
Hi,
While creating new emergencies the url is: http://localhost:3000/users/17/emergencies/new
If validation fails, the url is getting change as: http://localhost:3000/users/17/emergencies
And, than If i refresh the page, its getting crash, because its trying to find list of contacts.
So, how I can I fix this. Please help.