Ask A Question

Notifications

You’re not receiving notifications from this thread.

How do I create a parent record from the child when the parent doesn't exist?

Nino Rosella asked in Rails

Hi team,

I've trying to model books, chapters, and notes.

I have the following:

class Book < ApplicationRecord
    has_many :chapters
    has_many :notes
end
class Chapter < ApplicationRecord
    belongs_to :book
    has_many :notes
end
class Note < ApplicationRecord
    belongs_to :chapter
end

I can create Books and notes just fine.

What I want to do when creating a new Note is either create a new Chapter or assign an existing one to a note. Said another way: I'm trying to create a parent from the child before the parent even exists, or assigning an exising parent to the child.

This is the kind of functionality that's provided by gems such as acts_as_taggable_on. I've tried using nested forms, but just couldn't get it near to what I wanted. I'm wondering if my architecture is even correct for this type of use? Any guidance you could provide would be much appreciated.

Reply

I mananged to solve this. Here's what I did for anyone that comes across this in the future. Note in the new action I have @note.build_chapter rather than @note.chapter.build

class Book < ApplicationRecord
    has_many :chapters
    has_many :notes
end
class Chapter < ApplicationRecord
    belongs_to :book
    has_many :notes
end
class Note < ApplicationRecord
    belongs_to :chapter, optional: true
  accepts_nested_attributes_for :chapter
end
class NotesController < ApplicationController
    def new
        @note = Note.new
        @note.build_chapter
    end

    def create
        @book = Book.find(params[:book_id])
        @note = @book.notes.create(note_params)

        if params[:book_note][:chapter_name]
            parent_chapter = @book.chapters.find_or_create_by(name: params[:note][:chapter_name], book_id: params[:book_id])
            @note.chapter = parent_chapter
        end
    end

    private

    def book_note_params
        params.require(:book_note).permit(:title, :body,  : chapters_attributes: [:id, :name, :chapter_id, :_destroy])
    end

end

The controllers need refactoring, but you get the gist.

Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 78,890+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.

    Screencast tutorials to help you learn Ruby on Rails, Javascript, Hotwire, Turbo, Stimulus.js, PostgreSQL, MySQL, Ubuntu, and more.

    © 2023 GoRails, LLC. All rights reserved.