Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use in-memory objects for adjustments in ItemAdjustments #1401

Merged

Conversation

jordan-brough
Copy link
Contributor

See individual commits.

This avoids extra queries and should improve performance.

It also should make refactoring easier without adding extra queries,
including some upcoming tax-refactoring I'm working on.

The two primary commits are these:

  • "Automatically update adjustments relationships" - a workaround for backward-compatibility
  • "Use in-memory objects for adjustments in ItemAdjustments" - to actually start using in-memory objects

I'm not super happy with the above workaround, but I couldn't think of a better option. Also, it makes me nervous that we need a workaround like that in the first place -- it seems like this could be fragile. See, for example, the "Don't use all_adjustments in OrderAdjuster" commit. Using all_adjustments in the "wrong" way can result in outdated in-memory objects and thus incorrect calculations.

Relates to #1252 and previous work done in #1356, #1389, and #1400.

@jordan-brough jordan-brough force-pushed the in-memory-objects-in-item-adjustments branch from 0b8c268 to d470868 Compare August 24, 2016 12:35
So that in-memory associations stay up to date for calculations in
OrderUpdater and elsewhere.

E.g. if you do this:

    Spree::Adjustment.create!(adjustable: line_item, ...)

Then `line_item.adjustments` does not get updated if it's already
loaded.

Also this:

  source.adjustments.create!(adjustable: line_item, ...)

likewise doesn't update `line_item.adjustments`.

The code in this commit is not the most lovely code, but I couldn't
think of a better option for the time being, given that we expose all
of ActiveRecord as an interface and it's likely that extensions and/or
stores themselves have code like the above in, for example, their
promotion actions.
Using all_adjustments bypasses the individual `adjustments`
associations (order.adjustments, line_item.adjustments &
shipment.adjustments) which makes them outdated for further use.
Using order.inventory_units bypasses `line_item.adjustments` which
makes them outdated for further use.
This ensures that the same object is used as the one inside
`item.adjustments` so that it's kept up to date correctly
This avoids extra queries and should improve performance.

It also should make refactoring easier without adding extra queries,
including some upcoming tax-refactoring I'm working on.
This switches to update the adjustable `adjustments` instead of the
promotion action adjustments.  The former is most likely more
important.
This keeps `item.adjustments` up to date.
This switches to update the adjustable `adjustments` instead of the
tax rate adjustments.  The former is most likely more important.
This keeps `line_item.adjustments` up to date.
This makes it the same as all the other `adjustments` relationships
which makes the repair code in Adjustment simpler, and it makes it
easier to query for duplicates.

Also, use `line_item.adjustments.create` instead of
`unit_cancel.adjustments.create`. The latter bypasses
`line_item.adjustments` which makes them outdated for further use.
`create(:adjustment)` seems like a reasonble thing to do, but it
doesn't update, e.g., `line_item.adjustments` and triggers the warning
we have in place in Adjustment.
Nest :tax_adjustment factory under :adjustment factory

Avoids duplicated `after_build` code.
This shouldn't happen in Solidus core anymore.
@jordan-brough jordan-brough force-pushed the in-memory-objects-in-item-adjustments branch from d470868 to 1e60956 Compare August 24, 2016 12:47
order.all_adjustments.tax.destroy_all
[order, *order.line_items, *order.shipments].each do |item|
item.adjustments.destroy(item.adjustments.select(&:tax?))
end
Copy link
Contributor

@jhawthorn jhawthorn Aug 24, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of this we should probably fix this line https://github.com/solidusio/solidus/blob/master/core/app/models/spree/tax/item_adjuster.rb#L31

and then remove the skip_destroy_adjustments option

orders here should never have tax adjustments (they've been only on items since spree 2.2), so I don't think we need to consider that

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jhawthorn thanks, updated!

This `destroy_all` was on a scope and thus could cause data to be out
of sync. And, as mentioned by jhawthorn in the PR review we can move
tax adjustment destroys to ItemAdjuster because:

> orders here should never have tax adjustments (they've been only on
> items since spree 2.2)
@mtomov
Copy link
Contributor

mtomov commented Aug 26, 2016

Thank you for those 👍

Would they actually make it into the 1.x branch, or only onto the Rails5 one?

@jhawthorn
Copy link
Contributor

👍

@jhawthorn jhawthorn added this to the 1.4.0 milestone Aug 26, 2016
@@ -6,18 +6,18 @@ class Spree::UnitCancel < Spree::Base
DEFAULT_REASON = 'Cancel'

belongs_to :inventory_unit
has_one :adjustment, as: :source, dependent: :destroy
has_many :adjustments, as: :source, dependent: :destroy
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this change would merit an entry in the CHANGELOG?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bbuchalter good point. I updated to @jhawthorn's solution though, so I've reverted back to has_one.

Per PR feedback. Avoid changing the `has_many`/`has_one` relationship
while still keeping in-memory objects up to date.
@jordan-brough
Copy link
Contributor Author

FYI I've added a Changelog entry for this and the related PRs.

@cbrunsdon
Copy link
Contributor

Looks great to me, really fantastic work, thanks 👍 and anyone that contributed eyes.

@jhawthorn jhawthorn merged commit c9cf2c7 into solidusio:master Aug 31, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants