Как определить внешний ключ программно? - PullRequest
1 голос
/ 06 января 2011

Ruby 1.8.7-p249, Rails 2.3.8, SQLite3.

Я хотел бы создать две таблицы программно и определить отношения между родителями и детьми. Метод foreign_key работает в миграциях БД, но в моем коде в блоке 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 голосов
/ 27 января 2011

Вы уже прошли большую часть пути, поскольку вы использовали соглашение [parent_table_name] _id для внешнего ключа (Хорошая работа!). Rails использует соглашение по модели конфигурации, поэтому, так как вы выбрали имя внешнего ключа order_id в таблице счетов, Rails автоматически выяснит, что order_id является внешним ключом первичного ключа order.id. Все, что вам нужно сделать, это указать в ваших моделях атрибуты has_many и assign_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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...