0

The Order model in the Spree framework "has many" line items, described like so:

has_many :line_items, -> { order('created_at ASC') }, dependent: :destroy, inverse_of: :order

I've added a model called SelfFulfillmentUnit which "belongs to" a line item (a line item can have many SelfFulfillmentUnit objects), simply described as such:

has_many :self_fulfillment_units

I would like to be able to access all of the Self-fulfillment Units associated with this order through the line items, so I have an order decorator which creates this relationship described like so:

has_many :self_fulfillment_units, through: :line_items

The Problem:

Unfortunately, when I do this:

order.self_fulfillment_units

I receive this error:

ambiguous column name: created_at: SELECT spree_self_fulfillment_units.id FROM "spree_self_fulfillment_units" INNER JOIN "spree_line_items" ON "spree_self_fulfillment_units"."line_item_id" = "spree_line_items"."id" WHERE "spree_line_items"."order_id" = 13 ORDER BY created_at ASC

I'm fairly certain this is caused by the lambda condition in the has_many :line_items of the Order model.

Assuming that is the case, I'm not certain how to prevent the condition block from executing. As per this answer, I tried adding the unscoped method to the order select call (Spree::Order.unscoped.by_number....), however this did not seem to have any effect (the ORDER BY created_at ASC portion remained).

The only solution I've been able to find is to add this to the order decorator:

has_many :line_items, dependent: :destroy, inverse_of: :order

effectively overriding the line_items relationship line from the base order model. This, however, is obviously not an ideal solution, since every call to the line_items relation is now affected.

Alternatively, I could create a custom line items has_many relationship with a different name, but without the condition block.

Question: Other than that solution though, I'm now sure how else to solve this. Is there a way to somehow suppress the condition block of a relationship statement?

Community
  • 1
  • 1
Paul Richter
  • 10,908
  • 10
  • 52
  • 85
  • Have you already tried to add the table name into the order method into the lambda? You should override the has_many also in this solution but you will keep the original behavior. – kennyadsl Oct 25 '14 at 18:36
  • @kennyadsl Yeah that's what did after posting this. Its a bit better than the other crumby solution. I'm still curious if there's a way to somehow manually suppress the condition block. – Paul Richter Oct 25 '14 at 22:42
  • 1
    I'm not sure if you just want to cleanly solve the issue or removing the lambda has a real purpose. Anyway I think this is a bug in spree and I just submitted a [pull request](https://github.com/spree/spree/pull/5531) that should solve this issue without adding any line into your project. If/When that will be merged you should update spree pointing, probably pointing to github repo until next spree versions come out. – kennyadsl Oct 26 '14 at 08:50

1 Answers1

1

I take the best of both options: override the has_many relation but fix the error, don't change it's functionality. Also, you can send a pull request to spree.

You can add an initializer at config folder with:

module Spree
  class Order < Spree::Base
    has_many :line_items, -> { order(:created_at) }, dependent: :destroy, 
      inverse_of: :order
  end
end 

Then at the console can see:

~/rails/try/spree_pj (development) > Spree::Order.first.line_items
  Spree::Order Load (0.2ms)  SELECT  "spree_orders".* FROM "spree_orders"
  ORDER BY "spree_orders"."id" ASC LIMIT 1
  Spree::LineItem Load (0.2ms)  SELECT "spree_line_items".* FROM 
  "spree_line_items" WHERE "spree_line_items"."order_id" = ?  ORDER BY 
  "spree_line_items"."created_at" ASC [["order_id", 1]]
=> #<ActiveRecord::Associations::CollectionProxy [....]>

With ORDER BY "spree_line_items"."created_at" ASC your issue is fixed.

Ops! I seen that this work fine at the console, but not at the server! I leve alive this answer, because it can help to another ideas.

Alejandro Babio
  • 5,189
  • 17
  • 28