2016-04-06 3 views
0

J'utilise postgresql et rails 4.2 pour le développement de mon application.rails rollback résultats résultats dans l'ID discontinu

Voici la question:

Lorsqu'un modèle d'utilisateur est créé, j'ai besoin de deux autres modèles associés au modèle de l'utilisateur à créer à temps: modèle de profil et le modèle user_behavior. En cas de maintenir la cohérence des dossiers, la transaction est utilisée comme ceci:

begin 
    @new_user = User.new 
    @new_user.transaction do 
    @new_user.update_attributes!(users_params) 
    @new_user.profile = Profile.create!(profiles_params) 
    @new_user.user_behavior = UserBehavior.create! 
    end 
rescue ActiveRecord::RecordInvalid => exception 
    render_response_msg(4003, { message: exception.message }) 
rescue ArgumentError => exception 
    render_response_msg(4003, { message: "invalid parameters" }) 
end 
@new_user 

deux modèle de l'utilisateur et le modèle de profil a quelques validations

problème 1. J'utilise une variable d'instance @new_user à apporter le nouvel enregistrement de l'utilisateur créé de la portée de la transaction, je ne suis pas sûr que ce soit une méthode générique pour le faire, d'autres idées? problème

2. lorsque le params utilisateur est bon, il passe et créer un enregistrement utilisateur, puis le profil params est pas valide, fait toute la rollback transaction. Ensuite, j'ai trouvé l'ID (ID d'incrémentation automatique de base du modèle dans les rails) du modèle de l'utilisateur est discontinue. Par exemple, si elle échoue deux fois à cause des paramètres de profil, alors la transaction de succès va créer un modèle avec id = 3. Comment puis-je résoudre ce problème?

+0

Pourquoi les espaces vides dans les valeurs 'id' sont-ils un problème? Ils seront uniques, c'est tout ce qui est vraiment garanti. –

Répondre

0

[Modifier la réponse au problème 1 est impossible, car la variable locale ne peut pas être retourné comme je l'avais indiqué dans mon commentaire m'a manqué dans mon post original]

En réponse à un problème 1: Je pense que la description fournie dans cet article http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html serait utile. Par conséquent, je ferais quelque chose comme suit:

User.transaction do 
    new_user = User.new(user_params) 
    new_user.profile = Profile.create!(profile_params) 
    new_user.behavior = UserBehavior.create! 
    new_user.save! 
end 

En réponse à un problème 2: comme mu is too short a souligné, il ne devrait pas d'importance, mais postgresql utilise une table de séquence pour chaque table dans la base de données généralement nommée [YOUR_TABLE_NAME]_id_seq vous devrez modifier la valeur de la colonne last_value dans cette table afin d'ajuster la séquence d'id mais une erreur causerait certainement beaucoup de problèmes en ce qui concerne le maintien de l'unicité, et je déconseillerais certainement de jouer avec.

+0

Notez que je dois retourner un nouvel enregistrement d'utilisateur créé dans cette méthode, si ** new_user ** est utilisé comme variable locale, je ne peux pas extraire l'entité de la portée de la transaction. – user6164268

+0

Oh oui! Je suis tellement désolé que j'ai absolument manqué ça. Je vais éditer ma réponse –

+0

Aussi je pense que vous pouvez réaliser ce que vous essayez de faire sans une variable d'instance si vous initialisez votre variable comme 'new_user' avant la transaction, elle devrait toujours être accessible dans le bloc' begin'. vous pouvez ajouter 'return new_user' juste avant' rescue ActiveRecord :: RecordInvalid => exception' et si vous ne voulez pas revenir à ce point et que vous avez besoin de new_user accessible en dehors du bloc 'begin', initialisez' new_user' avant le 'begin 'le bloc commence. –