2011-08-29 3 views
5

J'ai un User qui a un Widget.Comment détruire l'autre relation has_one lors de la mise à jour d'une association?

class User 
    has_one :widget, :dependent => :destroy 
end 

class Widget 
    belongs_to :user 
end 

Et quand je crée une nouvelle Widget pour un User, je veux détruire l'ancien associé au User.

Voilà ma situation:

Créer un utilisateur:

user = User.new 
user.save 
user # => #<User id: 1> 

Créer widget de l'utilisateur:

widget = Widget.new 
widget.user = user 
widget.save 

Recharger et vérifier le widget:

user.reload 
user.widget # => #<Widget id: 1, user_id: 1> 

Construire un widget, notez que le widget existant est détruit avant que l'autre est sauvé:

user.build_widget # => #<Widget id: nil, user_id: 1> 
user.reload 
user.widget # => nil 

widget de l'utilisateur Recréer:

user.create_widget # => #<Widget id: 2, user_id: 1> 

Créer un autre widget:

widget = Widget.new :user => user 
widget.save 

Maintenant, les deux existent:

Widget.find(2) # => #<Widget id: 2, user_id: 1> 
Widget.find(3) # => #<Widget id: 3, user_id: 1> 

Et c'est le premier utilisateur:

user.reload 
user.widget # => #<Widget id: 2, user_id: 1> 

Est-il possible de le faire:

def create 
    @widget = current_user.build_widget(params[:widget]) 

    respond_to do |format| 
    if @widget.save 
     format.html { redirect_to widget_path, notice: 'Widget was successfully created.' } 
     format.json { render json: @widget, status: :created, location: @widget } 
    else 
     format.html { render action: 'new' } 
     format.json { render json: @widget.errors, status: :unprocessable_entity } 
    end 
    end 
end 

sans supprimer l'ancien avant d'enregistrer un widget, ou ceci:

def create 
    @widget = Widget.new(params[:widget]) 
    @widget.user = current_user 

    respond_to do |format| 
    if @widget.save 
     format.html { redirect_to widget_path, notice: 'Widget was successfully created.' } 
     format.json { render json: @widget, status: :created, location: @widget } 
    else 
     format.html { render action: 'new' } 
     format.json { render json: @widget.errors, status: :unprocessable_entity } 
    end 
    end 

fin

sans garder deux copies autour?

Je ne veux pas gâcher mes contrôleurs avec des transactions comme

Widget.transaction do 
    old_widget.destroy 
    new_widget.save 
end 

mais jusqu'à présent, cela semble être la seule façon.

Répondre

0

Il semble que vous ayez deux chemins d'utilisation où un utilisateur peut créer des widgets. Du côté de l'utilisateur et du côté du widget.Il vaudrait mieux que vous les canalisiez à travers un morceau de code, et que vous mettiez quelques validations d'unicité pour vous assurer qu'il n'y a pas de dérapage.

Que diriez-vous d'un find_or_create_by dans user.create_widget afin que vous puissiez éditer le widget existant s'il a besoin d'être mis à jour ou que vous en créez un nouveau.

Questions connexes