![](/img/trans.png)
[英]Index name too long on rails activerecord migration. Tried adding index manually, same error
[英]How do I handle too long index names in a Ruby on Rails ActiveRecord migration?
我正在嘗試添加一個從四個關聯表的外鍵創建的唯一索引:
add_index :studies,
["user_id", "university_id", "subject_name_id", "subject_type_id"],
:unique => true
數據庫對索引名稱的限制導致遷移失敗。 這是錯誤消息:
表 'studies' 上的索引名稱 'index_studies_on_user_id_and_university_id_and_subject_name_id_and_subject_type_id' 太長; 限制為 64 個字符
我該如何處理? 我可以指定不同的索引名稱嗎?
為add_index
提供:name
選項,例如:
add_index :studies,
["user_id", "university_id", "subject_name_id", "subject_type_id"],
unique: true,
name: 'my_index'
如果在create_table
塊中的references
上使用:index
選項,它將采用與add_index
相同的選項哈希作為其值:
t.references :long_name, index: { name: :my_index }
您還可以更改create_table
塊中列定義中的索引名稱(例如您從遷移生成器中獲取)。
create_table :studies do |t|
t.references :user, index: {:name => "index_my_shorter_name"}
end
在 PostgreSQL 中, 默認限制是 63 個字符。 因為索引名稱必須是唯一的,所以有一點約定很好。 我使用(我調整了示例以解釋更復雜的結構):
def change
add_index :studies, [:professor_id, :user_id], name: :idx_study_professor_user
end
正常的索引應該是:
:index_studies_on_professor_id_and_user_id
邏輯是:
index
變成idx
_id
這通常可以完成這項工作。
你也可以這樣做
t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
與上一個答案類似:只需將 'name' 鍵與常規 add_index 行一起使用:
def change
add_index :studies, :user_id, name: 'my_index'
end
恐怕這些解決方案都不適合我。 也許是因為我在 create_table 遷移中使用了belongs_to
來實現多態關聯。
我將在下面添加我的代碼和解決方案的鏈接,以防其他人在搜索與多態關聯相關的“索引名稱太長”時偶然發現。
以下代碼對我不起作用:
def change
create_table :item_references do |t|
t.text :item_unique_id
t.belongs_to :referenceable, polymorphic: true
t.timestamps
end
add_index :item_references, [:referenceable_id, :referenceable_type], name: 'idx_item_refs'
end
這段代碼對我有用:
def change
create_table :item_references do |t|
t.text :item_unique_id
t.belongs_to :referenceable, polymorphic: true, index: { name: 'idx_item_refs' }
t.timestamps
end
end
這是幫助我的 SO Q&A: https : //stackoverflow.com/a/30366460/3258059
我有一個經常使用生成器的項目,需要它是自動的,所以我從 rails 源復制了index_name
函數來覆蓋它。 我在config/initializers/generated_index_name.rb
添加了這個:
# make indexes shorter for postgres
require "active_record/connection_adapters/abstract/schema_statements"
module ActiveRecord
module ConnectionAdapters # :nodoc:
module SchemaStatements
def index_name(table_name, options) #:nodoc:
if Hash === options
if options[:column]
"ix_#{table_name}_on_#{Array(options[:column]) * '__'}".slice(0,63)
elsif options[:name]
options[:name]
else
raise ArgumentError, "You must specify the index name"
end
else
index_name(table_name, index_name_options(options))
end
end
end
end
end
它創建像ix_assignments_on_case_id__project_id
這樣的索引,如果它仍然太長,則將其截斷為 63 個字符。 如果表名很長,那仍然是不唯一的,但是您可以添加復雜性,例如將表名與列名分開縮短或實際檢查唯一性。
請注意,這是來自 Rails 5.2 項目; 如果您決定這樣做,請從您的版本中復制源代碼。
我有這個問題,但有timestamps
功能。 它在 updated_at 上自動生成一個超過 63 個字符限制的索引:
def change
create_table :toooooooooo_loooooooooooooooooooooooooooooong do |t|
t.timestamps
end
end
表 'tooooooooooo_looooooooooooooooooooooooooooong' 上的索引名稱 'index_tooooooooooo_looooooooooooooooooooooooooooooong_on_updated_at' 太長; 限制為 63 個字符
我嘗試使用timestamps
來指定索引名稱:
def change
create_table :toooooooooo_loooooooooooooooooooooooooooooong do |t|
t.timestamps index: { name: 'too_loooooooooooooooooooooooooooooong_updated_at' }
end
end
但是,這會嘗試將索引名稱應用於updated_at
和created_at
字段:
表 'toooooooooo_looooooooooooooooooooooooooooooong' 上的索引名稱 'too_long_updated_at' 已經存在
最后我放棄了timestamps
,只是創建了很長的時間戳:
def change
create_table :toooooooooo_loooooooooooooooooooooooooooooong do |t|
t.datetime :updated_at, index: { name: 'too_long_on_updated_at' }
t.datetime :created_at, index: { name: 'too_long_on_created_at' }
end
end
這有效,但我很想知道是否可以使用timestamps
方法!
create_table :you_table_name 做 |t| t.references :studant, index: { name: 'name_for_studant_index' } t.references :teacher, index: { name: 'name_for_teacher_index' } end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.