Search code examples
ruby-on-railsrubynested-resources

Nested Resource Creation in Parent Form


I have a class called Quote which has_many :line_items, as: :line_itemable (line_items are polymorphic). A quote must have at least one line_item upon creation, so in my Quote creation form I have a section dedicated to adding line items. My routes look like this:

resources :quotes, shallow: true do
  resources :line_items
end

which means my routes look like this:

                     POST  /quotes/:quote_id/line_items(.:format)      line_items#create
new_quote_line_item  GET   /quotes/:quote_id/line_items/new(.:format)  line_items#new

In the line items section of the quote form I have a button that, when clicked, links to the new_quote_line_item controller action to render a line_item creation modal. My issue is that since the quote hasn't been created yet it doesn't have :quote_id to use in the path. How can I go about achieving this the Rails Way™? I was considering using ajax but I'm not sure if that is overkill for this situation. Thanks for your help!


Solution

  • Ajax

    You wouldn't need ajax functionality for this - Ajax only allows you to pull data from the server asynchronously, which essentially means you don't have to reload the page.

    --

    Nested Attributes

    What you're looking for, as alluded to by atomAltera sounds like accepts_nested_attributes_for - which allows you to create dependent models from the parent

    It sounds to me that you'll need to create a quote before you try and populate line_items, which is actually quite simple using ActiveRecord:

    #app/models/quote.rb
    Class Quote < ActiveRecord::Base
       has_many :line_items
       accepts_nested_attributes_for :line_items
    end
    
    #app/controllers/quotes_controller.rb
    Class QuotesController < ApplicationController
        def new
           @quote = Quote.new
           @quote.line_items.build
        end
    
        def create
           @quote = Quote.new(quote_params)
           @quote.save
        end
    
        private
    
        def quote_params
            params.require(:quote).permit(:quote, :attributes, :new, line_items_attributes: [:line, :items, :attributes])
        end
    end
    

    --

    If you need any further information, please let me know!!