Rails accepts_nested_attributes_for always creates nested models but does not update them

Given the following:

class WebsitesController < ApplicationController # POST /websites/save # POST /websites/save.json def save Website.exists?(name: params[:website][:name]) ? update : create end # POST /websites # POST /websites.json def create @server = Server.find_or_create_by_name(params[:server_id]) @website = @server.websites.new(params[:website]) #etc... @website.save end # PUT /websites/1 # PUT /websites/1.json def update @website = Website.find_by_name(params[:website][:name]) #etc... @website.update_attributes end end 

Customer does not have identifiers for these models

A request that is sent only has names , but not ids .

And the following models

 class Website < ActiveRecord::Base serialize :website_errors attr_accessible :plugins_attributes has_many :plugins accepts_nested_attributes_for :plugins end class Plugin < ActiveRecord::Base belongs_to :website end 

When I make a POST request to /websites/save.json , the Website updated correctly if it exists, but the Plugins that it owns always get recreated, causing duplicate content in the database. Why is this happening? I am redirecting to the update action that calls update_attributes , so how could it be that it is not updating it? I believe this is because no identifier is specified with the request.

Can I make a Controller to listen on plugin_name instead of plugin_id ?

+7
ruby-on-rails activerecord ruby-on-rails-3
source share
1 answer

Change your controller like this:

 def update @website = Website.find_by_name(params[:website][:name]) if @website.update(params) redirect_to website_path(@website) else render :edit end end 

Also, if you use strong_parameters , you will need this at the bottom of your controller:

 params.require(:website). permit( :name, ..., plugins_attributes: [ :name, ..., ] ) end 
+1
source share

All Articles