-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Remove code column from spree_promotions table #3028
Remove code column from spree_promotions table #3028
Conversation
f773bb7
to
1a1729f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! 💪
I have to add a guard to let people know that they have to remove data from the column before running the migration. Also, I need to add a changelog entry |
d5ab562
to
9c1741f
Compare
migration_context.say "Creating Spree::PromotionCode with value '#{promotion.code}' "\ | ||
"for Spree::Promotion with id '#{promotion.id}'" | ||
|
||
promotion.codes.create(value: promotion.code) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about create!
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pointing this out @mdesantis !
There's a uniqueness validation on value
so if that value is already used (let's say the code has been already moved manually into the Spree::PromotionCode
) it will raise an exception.
What about using Spree::PromotionCode.find_or_create_by!(value: value, promotion_id: promotion.id)
instead?
I think this way it will only raise if the value is not unique and that value has been used on a Spree::PromotionCode
associated with another Spree::Promotion
. It will do nothing if the current Spree::Promotion
already has a Spree::PromotionCode
with the same value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I totally agree with that 👍
# This is another possible approach, it will convert Spree::Promotion#code | ||
# to a Spree::PromotionCode before removing the `code` field. | ||
# | ||
promotions.each do |promotion| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose the number of promotions might be quite high in some databases. In that case find_each
should work better than each
# You have some promotions with "code" field present! This is not good | ||
# since we are going to remove that column. | ||
# | ||
self.class.promotions_with_code_handler.new(self, promotions_with_code).call |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be better to use a simple callable instead of a class that responds to #call
and pass options directly to call
, also a constant would be more straightforward than a method:
self.class.promotions_with_code_handler.new(self, promotions_with_code).call | |
deprecated_code_handler = StopWithError | |
# deprecated_code_handler = DoNothing | |
# deprecated_code_handler = MoveToSpreePromotionCode | |
deprecated_code_handler.call(self, promotions_with_code) |
and then below:
# Please note that this will block the current migration and rollback all
# the previous ones run with the same "rails db:migrate" command.
StopWithError = ->(migration, promotions) {
raise StandardError, "You are trying to drop 'code' column from "\
"spree_promotions table but you have at least one record with that "\
"column filled. Please take care of that or you could lose data. See:" \
"\n" \
"https://github.com/solidusio/solidus/pull/3028"\
"\n"
}
This is much simpler and has the advantage of having the configuration near the error location, making it easier to find
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is very similar to what I did first but to test all the possible proposed approaches I ended up creating a method. I know it's not ideal but I can't think to other solutions for this. Feel free to suggest how can I keep this code tested reducing its complexity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like Elias idea of using simple callables, but Albertos approach is working well and is tested (not that easy with lambdas), so I think it's fine. The outcome is the same.
What I do care about is the very thoughtful work that is done here and want to give an extra appreciation! Very nicely done, Alberto! 👏
c544736
to
2c2318f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this. Especially the very thoughtful way of handling the data migration. Really great work. Also the commit messages are 👌
# This approach will delete all codes without taking any action. At | ||
# least we could print a message to track what we are deleting. | ||
# | ||
promotions.each do |promotion| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's also this instance of each
that can be replaced with find_each
. Sorry for not finding it earlier.
f0adae8
to
9d22219
Compare
There's some issue with the database in test environment when it tries to roll back to the previous state after the test ends, I need to investigate more on why it's happening. |
5d20dfc
to
66d3c63
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thanks Alberto 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kennyadsl great job!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Promotions are now tied to multiple code records so this scope does does not make sense anymore.
Since it includes a reference to promotion.code that is no more valid
We can't use a simple `change` method here since we also want to remove the index and we should respect the order of these actions.
This code needs to be removed for 2 reasons: 1. it didn't work, it should be on a class level (`def self.columns`) see issue solidusio#2979, which can be closed when this is merged. 2. is not used anymore since we are removing the `code` column at all from the database.
By default we raise and error to give users a notice that we code column will be removed from spree_promotions table and they will lose their data. We are also providing another 2 options that can be activated by changing `promotions_with_code_handler` class method content making it return another class. Users can also create their own class directly into the migration and handle this how they prefer.
66d3c63
to
3435a9b
Compare
Description
This PR removes
code
column formSpree::Promotion
since promotions are now tied to multiple codes viaSpree::PromotionCode
.Ref. #2979
TODO:
Checklist: