Skip to content

Commit

Permalink
Migrate data to fix records with missing unit_presentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt-Yorkley committed Sep 6, 2023
1 parent 3035047 commit 0505a79
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 1 deletion.
181 changes: 181 additions & 0 deletions db/migrate/20230906165200_migrate_imported_variants_data.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
class MigrateImportedVariantsData < ActiveRecord::Migration[7.0]
class OptionValueNamer
# nameable can be either a Spree::LineItem or a Spree::Variant
def initialize(nameable = nil)
@nameable = nameable
end

def name
value, unit = option_value_value_unit
separator = value_scaled? ? '' : ' '

name_fields = []
name_fields << "#{value}#{separator}#{unit}" if value.present? && unit.present?
name_fields << @nameable.unit_description if @nameable.unit_description.present?
name_fields.join ' '
end

def value
value, = option_value_value_unit
value
end

def unit
_, unit = option_value_value_unit
unit
end

private

def value_scaled?
@nameable.product.variant_unit_scale.present?
end

def option_value_value_unit
if @nameable.unit_value.present? && @nameable.product&.persisted?
if %w(weight volume).include? @nameable.product.variant_unit
value, unit_name = option_value_value_unit_scaled
else
value = @nameable.unit_value
unit_name = pluralize(@nameable.product.variant_unit_name, value)
end

value = value.to_i if value == value.to_i

else
value = unit_name = nil
end

[value, unit_name]
end

def option_value_value_unit_scaled
unit_scale, unit_name = scale_for_unit_value

value = (@nameable.unit_value / unit_scale).to_d.truncate(2)

[value, unit_name]
end

def scale_for_unit_value
WeightsAndMeasures.new(@nameable).scale_for_unit_value
end

def pluralize(unit_name, count)
OpenFoodNetwork::I18nInflections.pluralize(unit_name, count)
end
end

module VariantAndLineItemNaming
def options_text
return unit_presentation unless variant_unit == "weight"
return display_as if has_attribute?(:display_as) && display_as.present?
return variant.display_as if variant_display_as?

unit_presentation
end

def variant_display_as?
respond_to?(:variant) && variant.present? &&
variant.respond_to?(:display_as) && variant.display_as.present?
end

def product_and_full_name
return product.name if full_name.blank?
return "#{product.name} - #{full_name}" unless full_name.start_with?(product.name)

full_name
end

# Used like "product.name - full_name", preferably using product_and_full_name method above.
# This returns, for a product with name "Bread":
# Bread - 1kg # if display_name blank
# Bread - Spelt Sourdough, 1kg # if display_name is "Spelt Sourdough, 1kg"
# Bread - 1kg Spelt Sourdough # if unit_to_display is "1kg Spelt Sourdough"
# if display_name is "Spelt Sourdough" and unit_to_display is "1kg"
# Bread - Spelt Sourdough (1kg)
def full_name
return unit_to_display if display_name.blank?
return display_name if display_name.downcase.include? unit_to_display.downcase
return unit_to_display if unit_to_display.downcase.include? display_name.downcase

"#{display_name} (#{unit_to_display})"
end

def name_to_display
return product.name if display_name.blank?

display_name
end

def unit_to_display
return display_as if has_attribute?(:display_as) && display_as.present?
return variant.display_as if variant_display_as?

options_text.to_s
end

def assign_units
assign_attributes(unit_value_attributes)
end

def update_units
update_columns(unit_value_attributes)
end

def unit_value_attributes
units = { unit_presentation: option_value_name }
units.merge!(variant_unit: product.variant_unit) if has_attribute?(:variant_unit)
units
end

def weight_from_unit_value
(unit_value || 0) / 1000 if product.variant_unit == 'weight'
end

private

def option_value_name
return display_as if has_attribute?(:display_as) && display_as.present?

OptionValueNamer.new(self).name
end
end

class Variant < ActiveRecord::Base
include VariantAndLineItemNaming

belongs_to :product

self.table_name = "spree_variants"
end

class Product < ActiveRecord::Base
has_many :variants

self.table_name = "spree_products"
end

def up
migrate_variant_unit

Variant.where(unit_presentation: "").where.not(import_date: nil).each do |variant|
variant.update_columns(
variant.unit_value_attributes.merge(updated_at: Time.zone.now)
)
end
end

private

def migrate_variant_unit
ActiveRecord::Base.connection.execute(<<-SQL
UPDATE spree_variants
SET variant_unit = spree_products.variant_unit
FROM spree_products
WHERE spree_variants.product_id = spree_products.id
AND spree_variants.variant_unit IS NULL
SQL
)
end
end
2 changes: 1 addition & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2023_08_09_201542) do
ActiveRecord::Schema[7.0].define(version: 2023_09_06_165200) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
enable_extension "plpgsql"
Expand Down

0 comments on commit 0505a79

Please sign in to comment.