2016-04-07 3 views
1

Je rencontre un problème étrange avec Rails 4.2.4. Je crée une nouvelle table, qui fait référence à d'autres, comme ceci:La pluralisation incorrecte du nom de la colonne lors de la création de la clé étrangère

t.references :local, index: true, foreign_key: true, null: false 
t.references :serie, index: true, foreign_key: true, null: false 

quand j'exécute la migration, il y a une erreur lors de la création de la contrainte de clé étrangère:

PG::UndefinedColumn: ERROR: no existe la columna «series_id» referida en la llave foránea

qui est espagnol

PG::UndefinedColumn: ERROR: column «series_id» referenced in foreign key constraint does not exist

signifie qu'il n'y a pas de colonne "id_série" dans la table créée. Bien sûr, il ne devrait pas y avoir de colonne avec ce nom.

Le nom de colonne correct que la génération de FK devrait rechercher est "serie_id", et il existe.

Maintenant, la chose la plus étrange est qu'elle ne manque pas pour: local, par exemple. Il ne cherche pas "locales_id", mais "local_id" qui est correct, et le FK correspondant est créé.

J'ai flexions coutume espagnole, et pluralisations sont correctes:

local -> locales

serie -> series

mais je ne comprends pas pourquoi la génération FK semble pluralisation dans un cas et pas dans l'autre.

J'ai trouvé une solution de travail dans this answer, qui est spécifiquement les clés déclarant étrangères, comme:

add_foreign_key :turnos_registrados, :series, column: :serie_id 

mais ce que je voudrais savoir pourquoi est-ce qui se passe.

Merci d'avance.

Répondre

2

Il semble que Rails ne fait cette procédure pour obtenir le nom de colonne de clé étrangère:

    modèle référencé dans la migration → (conversion symbole string) → pluralizesingularisent

La pluralisation est fait lors de la recherche d'un nom de table pour le modèle référencé donné, voir this line in the source code. Ensuite, la singularisation est effectuée lors de la dérivation de la colonne clé étrangère réelle du nom de table précédemment pluralisé (voir le source here).

Cependant, en anglais, "series" est un collective noun, de sorte que les formes au singulier et pluriel sont les mêmes. Poignées Rails ce correctement par défaut:

"series".pluralize 
# => "series" 

"series".singularize 
# => "series" 

Mais notez aussi ceci:

"serie".pluralize 
# => "series" 

Ainsi, le « s » annexe est d'abord ajouté au nom du modèle référencé serie et la singularisation donne le même mot - "séries". C'est à dire.Rails donnent les éléments suivants pour le :serie modèle référencé à partir de votre migration:

:serie → "serie" (conversion to string) → "series" (pluralize) → "series" (singularize) 

Donc, ce pourquoi Rails essaie de chercher series_id colonne de clé étrangère, mais pas pour locales_id.

Vous écrivez que vous avez réussi à ajouter manuellement la bonne clé en utilisant add_foreign_key. Je suspecte que vous rencontrerez plus de problèmes avec votre installation plus tard car Rails essayera toujours de dériver la clé étrangère comme series_id. Vous devez spécifier la bonne clé étrangère (serie_id) partout dans vos associations ou définir une règle de pluralisation personnalisée pour votre cas. La règle devrait être ajoutée comme un initialiseur qui contient:

ActiveSupport::Inflector.inflections do |inflect| 
    inflect.irregular 'serie', 'series' 
end 

Une fois que vous avez cela, la pluralisation fonctionnera comme prévu pour votre cas particulier:

"series".singularize 
# => "serie" 

Et avec cette règle personnalisée, je pense que même Votre migration d'origine devrait fonctionner sans problèmes.

+0

Merci, BoraMa. Votre réponse est très détaillée et vous avez raison, même les migrations ont fonctionné. Je suis allé plus loin et j'ai trouvé une autre solution, je vais l'ajouter comme réponse. – user2553863

1

Merci à BoraMa's answer, je suis allé plus loin et a trouvé le « pourquoi »:

semble que certains Rails prioritaires par défaut flexions en anglais ont été se mettre en travers.

J'ai une règle d'inflexion

inflect.singular(/((?<![aeiou][rndlj])e|a|i|o|u)s([A-Z]|_|$)/, '\1\2') 

qui devrait prendre un

"series".singularize 

depuis

2.2.1 :006 > "series".gsub(/((?<![aeiou][rndlj])e|a|i|o|u)s([A-Z]|_|$)/,'\1\2') 
=> "serie" 

mais il ne fonctionnait pas. D'une manière ou d'une autre, en ajoutant le

inflect.irregular 'serie', 'series' 

fait fonctionner, mais cela devrait fonctionner sans trop. Alors, je me doutais d'une règle prédéfinie, qui peut être confirmée (la contribution d'une autre Borama) dans la console parce que la réponse à la phrase

ActiveSupport::Inflector.inflections.singulars 

imprimera entre autres: [/ (s) eries $/i , "\ 1eries"].

Afin de se débarrasser de ces valeurs par défaut, en ajoutant

inflect.clear 

à inflections.rb fait. Maintenant, cela fonctionne avec la règle plus générale que j'avais à l'origine.

+0

Aah, je vois, il y a en effet une règle de singularisation par défaut dans Rails pour "series" → "series". Voyez par vous-même dans la console: 'ActiveSupport :: Inflector.inflections.singulars' va imprimer entre autres:' [/ (s) eries $/i, "\\ 1eries"] '. – BoraMa

+1

Merci encore, vous m'avez aidé à mieux comprendre comment tout ce travail. Je vais l'ajouter à la réponse. – user2553863