Is it possible to update a rails model to sync with provided nested attributes for that model?
Let's say I have a many to many association between a Lbrirary and Book model:
class Library < ApplicationRecord
#id integer
#name string
#location string
has_many :library_books, dependent: :destroy
has_many :books, through: :library_books
accepts_nested_attributes_for :library_books, allow_destroy: true
end
class Book < ApplicationRecord
#id integer
#name string
#author name
has_many :libraries, through: :library_books
has_many :library_books
end
class LibraryBook < ApplicationRecord
# id integer
# book_id integer
# library_id integer
belongs_to :library
belongs_to :book
end
class LibrariesController < ApplicationController
def update
@library = Library.find(params[:id])
if @library.update(library_params)
# Successful update
else
# Handle errors
end
end
private
def library_params
params.require(:library).permit(:name, library_books_attributes: [:id, :book_id])
end
end
Now, I send a request to the LibrariesController to create a new Library record along with several books:
{
"id": 1,
"library_books_attributes": [
{
id: 2
book_id: 3
},
{
book_id: 4
},
{
book_id: 5
}
],
...
}
How can I ensure that LibraryBook is updated such that Library with id 1 ONLY matches what's in the request. So, if a record already existed in LibraryBook where book_id was 12 that recored would be destroyed because it is not in library_books_attributes
So in short whatever is in the request for the child model will always be the complete list whether records have to be created/update/or deleted. Is this possible with build in active record/rails functionality or is it required to write a method to do this delta?
For the built-in functionality you'd need to have that element of the passed in list like
{ id: 12, _destroy: 1 }. For what you seem to want you'd need to just write your ownlibrary_books_attributes=method.