Ryan
Ryan

Reputation: 18109

Rails Simple Form Association for all possible objects

I'm trying to setup simple_form for a product/cart scenario, but a little differently than the typical scenario. My display needs to list ALL available products and have a qty input for each. When saved, the cart_items should store cart_id, product_id, and qty only for those items which have a qty provided. If it's blank or zero, it should not be added to cart_items

Cart:

class Cart < ApplicationRecord
  has_many :cart_items
  has_many :products, through: :cart_items
  accepts_nested_attributes_for :cart_items
end

Cart Items:

class CartItem < ApplicationRecord
  belongs_to :cart
  belongs_to :product
end

Products:

class Products < ApplicationRecord
  has_many :cart_items
  has_many :carts, through: :cart_items
end

I'm trying to have my form display such as: [ x ] (Qty) Product Name [ x ] (Qty) Product Name [ x ] (Qty) Product Name [ x ] (Qty) Product Name

I'm not sure how to get the extra field for qty using f.association :cart_items, collection: Products.all() , and I tried this:

<%= f.simple_fields_for :cart_items do |fa| %>
    <%= fa.association :product, as: :select %>
    <%= fa.input :qty %>
<% end %>

But that only displays existing associations, and also displays the product in a select list whereas I'd like to just list out all products and display their associated qty.

Is there a nice and pretty "Rails-y" way of doing this that I'm overlooking, or do I need to do some more manual manipulation in my controller and views? I'm using Rails 5.

Upvotes: 0

Views: 471

Answers (1)

user919635
user919635

Reputation:

I suspect that there is no special "Rails-y" way, or I am not aware of it. I think that you will have to loop over all your products and build cart_items for the missing ones before simple_fields_for tag. If a cart item with a product already exists then just show it; otherwise, build it first and then show.

You will also have to add rejection of cart_items in case of missing qty. Something like this:

accepts_nested_attributes_for :cart_items, reject_if: lambda { |ci| ci[:qty].blank? || ci[:qty].zero? }

This should do the trick.

Upvotes: 1

Related Questions