首页 文章

Rails迁移:add_reference到表但外键比Rails公约的列名不同

提问于
浏览
42

我有以下两种型号:

class Store < ActiveRecord::Base
    belongs_to :person
end

class Person < ActiveRecord::Base
    has_one :store
end

这是问题所在:我正在尝试创建迁移以在people表中创建外键 . 但是,引用Store外键的列未命名为store_id,因为它是rails约定,而是命名为foo_bar_store_id .

如果我遵循rails约定,我会像这样进行迁移:

class AddReferencesToPeople < ActiveRecord::Migration
  def change
    add_reference :people, :store, index: true
  end
end

但是这不起作用,因为列名不是 store_id ,而是 foo_bar_store_id . 那么我如何指定外键名称只是不同,但仍保持索引:true以保持快速性能?

6 回答

  • 3

    AddReferencesToPeople 迁移中,您可以使用以下方法手动添加字段和索引:

    add_column :people, :foo_bar_store_id, :integer
    add_index :people, :foo_bar_store_id
    

    然后让你的模型像这样知道外键:

    class Person < ActiveRecord::Base
      has_one :store, foreign_key: 'foo_bar_store_id'
    end
    
  • 2

    在Rails 4.2中,您还可以使用自定义外键名称设置模型或迁移 . 在您的示例中,迁移将是:

    class AddReferencesToPeople < ActiveRecord::Migration
      def change
        add_column :people, :foo_bar_store_id, :integer, index: true
        add_foreign_key :people, :stores, column: :foo_bar_store_id
      end
    end
    

    Here是关于此主题的有趣博客文章 . Here是Rails指南中的半隐藏部分 . 这篇博文绝对帮助了我 .

    对于关联,显式地声明这样的外键或类名(我认为你的原始关联被切换为'belongs_to'在具有外键的类中):

    class Store < ActiveRecord::Base
      has_one :person, foreign_key: :foo_bar_store_id
    end
    
    class Person < ActiveRecord::Base
      belongs_to :foo_bar_store, class_name: 'Store'
    end
    

    请注意,class_name项必须是字符串 . foreign_key项可以是字符串或符号 . 这实际上允许您使用语义命名的关联访问漂亮的ActiveRecord快捷方式,如下所示:

    person = Person.first
    person.foo_bar_store
    # returns the instance of store equal to person's foo_bar_store_id
    

    有关belongs_tohas_one文档中的关联选项的更多信息,请参阅 .

  • 1

    在较新的rails中,您可以使用不同的名称向表中添加外键,如下所示:

    class AddFooBarStoreToPeople < ActiveRecord::Migration[5.0]
      def change
        add_reference :people, :foo_bar_store, foreign_key: { to_table: :stores }
      end
    end
    
  • 58
    # Migration
    change_table :people do |t|
      t.references :foo_bar_store, references: :store #-> foo_bar_store_id
    end
    
    # Model
    # app/models/person.rb
    class Person < ActiveRecord::Base
      has_one :foo_bar_store, class_name: "Store"
    end
    
  • 5

    为了扩展schpet的答案,这适用于 create_table Rails 5迁移指令,如下所示:

    create_table :chapter do |t|
      t.references :novel, foreign_key: {to_table: :books}
      t.timestamps
    end
    
  • 49

    在封面下,add_reference只是委托给add_column和add_index,所以你只需要自己处理:

    add_column :people, :foo_bar_store_id, :integer
    add_index :people, :foo_bar_store_id
    

相关问题