2010-09-17 7 views
0

Désolé si cette question semble simple, je suis très très nouveau sur Rails (j'ai commencé à apprendre il y a quelques jours), mais après avoir consulté Google et "Développement Web Agile avec Rails" je ne trouve pas la réponse .Rails Clé étrangère Numéro

J'ai un problème avec Rails 2.3.8 créant une clé étrangère sur deux modèles. Mes tables ressemblent à ceci:

cars         manufacturer 
----         ------------ 
car_make        name 
car_model       country 
car_class       logo_url 
image_url       (and default 'id' created by Rails) 
manufacturer_id 
(and default 'id' created by Rails) 

Mes champs 'car_make' et 'name' sont essentiellement les mêmes; chaque voiture que je crée, je veux être en mesure de l'associer à un fabricant existant. C'est la colonne que j'essaie de créer FK.

Mon car.rb a 'belongs_to: manufacturer', et mon manufacturer.rb a 'has_many: cars' pour établir un rapport de un fabricant à plusieurs voitures. Cependant, lorsque je crée une nouvelle voiture (via un échafaudage), le champ manufacturer_id est vide.

Je suis allé à mon cars_controller, a trouvé la méthode « créer » qui est utilisé, et essayé d'ajouter la deuxième ligne ci-dessous:

@car = Car.new(params[:car]) 
@car.manufacturer_id = car.manufacturer.id # <=== 

Cela produit un « NameError dans CarsController # créer » erreur, et Je vois:

undefined local variable or method 'car' for #<CarsController:0x1034642f0> 

Rails ne semble pas aimer la ligne que j'ai ajoutée. Qu'est-ce qui me manque pour faire ce travail?

Répondre

0

Eh bien, vous devez avoir un fabricant disponible avant de pouvoir l'attacher à la voiture.

@car = Car.new(params[:car]) 
m = Manufacturer.first # => as you can see you must already have one made 
@car.manufacturer = m 
@car.save 

La raison car est non défini est parce que, eh bien, vous ne l'avez pas définir. Quel constructeur de voiture voulez-vous attribuer à @car?

Donc, fondamentalement, vous devez faire un fabricant avant de faire une voiture. Si le formulaire que vous remplissez a les données pour le fabricant, alors assurez-vous de mettre cela sous une clé différente dans les paramètres, comme, par exemple, params[:manufacturer] et faire une chose similaire à celle que vous faites avec la voiture. Peut-être comme:

@car = Car.new(params[:car]) 
@manufacturer = Manufacturer.find_or_create_by_name_and_country(params[:manufacturer][:name], params[:manufacturer][:country]) 
@car.manufacturer = @manufacturer 
@car.save 
+0

Ah c'est logique. Je veux trouver le bon manufacturer_id correspondant au champ car_make. Par exemple, si ma table Manufacturer est remplie avec 'Acura', 'Honda' et 'Toyota' sous la colonne des noms, et que je crée une nouvelle voiture avec car_make 'Honda', je veux trouver le bon manufacturer_id qui est dans la rangée 'Honda'. – Anon

+0

Ah ah, alors vous ne devriez pas faire ça. Car make doit être trouvé via 'car.manufacturer.name', pas dupliqué sur la voiture elle-même! – rfunduk

+0

Afin de le pirater pour que cela fonctionne (* mauvaise idée *), vous pouvez essayer: '@car.manufacturer = Manufacturer.find_by_name (@ car.car_make); @ car.save' qui va essayer de trouver le manuf par le champ car_make de la voiture que vous venez de mettre à jour ... Encore une fois, va avoir un mauvais moment si vous allez trop loin dans ce chemin :) – rfunduk

0

À votre avis, vous voulez générer une liste déroulante pour les fabricants (je suppose), de sorte que vous devriez faire quelque chose comme ceci sous la forme:

<%= collection_select(:car, :manufacturer_id, Manufacturer.all, :id, :name) %> 

Ensuite, votre action create ne devrait pas avoir besoin de définir explicitement un manufacturer_id car il aurait dû l'avoir reçu du formulaire.

+0

Wow ce design est beaucoup plus intuitif, je me demande pourquoi je n'y avais pas pensé avant: P – Anon