如何以编程方式定义外键?

时间:2011-01-06 12:27:02

标签: ruby-on-rails ruby database sqlite activerecord

Ruby 1.8.7-p249,Rails 2.3.8,SQLite3。

我想以编程方式创建2个表并定义它们之间的父子关系。 foreign_key方法在db迁移中有效,但在我的ActiveRecord :: Schema.define块中的代码中不起作用。

如何以编程方式创建外键?

代码:

# 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

错误:

-- 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

1 个答案:

答案 0 :(得分:0)

你已经大部分在那里,因为你使用[parent_table_name] _id的约定作为外键(Good work!)。 Rails使用约定优于配置模型,因此,由于您选择在发票表中命名外键order_id,Rails将自动确定order_id是order.id主键的外键。您需要做的就是在模型中指定has_many和belongs_to属性。

/app/models/order.rb

class Order < ActiveRecord::Base

  has_many :invoices

end


----------


/app/models/invoice.rb

class Invoice < ActiveRecord::Base

  belongs_to :order

end

注意:如果您在发票表中将外键命名为order_id以外的东西(在Rails中不推荐),让我们说schmorder_id,那么您可以指定它是订单模型中的外键,如下所示:

/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