Ruby 1.8.7-p249, Rails 2.3.8, SQLite3.
I'd like to create 2 tables programatically and define parent-child relationship between them. The foreign_key method does work in db migrations but it doesn't work in my code in ActiveRecord::Schema.define block .
How do I create a foreign key programatically?
Code:
# To change this template, choose Tools | Templates
# and open the template in the editor.
require "rubygems"
require "active_record"
require "logger"
require "pp"
ActiveRecord::Base.logger = Logger.new($stdout)
ActiveRecord::Base.establish_connection(
:adapter => "sqlite3",
:database => "../db/development_mp.sqlite3"
)
ActiveRecord::Schema.define do
create_table :orders, :force => true do |t|
t.string :name
t.timestamps
end
create_table :invoices, :force => true do |t|
t.integer :order_id
t.timestamps
end
# Error!
foreign_key(:invoices, :order_id, :orders)
end
Error:
-- foreign_key(:invoices, :order_id, :orders) D:/Ruby/bitnami-rubystack-2.1-0/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.8/lib/active_record/migration.rb:352:in `send': undefined method `foreign_key' for
#<ActiveRecord::ConnectionAdapters::SQLite3Adapter:0x554f2f8> (NoMethodError)
from D:/Ruby/bitnami-rubystack-2.1-0/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.8/lib/active_record/migration.rb:352:in `method_missing'
from D:/Ruby/bitnami-rubystack-2.1-0/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.8/lib/active_record/migration.rb:328:in `say_with_time'
from D:/Ruby/bitnami-rubystack-2.1-0/ruby/lib/ruby/1.8/benchmark.rb:293:in `measure'
from D:/Ruby/bitnami-rubystack-2.1-0/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.8/lib/active_record/migration.rb:328:in `say_with_time'
from D:/Ruby/bitnami-rubystack-2.1-0/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.8/lib/active_record/migration.rb:348:in `method_missing'
from D:/prg/Ruby/Pragmatic.Agile-Web-Development-With-Rails-Third-Edition/active_record_basics/lib/has_one_mp.rb:29
from D:/Ruby/bitnami-rubystack-2.1-0/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.8/lib/active_record/schema.rb:47:in `instance_eval'
from D:/Ruby/bitnami-rubystack-2.1-0/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.8/lib/active_record/schema.rb:47:in `define'
from D:/prg/Ruby/Pragmatic.Agile-Web-Development-With-Rails-Third-Edition/active_record_basics/lib/has_one_mp.rb:16
You're already most of the way there, since you used the convention of [parent_table_name]_id for the foreign key (Good work!). Rails uses the convention over configuration model, so since you chose to name your foreign key order_id in your invoices table Rails will automatically figure out that order_id is the foreign key to the order.id primary key. All you need to do is specify in your models the has_many and belongs_to attributes.
/app/models/order.rb
class Order < ActiveRecord::Base
has_many :invoices
end
----------
/app/models/invoice.rb
class Invoice < ActiveRecord::Base
belongs_to :order
end
Note: If you named your foreign key in the invoices table something besides order_id (not recommended in Rails), let's say schmorder_id, then you would specify that it is the foreign key in your order model like such:
/app/models/order.rb
class Order < ActiveRecord::Base
#if the foreign_key in your invoices table was named schmorder_id...
has_many :invoices, :foreign_key => "schmorder_id"
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.