在Engine I have built中,我有3个类:书籍,类别和作者。每个类的迁移如下。作者和书籍之间以及类别和书籍之间存在一对多的关系。引擎将每个类命名为book_store
。在Postgresql(而不是sqlite)上使用相同的迁移时,我得到一个错误,其中一个类不存在PG::UndefinedTable: ERROR: relation "authors" does not exist
我不确定为什么会发生此错误。名称空间是否也应该在引用中?例如,从这个:
t.references :author, index: true, foreign_key: true
t.references :category, index: true, foreign_key: true
到此:
t.references :book_store_author, index: true, foreign_key: true
t.references :book_store_category, index: true, foreign_key: true
这似乎不起作用,因为BookStore::Books
中有一个名为book_store_author
和book_store_category
的属性会导致BookStore::Books.book_store_author
不属于引擎范围正常。
我是否可能需要更改迁移代码以在单独的行中反映引擎的命名空间?
# This migration comes from book_store (originally 20150814153615)
class CreateBookStoreAuthors < ActiveRecord::Migration
def change
create_table :book_store_authors do |t|
t.string :name
t.text :description
t.string :slug
t.timestamps null: false
end
add_index :book_store_authors, :slug, unique: true
end
end
# This migration comes from book_store (originally 20150814153710)
class CreateBookStoreCategories < ActiveRecord::Migration
def change
create_table :book_store_categories do |t|
t.string :title
t.text :description
t.string :slug
t.timestamps null: false
end
add_index :book_store_categories, :slug, unique: true
end
end
# This migration comes from book_store (originally 20150814153733)
class CreateBookStoreBooks < ActiveRecord::Migration
def change
create_table :book_store_books do |t|
t.string :title
t.string :lead
t.text :excerpt
t.text :description
t.decimal :price
t.integer :cover_type
t.integer :num_pages
t.string :isbn
t.integer :year
t.string :buy_link
t.string :size
t.string :cover_image
t.string :slug
t.references :author, index: true, foreign_key: true
t.references :category, index: true, foreign_key: true
t.timestamps null: false
end
add_index :book_store_books, :slug, unique: true
end
end
/home/deploy/apps/saturnalia_books/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.3/lib/active_record/migration.rb:797:in `migrate'
/home/deploy/apps/saturnalia_books/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.3/lib/active_record/tasks/database_tasks.rb:137:in `migrate'
/home/deploy/apps/saturnalia_books/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.3/lib/active_record/railties/databases.rake:44:in `block (2 levels) in <top (required)>'
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: relation "authors" does not exist
: ALTER TABLE "book_store_books" ADD CONSTRAINT "fk_rails_52f80cb3c5"
FOREIGN KEY ("author_id")
REFERENCES "authors" ("id")
/home/deploy/apps/saturnalia_books/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.3/lib/active_record/connection_adapters/postgresql/database_statements.rb:155:in `async_exec'
/home/deploy/apps/saturnalia_books/shared/bundle/ruby/2.2.0/gems/activerecord-4.2.3/lib/active_record/connection_adapters/postgresql/database_statements.rb:155:in `block in execute'
...
PG::UndefinedTable: ERROR: relation "authors" does not exist
答案 0 :(得分:1)
我通过更改模型和迁移文件解决了这个问题,如下所示。
我的blog
模型有很多tags
到tagging
模型。
所以我更新了tagging
模型,看起来像这样
module Blog class Tagging < ActiveRecord::Base belongs_to :tag, :class_name => "Blog::Tag" belongs_to :post, :class_name => "Blog::Post" end end
我修改了post
这样的模型。
module Blog class Post < ActiveRecord::Base has_many :taggings, :class_name => "Blog::Tagging" has_many :tags, through: :taggings end end
迁移文件修改如下
class CreateBlogTaggings < ActiveRecord::Migration def change create_table :blog_taggings do |t| t.integer :tag_id, index: true, foreign_key: true t.integer :post_id, index: true, foreign_key: true end end
因此,在您的情况下,将t.references :author
更改为t.integer :author _id
,将t.references :category
更改为t.integer :category_id
。
这可以解决您的迁移问题。
答案 1 :(得分:1)
您将获得PG::UndefinedTable
,因此无法找到您尝试引用的表author
我的psql。并且无法找到它,因为表在此处book_store_authors
create_table :book_store_authors
。
我不确定为什么它在sqlite上运行,但是当你创建模型时你肯定需要传递一个完整有效的表名(如果是用户,我的意思是单数形式,如果你因某种原因创建用户,则是复数形式)模型)到t.belongs_to
和t.references
答案 2 :(得分:0)
这确实是由于PostgreSql不了解如何在没有命名空间的情况下在表之间建立桥梁
您只需更改迁移文件即可解决此问题。
在您的图书迁移文件中:
变化
t.references :author, index: true, foreign_key: true
t.references :category, index: true, foreign_key: true
与
t.references :author
t.references :category
然后在你的行
之后add_index :book_store_books, :slug, unique: true
添加此
add_index(:book_store_books, 'author_id', :name => 'index_books_on_author')
add_index(:book_store_books, 'category_id', :name => 'index_books_on_category')
这些行手动创建表book_store_books的索引
此处有更多信息:http://apidock.com/rails/v4.2.1/ActiveRecord/ConnectionAdapters/SchemaStatements/add_index
不需要foreign_keys,但您仍然可以使用相同的方法添加它们
有了这个,您不必更改应用程序中的任何内容,postgresql知道如何管理命名空间表之间的引用
答案 3 :(得分:0)
问题在于foreign_key,rails api用于添加外键使用表名而不是模型名。如果你写这样的复合线:
t.references :author, index: true, foreign_key: true
它将生成2个单独的命令:
add_column :book_store_books, :author_id, index: true
add_foreign_key :book_store_books, :authors
第二个命令将导致undefined relation "authors"
可以通过使用2个单独的命令来修复:
t.references :author, index: true
和add_foreign_key :book_store_books, book_store_authors
所以你的移植文件是:
class CreateBookStoreBooks < ActiveRecord::Migration
def change
create_table :book_store_books do |t|
# more lines go here
# ...
# bonus: you can define you slug unique index inline
t.string :slug, index: true, unique: true
t.references :author, index: true
t.references :category, index: true
end
add_foreign_key :book_store_books, book_store_authors, column: :author_id
add_foreign_key :book_store_books, book_store_categories, column: :category_id
end
end