We built (based on the book Agile webdev Rails4) a shopping/inquiry cart.
Visitor can add line_items (houses)to the cart and and then checkout. When the visitor checks out a lead is created.
My models:
class House < ActiveRecord::Base
has_many :line_items
end
class LineItem < ActiveRecord::Base
belongs_to :lead
belongs_to :house
belongs_to :cart
end
class Lead < ActiveRecord::Base
has_many :line_items, dependent: :destroy
def add_line_items_from_cart(cart)
cart.line_items.each do |item|
line_items << item
end
end
end
class Cart < ActiveRecord::Base
has_many :line_items, dependent: :destroy
accepts_nested_attributes_for :line_items
end
A module for creating the session cart
module CurrentCart
extend ActiveSupport::Concern
private
def set_cart
@cart = Cart.find(session[:cart_id])
rescue ActiveRecord::RecordNotFound
@cart = Cart.create
session[:cart_id] = @cart.id
end
end
Carts_controller
class CartsController < ApplicationController
before_action :set_cart, only: [:show, :edit, :update, :destroy]
def create
@cart = Cart.new(cart_params)
respond_to do |format|
if @cart.save
format.html { redirect_to @cart, notice: 'Cart was successfully created.' }
format.json { render action: 'show', status: :created, location: @cart }
else
format.html { render action: 'new' }
format.json { render json: @cart.errors, status: :unprocessable_entity }
end
end
end
end
Line_item Controller
class LineItemsController < ApplicationController
skip_before_action :authorize, only: :create
include CurrentCart
before_action :set_cart, only: [:create]
before_action :set_line_item, only: [:show, :edit, :update, :destroy]
def create
house = House.find(params[:house_id])
@line_item = @cart.line_items.build(house_id: house.id)
respond_to do |format|
if @line_item.save
format.html { redirect_to @line_item.cart,
notice: 'Vakantiehuis toegevoegd in lijst.' }
format.json { render action: 'show',
status: :created, location: @line_item }
else
format.html { render action: 'new' }
format.json { render json: @line_item.errors,
status: :unprocessable_entity }
end
end
end
leads_controller
class LeadsController < ApplicationController
include CurrentCart
before_action :set_cart, only: [:new, :create]
def create
@lead = Lead.new(lead_params)
@lead.add_line_items_from_cart(@cart)
respond_to do |format|
if @lead.save
format.html { redirect_to @lead, notice:
'Thank you for your order.' }
format.json { render action: 'show', status: :created,
location: @order }
else
format.html { render action: 'new' }
format.json { render json: @lead.errors,
status: :unprocessable_entity }
end
end
end
end
We want to add a new model (apartments to the shopping cart). So i added apartment_id in the line_items table and changed the models
class Apartment < ActiveRecord::Base
has_many :line_items
end
class LineItem < ActiveRecord::Base
belongs_to :lead
belongs_to :house
belongs_to :apartment
belongs_to :cart
end
But i don't now how i must change the create method in the LineItems_controller so we can add houses and apartments to the cart?
THanks remco
You'll want to change your line_items
model to have a polymorphic association :
Polymorphic associations are simply when you have the ability to associate different objects in the same model. This would not be correct if your apartments
were child-objects of the House
model, but as they are independent, you'll be able to associate them polymorphically
Here's how I'd do it:
#app/models/line_item.rb
class LineItem < ActiveRecord::Base
belongs_to :item, polymorphic: true
end
#app/models/house.rb
class House < ActiveRecord::Base
has_many :line_items, as: :items
end
#app/models/apartment.rb
class Apartment < ActiveRecord::Base
has_many :line_items, as: :items
end
This will give you the ability to do the following:
#app/controllers/line_items.controller.rb
class LineItemsController < ApplicationController
before_action :create_object
def create
@line_item = @cart.line_items.build item: @object
@line_items.save
end
private
def create_object
id = params[:house_id] || params[:apartment_id]
model = "House" if params[:house_id]
model = "Apartment" if params[:apartment_id]
model. constantize
@object = model.find id
end
end
This should reference the correct model for you the ability to save either an apartment or a house to your LineItem
model
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.