I have a Cart
, CartProduct
, and Product
model. Whenever a product is added to the cart, the CartProduct
model, which represents the items in the shopping cart, has an attribute quantity
that's updated accordingly. Currently I'm sending PATCH
requests on Cart
to update the Cart
s associated CartProduct
models.
My question is: when I want to update a shopping cart item, would it be better to have add_product
, remove_product
, etc. methods in the CartProduct
model, or should I have those methods in the Cart
model (my current setup below, which functions just fine)? Or is this up to personal preference?
Please note that the code is incomplete; I just picked out the important parts for this question:
class Cart < ActiveRecord::Base
has_many :cart_products, inverse_of: :cart, dependent: :destroy
has_many :products, through: :cart_products, source: :product
def add_product(product_id) #directed here from PATCH request
#pulls the associated cart_product for this cart and updates
end
def remove_product(product_id) #directed here from PATCH request
end
end
class CartProduct < ActiveRecord::Base
belongs_to :cart, inverse_of: :cart_products
belongs_to :product, inverse_of: :cart_products
#or should add_product, remove_product methods go here instead?
end
class Product < ActiveRecord::Base
has_many :cart_products, inverse_of: :product, dependent: :destroy
has_many :carts, through: :cart_products, source: :cart
end
When a user increments the quantity of a shopping cart item, what's actually being updated is the CartProduct
model, not the Cart
model - so this worries me because I'm sending a PATCH
request on the Cart
, while I suppose it would make more sense to have a route/method on the CartProduct
model because that's the actual model being updated.
I think what you're asking would be left up to personal preference.
My preference would be to keep it exactly as you have it and call add_product
from your Cart
model.
Others may suggest creating a completely new class, observer, etc to handle that relationship between the two models but what you end up doing is making one class that is dependent upon two models rather than keeping what you have and just having one models method dependent on one other model's attribute.
You mixing up what controllers and models do in MVC.
Models are how you implement the business logic in your application, and how the different objects are tied together. Models should not know anything about PUT, POST, PATCH or even that there is a current request, its not their job.
So if you are creating a method in your model to handle a specific kind of request than your doing it wrong.
Controllers are responsible for responding to requests. Together with routes they build the RESTful interface that your app exposes.
Exactly how to deal with nested resources like in this case is a matter of opinion.
I'm going to use the more common term line item instead of CartProduct for clarity:
Prefix Verb URI Pattern Controller#Action
products GET /products(.:format) products#index
POST /products(.:format) products#create
product GET /products/:id(.:format) products#show
PATCH /products/:id(.:format) products#update
PUT /products/:id(.:format) products#update
DELETE /products/:id(.:format) products#destroy
cart_line_items GET /carts/:cart_id/line_items(.:format) line_items#index
POST /carts/:cart_id/line_items(.:format) line_items#create
line_item GET /line_items/:id(.:format) line_items#show
PATCH /line_items/:id(.:format) line_items#update
PUT /line_items/:id(.:format) line_items#update
DELETE /line_items/:id(.:format) line_items#destroy
carts GET /carts(.:format) carts#index
POST /carts(.:format) carts#create
cart GET /carts/:id(.:format) carts#show
PATCH /carts/:id(.:format) carts#update
PUT /carts/:id(.:format) carts#update
DELETE /carts/:id(.:format) carts#destroy
In many cases using nested attributes and creating/updating/deleting child records is a good solution - but it often leads to the temptation of creating a very limited set up of actions that do everything.
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.