Want to receive a weekly email containing
the scoop on our new titles along with the
occasional special offer? Just click the button.
(You can always unsubscribe later by editing your
account information).

Give us an email and a password (you can use the password later to log in and
change your preferences). We'll send you a newsletter roughly once a week.

In my decrement method, I had if @line_item.update_attributes(params[:id]) which contained respond_to. Turns out this didn’t work if the line_item should disappear because if you run @line_item.destroy BEFORE update_attributes, you get a “frozen hash” error that not only returns false but returns a runtime error. I got around this with the following:

When I had if ($('#cart tr').length 0, it would never work because the cart grand total is inside a tr that never goes away. This wasn’t made obvious when we were building our create.js.erb in the example so it took me a bit to figure out.

I am a little glad I learned so much, but mostly just angry right now.

Christian says:

Hi there, could you do me a big favour and share the complete code? I’ve been fiddling around with this task for hours but I just can’t get it to work (the ajax part).

Johan says:

I believe the button_to should be: <%= button_to ‘Del’, decrement_line_items_path(line_item_id: line_item), remote: true %> I.e “decrement_line_items(!)_path”, at least that worked for me.

Tiger says:

Should this decrement function be written in the model or the controller?

Again, there is more than one way to do it, I show two above, but another still would be to put all the logic into this controller method (though that would go against the point of MVC). I vote for the 1st way because it is less roundabout (i.e. one less call).

Note: I don’t know what is the right thing to do for the else-clause in respond_to. Please reply if you know.

Exl says:

Johan says:

Thanks for the code Exl. Just asking, is it normal to use “put” in this case?

Exl says:

Johan, thanks for bringing this up. Although PUT works in this case, the correct HTTP method for such operations is actually POST! The reason is because POST is not idempotent, whereas PUT is (actually, all of the main HTTP methods are idempotent (meaning, they are operations that should produce the same results even if executed multiple times). Idempotent is derived from Latin: idem ‘same’ + potent.

PUT is idempotent and implies putting a resource. Do it as many times as you like, and the result is the same. x=5 (the assignment) is idempotent.

POST updates a resource, adds a subsidiary resource, or causes a change. A POST is not idempotent, in the way that x++ is not idempotent. Doing it repeatedly will produce different results. In the case of each of our “decrement”, the resulting value changes each time.

Johan says:

Thanks for the info Exl. Wonder why they did update as “put” in the book, for example the cart controller:

# PUT /carts/1
# PUT /carts/1.json
def update
...

Exl says:

Johan, I think it’s because the update method is like x=5. It’s not like x++. The functional purpose of update is:

@cart = Cart.find(params[:id])

No matter how many times you apply a given set of parameters, the result should be the same for that set of parameters. Whereas each time you call decrement, the result will be different (the product quantity will be one less than each call before).

This is my understanding. If someone has better insight, please let us know.