Sort collection of models by last added (to collection)

Hey all,

I’m working on a site that has a model Set and a model Cart. Set belongs_to Cart and Cart has_many Sets. I’m using ruby’s append method to add a set to the cart.

Cart.sets << set

On the shopping page, I have a list of the sets in the current_cart. They should display in the order that the sets were added to the cart, and for the most part that is the case. Occasionally, though, a set being added to the cart will jump to the middle of the pack, and I can’t figure out why. I know that the sets aren’t being sorted by ID because in my current list set 4 is first followed by 2 and 3 (the correct order).

Also, if I were to delete set 4 (from the first position) and re-add the set to the cart it will jump back to the first spot. I feel like I’m missing something obvious here.

Any ideas?

The “shovel” operator creates an association in the database. When you retrieve the records from the database, the sort is non-deterministic. You didn’t give it any constraints so your database returns them in whatever order it happened to retrieve the records.

It sounds like you need a cart/sets join model so you can use the created_at field for sorting.

Thanks for your reply @derekprior. I actually do have a join model called cart_set, but I’m unsure of how to sort by using created_at on the join model. I’ll keep digging!

So I’ve managed to get it to work, but it’s pretty dirty. What would be a more ideal way to do this?

<% CartIconSet.where(cart: current_cart).order('created_at').each do |set| %>
    <% set = IconSet.find(set.icon_set) %>
<% end %>

^— I feel really bad for doing this.

What about?


Assuming the relationships are set up like that, that should fetch you the icon sets for the current cart. The includes means when you are iterating over the cart_icon_sets you can call set to get the associated set record without doing another database round trip.

1 Like

I got it working. Still messy, but it’s down to one line.

<% current_cart.cart_icon_sets.order('created_at').map(&:icon_set).each do |set| %>

I’m not sure why I couldn’t get it to work with includes but I’ll see if I can’t figure it out. Thanks!