提问



我想在Ruby on Rails迁移脚本中创建一个列unique。最好的方法是什么?还有一种方法可以索引表中的列吗?


我想在数据库中强制执行unique列而不是仅使用:validate_uniqueness_of

最佳参考


简短的回答:


add_index :table_name, :column_name, unique: true


要将多个列索引在一起,可以传递一组列名而不是一个列名,


add_index :table_name, [:column_name_a, :column_name_b], unique: true


对于更细粒度的控制,有一个execute方法执行直接SQL。


而已!


如果您将此作为常规旧模型验证的替代,只需检查它是如何工作的。我不确定向用户报告的错误是否会很好。您可以随时执行这两项操作。

其它参考1



  rails生成迁移add_index_to_table_name column_name:uniq



要么



  rails生成迁移add_column_name_to_table_name column_name:string:uniq:index



生成


class AddIndexToModerators < ActiveRecord::Migration
  def change
    add_column :moderators, :username, :string
    add_index :moderators, :username, unique: true
  end
end


如果您要在现有列中添加索引,请删除或注释add_column行,或进行检查


add_column :moderators, :username, :string unless column_exists? :moderators, :username

其它参考2


由于这还没有被提及但回答了我在找到这个页面时遇到的问题,你还可以指定索引在通过t.referencest.belongs_to添加时应该是唯一的:


create_table :accounts do |t|
  t.references :user, index: { unique: true } # or t.belongs_to

  # other columns...
end


(截至至少Rails 4.2.7)

其它参考3


我使用Rails 5,上面的答案很有效;这是另一种对我有用的方法(表名是:people,列名是:email_address)


class AddIndexToEmailAddress < ActiveRecord::Migration[5.0]
  def change
    change_table :people do |t|
      t.index :email_address, unique: true
    end
  end
end

其它参考4


如果要创建新表,可以使用内联快捷方式:


  def change
    create_table :posts do |t|
      t.string :title, null: false, index: {unique: true}
      t.timestamps
    end
  end

其它参考5


add_index :table_name, :column_name, unique: true


要将多个列索引在一起,可以传递一组列名而不是一个列名。

其它参考6


您可能希望为唯一键添加名称,因为rails的默认unique_key名称可能太长,DB可能会抛出错误。


要为索引添加名称,只需使用name:选项。
迁移查询可能看起来像这样 -


add_index :table_name, [:column_name_a, :column_name_b, ... :column_name_n], unique: true, name: 'my_custom_index_name'


更多信息 - http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/add_index [21]