views:

785

answers:

5

I just picked up Agile Web Development with Rails 3rd Ed., and I'm going thru the Depot Application chapters, and I have a question about Product/Item options-

If I wanted to modify the product catalog and store so that products could have options (size, color, whatever), where/how would I do that?

Let's say I'm selling t-shirts, and they come in different sizes. I don't feel like that's something that really needs a model created to handle sizes, so I thought I could just add it as a select box in the html in the store's view.

But, each Add to Cart button is wrapped by a form tag that is automatically generated by button_to, and doesn't seem to give me the ability to pass additional parameters to my cart. How can I get the size of the item added into the POST to add_to_cart?

And perhaps more importantly- what is the most Railsy way to do so?

Thanks in advance for any help! --Mark

The helper in my view:

<%= button_to "Add to Cart" , :action => :add_to_cart, :id => product %>

The form that it generates:

<form method="post" action="/store/add_to_cart/3" class="button-to">

A: 

I'd drop the button_to helper and use a proper form, submitting the product properties to the add_to_cart action.

<% form_for(@product) do |f| %>
<%= f.select :size, ['S', 'M', 'L', 'XL', 'XXL'] %>
# other properties...
<%= f.submit 'Add to Cart' %>
<% end %>
Can Berk Güder
That's a step in the right direction, but only helps to display **size** in my cart view. I need to add **size** to my cart object so that it's actually stored with the item, in my cart.Thanks again for any help, I've been working on it all weekend, but I'm obviously not a programmer.--Mark
A: 

You will need to add attributes to your model. For that, you will need to create a migration to update your database table. I only have the 2nd edition of the book, but there's a section called "Iteration A2: Add a missing column" that describes how to do this. I assume a similar section would be in the 3rd edition.

After doing that, you can follow Can Berk Güder's suggestion and replace the button by a form.

Jeroen Heijmans
A: 

Are you sure? I really didn't think that it made sense to have a field in the database that would never store anything.

This is what's confusing me about using Rails so far- Taking one model (product), and then trying to tack on other data when you save it in another model (cart_item).

Can anyone confirm that Jeroen is right? I just want to be sure that I'm learning this the right way, because I am a total beginner, and I wouldn't know a bad habit from a standard practice at this point! Thanks so much! And thanks two both of you for taking the time to answer already.

+1  A: 

I'm not sure why you wouldn't store size, unless what you mean is that you'd store size as part of cart_item rather than product, which would be fine. In that case you'd do something like this:

<% form_for(@cart_item) do |f| %>
<%= f.select :size, ['S', 'M', 'L', 'XL', 'XXL'] %>
<%= f.hidden_field :product_id, :value => @product.id %> 
# other properties...
<%= f.submit 'Add to Cart' %>
<% end %>
Cameron Price
I agree. I'd add size to the cart_item model.
Owen
+2  A: 

Ok, it's 2 days later, and I figured it out. This is what I had to do-

1, in my store view:

<% form_for @product, :url => {:action => "add_to_cart", :id => @product} do |f| %>
  <select name="productsize" id="productsize">
    <option value="L">L</option>
    <option value="XL">XL</option>
  </select>
  <%= f.submit 'Add to Cart' %>
<% end %>

2, added to my store controller:

productsize = params[:productsize]
@cart.add_product(product, productsize)

Had to get productsize from params, and then pass it with the rest of the product model to the cart model's add_product action.

3, adjusted the cart model to accept the argument, and:

@items << CartItem.new(product, productsize)

Passed it along with the rest of the product model to create a new Cart Item and add it to items.

4, added to the cart_item model:

attr_reader :product, :quantity, :productsize

def initialize(product, productsize)
@product = product
@productsize = productsize

to read in productsize and initialize Cart Item.

5, added to my add_to_cart view:

Size: <%=h item.productsize %>

To display it for the user.

That's it. If there is an easier or DRYer way to go about it, I'm all ears (eyes?).