Polymorphic Associations - Customer & Supplier have Phones

INTRO

I am currently working for a company who want a new e-commerce
interface; I have considered using ruby on rails. I am completely stuck
I don’t know what has gone wrong I am trying to create customers or
suppliers numbers and it wont do anything, it will actually ignore the
data I input and just show blank without any errors. Hopefully this
example can help others in the future if they want to do something
similar what I have.

SCENARIO

I have four tables, which are

  • Addresses
  • Customers
  • Suppliers
  • Phones

I have used polymorphic association because a customer and a supplier
can have more than one or many addresses and phone numbers etc. So I
basically created my tables using Migration, then used ruby Scaffold to
create models, views etc. This is how I have created the relationships
note that I am currently just going to focus on the phones table with
customer or supplier once I have this right I can easily do the
addresses:

Phones Table:

class CreatePhones < ActiveRecord::Migration
def self.up
create_table :phones do |t|
t.column :created_at, :datetime
t.column :updated_at, :datetime
t.column :phonable_id, :integer, :null => false
t.column :phonable_type, :string, :null => false
t.column :tag_for_phone, :string # could be “work phone”, “home
phone”, etc
t.column :number, :string # redundant but makes searching easier
t.column :country_code, :string
t.column :area_code, :string
t.column :local_number, :string

end
add_index :phones, :number # don't make this unique!

end

def self.down
drop_table :phones
end
end

Customer Table:

class CreateCustomers < ActiveRecord::Migration
def self.up
create_table :customers do |t|
t.column :first_name, :string
t.column :surname, :string
end
end

def self.down
drop_table :customers
end
end

Supplier Table:

class CreateSuppliers < ActiveRecord::Migration
def self.up
create_table :suppliers do |t|
t.column :name, :string
end
end

def self.down
drop_table :suppliers
end
end

Here are the relationships between tables:

Phones Model:

class Phone < ActiveRecord::Base
belongs_to :phonable, :polymorphic => true
has_one :customer, :as => :phonable
has_one :supplier, :as => :phonable
end

Customer Model:

class Customer < ActiveRecord::Base
has_many :phones, :as => :phonable, :dependent => :destroy
has_many :addresses, :as => :addressable, :dependent => :destroy

def full_name
“#{first_name} #{surname}”
end
end

Supplier Model:

class Supplier < ActiveRecord::Base
has_many :phones, :as => :phonable, :dependent => :destroy
has_many :addresses, :as => :addressable, :dependent => :destroy

def full_name
name
end
end

Now here are the controllers that I have used:

Phones Controller:

class PhonesController < ApplicationController
def index
list
render :action => ‘list’
end

GETs should be safe (see

http://www.w3.org/2001/tag/doc/whenToUseGet.html)
verify :method => :post, :only => [ :destroy, :create, :update ],
:redirect_to => { :action => :list }

def list
@phone_pages, @phones = paginate :phones, :per_page => 10
end

def show
@phone = Phone.find(params[:id])
end

def new
@customer = Customer.find(params[:customer_id]) if
params[:customer_id]
@supplier = Supplier.find(params[:supplier_id]) if
params[:supplier_id]
@phone = Phone.new
end

def create
@customer = Customer.find(params[:customer][:id]) if
params[:customer]
@supplier = Supplier.find(params[:supplier][:id]) if
params[:supplier]
@phone = Phone.new(params[:phone])
@phone.number = “+#{@phone.country_code} #{@phone.area_code}
#{@phone.local_number}”
respond_to do |format|
if @phone.save
@customer.phones << @phone if @customer
@supplier.phones << @phone if @supplier
@customer.save if @customer
@supplier.save if @supplier
flash[:notice] = “Successfully added #{@phone.number}.”
format.html { redirect_to phone_url(@phone) }
format.xml { head :created, :location => phone_url(@phone) }
else
flash[:notice] = “Unable to add #{@phone.number}.”
format.html { render :action => “new” }
format.xml { render :xml => @phone.errors.to_xml }
end
end
end

def edit
@phone = Phone.find(params[:id])
end

def update
@phone = Phone.find(params[:id])
if @phone.update_attributes(params[:phone])
flash[:notice] = ‘Phone was successfully updated.’
redirect_to :action => ‘show’, :id => @phone
else
render :action => ‘edit’
end
end

def destroy
Phone.find(params[:id]).destroy
redirect_to :action => ‘list’
end
end

Customers Controller:

class CustomersController < ApplicationController
def index
list
render :action => ‘list’
end

GETs should be safe (see

http://www.w3.org/2001/tag/doc/whenToUseGet.html)
verify :method => :post, :only => [ :destroy, :create, :update ],
:redirect_to => { :action => :list }

def list
@customer_pages, @customers = paginate :customers, :per_page => 10
end

def show
@customer = Customer.find(params[:id])
end

def new
@customer = Customer.new
end

def create
@customer = Customer.new(params[:customer])
if @customer.save
flash[:notice] = ‘Customer was successfully created.’
redirect_to :action => ‘list’
else
render :action => ‘new’
end
end

def edit
@customer = Customer.find(params[:id])
end

def update
@customer = Customer.find(params[:id])
if @customer.update_attributes(params[:customer])
flash[:notice] = ‘Customer was successfully updated.’
redirect_to :action => ‘show’, :id => @customer
else
render :action => ‘edit’
end
end

def destroy
Customer.find(params[:id]).destroy
redirect_to :action => ‘list’
end
end

Suppliers Controller:

class SuppliersController < ApplicationController
def index
list
render :action => ‘list’
end

GETs should be safe (see

http://www.w3.org/2001/tag/doc/whenToUseGet.html)
verify :method => :post, :only => [ :destroy, :create, :update ],
:redirect_to => { :action => :list }

def list
@supplier_pages, @suppliers = paginate :suppliers, :per_page => 10
end

def show
@supplier = Supplier.find(params[:id])
end

def new
@supplier = Supplier.new
end

def create
@supplier = Supplier.new(params[:supplier])
if @supplier.save
flash[:notice] = ‘Supplier was successfully created.’
redirect_to :action => ‘list’
else
render :action => ‘new’
end
end

def edit
@supplier = Supplier.find(params[:id])
end

def update
@supplier = Supplier.find(params[:id])
if @supplier.update_attributes(params[:supplier])
flash[:notice] = ‘Supplier was successfully updated.’
redirect_to :action => ‘show’, :id => @supplier
else
render :action => ‘edit’
end
end

def destroy
Supplier.find(params[:id]).destroy
redirect_to :action => ‘list’
end
end

This is my phones helper:

module PhonesHelper

def phonable_path(phonable)
if phonable.kind_of? Customer
customer_path(phonable)
else
supplier_path(phonable)
end
end
end

Now for the pages I have used the following code and what happens is
that I try to add a phone number for the customer and it wont add the
telephone number at all I have tried everything:

Customers View Show:

<% unless @user.phones.empty? %>
Phone Numbers
<% for phone in @customer.phones %>
<%= link_to phone.number, phone_path(phone) %>

<% end %>
<% end %>


<%= link_to 'Add Phone Number', new_user_phone_path(@user) %>

Phones View New:

New Phone Number

For <%=h @customer.full_name if @customer -%> <%=h @supplier.full_name if @supplier -%>
<% form_for :phone, :url => phones_path do |form| -%> <%= (hidden_field :customer, :id, :value => @customer.id) if @customer -%> <%= (hidden_field :supplier, :id, :value => @supplier.id) if @supplier -%> <%= render :partial => 'form', :object => form -%>

<%= submit_tag 'Create' -%>

<% end -%>

Phones View Show:

<% if @phone.phonable_type == ‘Customer’ -%>
Phone for

<%= link_to @phone.phonable.full_name, phonable_path(@phone.phonable)
-%>


<% end -%>

<% if @phone.phonable_type == ‘Supplier’ -%>
Phone for

<%= link_to @phone.phonable.full_name, supplier_path(@phone.phonable)
-%>


<% end -%>

Phones View _form :

<%= error_messages_for ‘phone’ %>

<%= form.hidden_field :phonable_type %>
<%= form.hidden_field :phonable_id %>

Created at
<%= datetime_select 'phone', 'created_at' %>

Updated at
<%= datetime_select 'phone', 'updated_at' %>

Tag for phone
<%= text_field 'phone', 'tag_for_phone' %>

Number
<%= text_field 'phone', 'number' %>

Country code
<%= text_field 'phone', 'country_code' %>

Area code
<%= text_field 'phone', 'area_code' %>

Local number
<%= text_field 'phone', 'local_number' %>

Routes:

map.resources :addresses
map.resources :phones
map.resources :suppliers do |supplier|
supplier.resources :supplier_phones,
:opaque_name => :phones,
:controller => :phones
supplier.resources :supplier_addresses,
:opaque_name => :addresses,
:controller => :addresses
end
map.resources :customers do |customer|
customer.resources :customer_phones,
:opaque_name => :phones,
:controller => :phones
customer.resources :customer_addresses,
:opaque_name => :addresses,
:controller => :addresses
end
end

Ok so thats it then, I have attached a word document if you want things
to be clearly labelled, please can someone help me to complete this
tricky situation thank you!!!