Advanced Model Relationships: Polymorphic
Master Advanced Rails Polymorphic Relationships and Database Design
Key Concepts You'll Master
Polymorphic Relationships
Learn how one model can belong to multiple other models using a single relationship structure.
Database Migrations
Master complex migrations that preserve existing data while changing relationship structures.
Model Architecture
Implement shared modules and delegate methods for clean, maintainable code organization.
In your code editor, open nutty > app > views > cart > index.html.erb
Locate the checkout button code around line 72:
<a href="#"><button type="button" id="check-out" class="btn-red btn-lg">Checkout</button></a>Replace this placeholder link with a proper Rails form that will handle the checkout submission (shown in bold):
</div>
<%= form_with url: '/cart/complete', method: :post do %>
<%= submit_tag 'Checkout', id: 'check-out', class: "btn-red btn-lg" %>
<% end %>
</div>
The form_with helper creates a form that will POST to our cart completion endpoint, while maintaining the original styling and behavior.
Save the file. This form submission needs corresponding routes to handle both the POST request and the confirmation page display.
In your code editor, open nutty > config > routes.rb
Around line 9, add the following bold code to set up both routes we'll need:
resources :line_items, only: [:create, :update, :destroy]
post 'cart/complete' => 'cart#complete'
get 'cart/complete' => 'cart#complete_page'
root 'products#index'
end
We're creating two distinct routes: the POST route processes the checkout logic, while the GET route displays the order confirmation page. This separation of concerns is a Rails best practice.
Save the file, then close it.
In your code editor, open nutty > app > controllers > cart_controller.rb
Add the controller methods to handle both the checkout processing and confirmation page display (shown in bold):
def index
@title = "Your Cart"
end
def complete
redirect_to '/cart/complete' and return
end
def complete_page
@title = "Your Order is Complete"
end
end
The complete method will eventually handle the order creation logic, while complete_page displays the confirmation. The redirect pattern prevents duplicate submissions if users refresh the page.
Save the file.
Open a Finder window and navigate to: Desktop > Class Files > yourname-Rails Class > snippets
Click on the complete_page.html.erb file and hit Cmd–C to copy it.
Still in the Finder, navigate to: Desktop > Class Files > yourname-Rails Class > nutty > app > views > cart
Hit Cmd–V to paste the file into the cart folder.
In your code editor, open nutty > app > views > cart > complete_page.html.erb
Review the template code—this saves significant development time and ensures consistent styling. In production applications, order confirmation pages typically include order numbers, shipping details, and next steps for customers.
Switch to the browser and go to localhost:3000.
Click on any product and click Add To Cart.
On the Cart page, click the Checkout button on the right.
You should be taken to a confirmation page for your order! However, we still need to implement the core functionality: creating persistent orders and clearing the cart after checkout.
A customer can only have one cart at a time but can have multiple orders throughout their lifetime. This relationship design prevents data conflicts.
Customer Relationship Structure
Standard vs Polymorphic Relationships
| Feature | Standard Approach | Polymorphic Approach |
|---|---|---|
| Foreign Keys | Multiple (cart_id, order_id) | Two fields (itemizable_id, itemizable_type) |
| Data Integrity | Risk of belonging to both | Exclusive relationship guaranteed |
| Code Complexity | Simple initial setup | Complex but cleaner long-term |
This migration requires custom up and down methods because we're preserving existing cart data while changing the relationship structure. Standard change method isn't sufficient.
Order Creation Process
Create Order Object
Initialize new order with current customer reference
Transfer Line Items
Move all cart line items to the new order using polymorphic relationship
Clean Up Cart
Destroy the empty cart and redirect to confirmation page
Key Takeaways
