2016-10-24 2 views
0

Я использую PostgreSQL в качестве моего db в рельсах. У меня есть модель User и модель продукта. Я пытаюсь создать модель транзакции, где я хочу обратиться к пользователю дважды, один раз в качестве покупателя и один раз в качестве продавца. Я создал модели, предложенные в этой статье (ответ toasterlovin) Write a migration with reference to a model twice Однако это дает мне ошибку, когда я использую PostgreSQL (с SQLite он работал нормально). Я получаю следующую ошибку. Что я могу сделать, чтобы решить эту проблему?Ссылка на таблицу дважды в rails/postgres

{StandardError: An error has occurred, this and all later migrations canceled:

PG::UndefinedTable: ERROR: relation "buyers" does not exist
: ALTER TABLE "transactions" ADD CONSTRAINT "fk_rails_0b24a7fcc3"
FOREIGN KEY ("buyer_id")
REFERENCES "buyers" ("id")
C:/Users/Powerhouse/Desktop/CodingDojo/ruby/rails/demo/db/migrate/20161024032156_create_transactions.rb:3:in change'
C:in
migrate'
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: relation "buyers" does not exist
: ALTER TABLE "transactions" ADD CONSTRAINT "fk_rails_0b24a7fcc3"
FOREIGN KEY ("buyer_id")
REFERENCES "buyers" ("id")
C:/Users/Powerhouse/Desktop/CodingDojo/ruby/rails/demo/db/migrate/20161024032156_create_transactions.rb:3:in change'
C:in
migrate'
PG::UndefinedTable: ERROR: relation "buyers" does not exist
C:/Users/Powerhouse/Desktop/CodingDojo/ruby/rails/demo/db/migrate/20161024032156_create_transactions.rb:3:in change'
C:in
migrate'
Tasks: TOP => db:migrate
(See full trace by running task with --trace) }

Модели

class User < ActiveRecord::Base 
    has_many :products 
    has_many :sales, :class_name => 'Transaction', :foreign_key => 'seller_id' 
    has_many :purchases, :class_name => 'Transaction', :foreign_key => 'buyer_id 
end 

Модель продукта

class Product < ActiveRecord::Base 
    belongs_to :user 
end 

модель транзакций

class Transaction < ActiveRecord::Base 
    belongs_to :buyer, :class_name => 'User' 
    belongs_to :seller, :class_name => 'User' 
    belongs_to :product 
end 

миграции файлов

Пользователь

class CreateUsers < ActiveRecord::Migration 
    def change 
    create_table :users do |t| 
     t.string :name 
     t.timestamps null: false 
    end 
    end 
end 

Продукт

class CreateProducts < ActiveRecord::Migration 
    def change 
    create_table :products do |t| 
     t.references :user, index: true, foreign_key: true 
     t.string :name 

     t.timestamps null: false 
    end 
    end 
end 

Transaction

class CreateTransactions < ActiveRecord::Migration 
    def change 
    create_table :transactions do |t| 
     t.references :buyer, index: true, foreign_key: true 
     t.references :seller, index: true, foreign_key: true 
     t.references :product, index: true, foreign_key: true 

     t.timestamps null: false 
    end 
    end 
end 
+0

вставьте свои модели. – Sravan

+0

Код для моделей и миграции добавлен @Sravan – commonsensei

ответ

1

Это связано с PostgreSql не понимая, как сделать заказ ассоциации внешних ключей.

Попробуйте изменить файл миграции в,

class CreateTransactions < ActiveRecord::Migration 
    def change 
    create_table :transactions do |t| 
     t.integer :buyer_id 
     t.integer :seller_id 
     t.integer :product_id 

     t.timestamps null: false 
    end 
    add_index(:transactions, :buyer_id) 
    add_index(:transactions, :seller_id) 
    add_index(:transactions, :product_id) 
    add_foreign_key :transactions, :users, column: :buyer_id 
    add_foreign_key :transactions, :users, column: :seller_id 
    end 
end 

Он автоматически связывает buyer_id с user, взяв власть в

belongs_to :buyer, :class_name => 'User'

выше линии делает buyer_id как внешний ключ.

Вы также можете попробовать,

class CreateTransactions < ActiveRecord::Migration 
    def change 
    create_table :transactions do |t| 
     t.references :buyer, index: true 
     t.references :seller, index: true 
     t.references :product, index: true 
     t.timestamps null: false 
    end 
    add_foreign_key :transactions, :users, column: :buyer_id 
    add_foreign_key :transactions, :users, column: :seller_id 
    end 
end 
+0

@commonsensei, вы пробовали это? – Sravan

+0

Но это отбрасывает FK в базе данных, поэтому вы выбрасываете ссылочную целостность. –

+0

, но он по-прежнему относится к отношениям 'user' to' transaction' и будет работать как ожидалось. Вы говорите о втором подходе? – Sravan

0

Ваша проблема в том, что, когда ActiveRecord увидеть это:

t.references :buyer, index: true, foreign_key: true 

пытается создать внешний ключ в базе данных (так как foreign_key: true), но соглашения об именах сообщают AR, что он должен быть связан с таблицей buyers (потому что вы ссылаетесь на :buyer).

Так же, как вы определяете class_name: в модели:

belongs_to :buyer, :class_name => 'User' 

сказать AR не использовать обычные Buyer имя, которое вы можете изменить соглашение в вашей миграции путем изменения :foreign_key вариант:

t.references :buyer, index: true, foreign_key: { to_table: :users } 

для явного указания таблицы.Аналогично для вашей другой ссылки, которая не использует обычную схему именования:

t.references :seller, index: true, foreign_key: { to_table: :users } 
+0

Спасибо за ответ mu слишком короткий .. Я вроде как этот подход тоже. Есть ли способ указать, какой to_table при использовании команды generate в команде promt ... rails g model. Операции покупателя: ссылки? – commonsensei

+0

Не то, чтобы я знал. Генераторы предназначены для покрытия распространенных случаев, нет ничего плохого в том, чтобы регулировать их выход, и вы должны понимать, что они генерируют в любом случае. –

+0

Спасибо за ответ mu .. оцените его .. – commonsensei

Смежные вопросы