ned ned - 4 months ago 8
Ruby Question

Ruby on rails polymorphic association on update deleting and insert, but it will update

When I update model with nested attributes rails run query:

DELETE FROM "assets" WHERE "assets"."id" = ? [["id", 14]]
UPDATE "posts" SET ...
INSERT INTO "assets" ("title", "assetable_id", "assetable_type", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["title", "Poster Title"], ["assetable_id", 3], ["assetable_type", "Post"], ["created_at", "2016-07-27 07:01:38.054681"], ["updated_at", "2016-07-27 07:01:38.054681"]]


But I want update, not delete/insert. Yes, if remove
dependent: :destroy
from model it run update query, but I want destroy asset when post is destroy.

If I have stored more info in assert model, when update it will lost.

This is bug?

My models:

class Asset < ActiveRecord::Base

belongs_to :assetable, polymorphic: true

end

class Post < ActiveRecord::Base

has_one :poster, as: :assetable, class_name: 'Poster', dependent: :destroy
accepts_nested_attributes_for :poster

end

class Poster < Asset

end


My controller:

class PostsController < ApplicationController

...

def update
if @post.update(post_params)
redirect_to blogger_blog_posts_path(@blog)
else
@categories = Category.full_tree
render 'edit'
end
end

...

def post_params
params.require(:post).permit(:title, :description, :content, category_ids: [], :poster_attributes => [:title])
end
end


rails version 4.2.5.1

Answer

In the strong parameters you have not permitted id for poster_attributes so just permit it and that should work:

def post_params
  params.require(:post).permit(:title, :description, :content, category_ids: [], :poster_attributes => [:title, :id])
end

As you have a has_one relationship so when you update the post it sends the title for the poster and as it doesn't contains the id attribute in it rails treats it as a new poster for the post and deletes the old one and creates a new one. So if you permit the id in the strong parameters as you are receiving it from the form it will update the existing poster only.