Rails 4.2引擎引用列迁移失败PG :: UndefinedTable:错误:在postgresql中

时间:2015-08-30 22:16:52

标签: ruby-on-rails postgresql

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

修改

here is the full stack trace

4 个答案:

答案 0 :(得分:1)

我通过更改模型和迁移文件解决了这个问题,如下所示。

我的blog模型有很多tagstagging模型。

所以我更新了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_tot.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: trueadd_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