我在使用Rails 4.2.4时遇到了一个奇怪的问题。我正在创建一个新表,引用其他一些表,如下所示:
t.references :local, index: true, foreign_key: true, null: false
t.references :serie, index: true, foreign_key: true, null: false
执行迁移时,创建外键约束时出错:
PG :: UndefinedColumn:ERROR:no existe la columna«series_id»referida en lallaveforánea
这是西班牙语
PG :: UndefinedColumn:ERROR:外键约束中引用的列«series_id»不存在
表示创建的表中没有“series_id”列。当然,它不应该是具有该名称的任何列。
FK生成应该寻找的正确列名是“serie_id”,它确实存在。
现在最奇怪的是它不会失败:例如,本地。它不会查找“locales_id”,而是查找正确的“local_id”,并创建相应的FK。
我有自定义的西班牙语变形,正确的复数是:
local - >区域设置
serie - >系列
然而我不明白为什么FK一代在一种情况下似乎是多元化而在另一种情况下却不是。
我在this answer找到了一个可行的解决方案,它特意声明了外键,例如:
add_foreign_key :turnos_registrados, :series, column: :serie_id
但我想知道的是为什么会发生这种情况。
提前致谢。
答案 0 :(得分:3)
似乎Rails执行此过程来获取外键列名:
迁移中引用的模型→(将符号转换为字符串)→复数→ singularize
在找到给定引用模型的表名时完成复数化,请参阅this line in the source code。然后,在从先前多元化的表名派生实际外键列时完成单一化(参见source here)。
然而,在英语中,“系列”是collective noun,因此单数和复数形式是相同的。 Rails默认处理这个问题:
"serie".pluralize
# => "series"
但也请注意:
serie
因此,首先将“s”附录添加到:serie
引用的模型名称中,然后单数化产生相同的单词 - “系列”。即Rails从您的迁移中为:serie → "serie" (conversion to string) → "series" (pluralize) → "series" (singularize)
引用的模型产生以下内容:
series_id
因此,这就是Rails尝试查找locales_id
外键列而不是add_foreign_key
的原因。
您写道,您设法使用series_id
手动添加了正确的密钥。我怀疑您稍后会遇到更多设置问题,因为Rails仍会尝试将外键导出为serie_id
。
您必须在关联中的任何位置指定正确的(ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 'serie', 'series'
end
)foreign_key,或者您应为您的案例定义自定义复数规则。该规则应添加为包含以下内容的初始化程序:
"series".singularize
# => "serie"
一旦你有了这个,复数将按照你的具体情况按预期工作:
{{1}}
使用这个自定义规则,我认为即使您的原始迁移也应该没有问题。
答案 1 :(得分:1)
感谢BoraMa's answer,我进一步发现了“为什么”:
似乎一些高优先级的Rails默认英语变形正在阻碍。
我有一个变形规则
inflect.singular(/((?<![aeiou][rndlj])e|a|i|o|u)s([A-Z]|_|$)/, '\1\2')
应该抓住
"series".singularize
因为
2.2.1 :006 > "series".gsub(/((?<![aeiou][rndlj])e|a|i|o|u)s([A-Z]|_|$)/,'\1\2')
=> "serie"
但它没有用。不知何故,添加建议的
inflect.irregular 'serie', 'series'
使它工作,但它应该没有。所以,我怀疑一些预先定义的规则,可以在控制台中确认(另一个BoraMa的贡献),因为对句子的回应
ActiveSupport::Inflector.inflections.singulars
将打印其他:[/(s)eries $ / i,“\ 1eries”]。
为了摆脱这些默认值,添加
inflect.clear
到inflections.rb成功了。现在它适用于我最初的一般规则。