class Order < ActiveRecord::Base
belongs_to :customer
end
class Customer < ActiveRecord::Base
has_many :orders
end
# some data
test_dev=# SELECT * FROM customers;
id | name
----+----------------
1 | Robby
2 | Nigel
3 | robby on rails
(3 rows)
test_dev=# SELECT * FROM orders;
id | customer_id | amount
----+-------------+--------
1 | 1 | 12.00
2 | 3 | 12.00
(2 rows)
# CONSOLE
RobbyOnRails:~/Programming/footest robbyrussell$ ./script/console
Loading development environment.
>> cust = Customer.find(3)
=> #<Customer:0x2751ce8 @attributes={"name"=>"robby on rails", "id"=>"3"}>
>> cust.orders
=> [#<Order:0x274e4d0 @attributes={"id"=>"2", "amount"=>"12.00", "customer_id"=>"3"}>]
>> Customer.destroy(3)
ActiveRecord::StatementInvalid: ERROR: update or delete on "customers" violates foreign key constraint "orders_customer_id_fkey" on "orders"
DETAIL: Key (id)=(3) is still referenced from table "orders".
: DELETE FROM customers
WHERE id = 3
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.11.1/lib/active_record/connection_adapters/abstract_adapter.rb:462:in `log' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.11.1/lib/active_record/connection_adapters/postgresql_adapter.rb:109:in `execute'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.11.1/lib/active_record/connection_adapters/postgresql_adapter.rb:113:in `delete'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.11.1/lib/active_record/base.rb:972:in `destroy_without_callbacks'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.11.1/lib/active_record/callbacks.rb:321:in `destroy_without_transactions'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.11.1/lib/active_record/transactions.rb:124:in `destroy'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.11.1/lib/active_record/transactions.rb:124:in `transaction'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.11.1/lib/active_record/transactions.rb:93:in `transaction'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.11.1/lib/active_record/transactions.rb:120:in `transaction'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.11.1/lib/active_record/transactions.rb:124:in `destroy'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.11.1/lib/active_record/base.rb:420:in `destroy'
from (irb):3
>> Customer.delete(3)
ActiveRecord::StatementInvalid: ERROR: update or delete on "customers" violates foreign key constraint "orders_customer_id_fkey" on "orders"
DETAIL: Key (id)=(3) is still referenced from table "orders".
: DELETE FROM customers WHERE id IN (3)
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.11.1/lib/active_record/connection_adapters/abstract_adapter.rb:462:in `log' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.11.1/lib/active_record/connection_adapters/postgresql_adapter.rb:109:in `execute'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.11.1/lib/active_record/connection_adapters/postgresql_adapter.rb:113:in `delete'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.11.1/lib/active_record/base.rb:445:in `delete_all'
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.11.1/lib/active_record/base.rb:414:in `delete'
from (irb):4
>>
# with dependent
class Customer < ActiveRecord::Base
has_many :orders, :dependent => true
end
This fixed that problem.
Okay, so now I will drop my table constraint and test this without the dependent. It should set the order.customer_id to null, right?
test_dev# \d orders
Table "public.orders"
Column | Type | Modifiers
-------------+---------------+--------------------------------------------------------
id | integer | not null default nextval('public.orders_id_seq'::text)
customer_id | integer |
amount | numeric(10,2) |
Indexes:
"orders_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"orders_customer_id_fkey" FOREIGN KEY (customer_id) REFERENCES customers(id)
test_dev=# ALTER TABLE orders DROP CONSTRAINT orders_customer_id_fkey;
ALTER TABLE
RobbyOnRails:~/Programming/footest robbyrussell$ ./script/console
Loading development environment.
>> cust = Customer.create(:name => 'Jim')
=> #<Customer:0x275373c @new_record_before_save=true, @new_record=false, @attributes={"name"=>"Jim", "id"=>5}, @errors=#<ActiveRecord::Errors:0x274fa88 @base=#<Customer:0x275373c ...>, @errors={}>>
>> cust.orders.create(:amount => '25.00')
=> #<Order:0x274991c @new_record=false, @attributes={"id"=>4, "amount"=>"25.00", "customer_id"=>5}, @errors=#<ActiveRecord::Errors:0x2746dfc @base=#<Order:0x274991c ...>, @errors={}>>
>>
test_dev=# SELECT * FROM orders;
id | customer_id | amount
----+-------------+--------
1 | 1 | 12.00
3 | 4 | 29.00
4 | 5 | 25.00
(3 rows)
Okay, now if I destroy that last customer, it should set customer_id to null, right?
RobbyOnRails:~/Programming/footest robbyrussell$ ./script/console
Loading development environment.
>> Customer.destroy(5)
=> {"name"=>"Jim", "id"=>"5"}
>>
=# SELECT * FROM orders;
id | customer_id | amount
----+-------------+--------
1 | 1 | 12.00
3 | 4 | 29.00
4 | 5 | 25.00
(3 rows)
Okay, so I got the :dependent part. However, in figuring this out, I found that Active Record is not setting the value of customer_id to NULL when I delete that specific customer from the customers table. This is in PostgreSQL... this leaves me with some semi-bad data when I have a table relationship that doesn't require the use of 'dependent'