diff --git a/core/app/models/spree/taxon.rb b/core/app/models/spree/taxon.rb index db8c7759b0f..32f129dcbc5 100644 --- a/core/app/models/spree/taxon.rb +++ b/core/app/models/spree/taxon.rb @@ -4,6 +4,9 @@ module Spree class Taxon < Spree::Base + extend FriendlyId + friendly_id :permalink, use: :history, slug_column: :permalink + acts_as_nested_set dependent: :destroy belongs_to :taxonomy, class_name: 'Spree::Taxonomy', inverse_of: :taxons @@ -13,8 +16,7 @@ class Taxon < Spree::Base has_many :promotion_rule_taxons has_many :promotion_rules, through: :promotion_rule_taxons - before_create :set_permalink - before_update :set_permalink + before_save :set_permalink after_update :update_child_permalinks, if: :saved_change_to_permalink? validates :name, presence: true @@ -121,6 +123,24 @@ def permalink_part=(value) end end + # override for {FriendlyId::Slugged#should_generate_new_friendly_id?} method, + # to control exactly when new friendly ids are set or updated + def should_generate_new_friendly_id? + permalink_changed? || super + end + + # override for {FriendlyId::Slugged#normalize_friendly_id} method, + # to control over the slug format + def normalize_friendly_id(value) + return '' if value.blank? + + parts = value.to_s.split('/') + last_word = parts.pop + corrected_last_word = Spree::Config.taxon_url_parametizer_class.parameterize(last_word) + + (parts << corrected_last_word).join('/') + end + private def touch_ancestors_and_taxonomy diff --git a/core/spec/models/spree/taxon_spec.rb b/core/spec/models/spree/taxon_spec.rb index 2b254a19ba5..93446d95b23 100644 --- a/core/spec/models/spree/taxon_spec.rb +++ b/core/spec/models/spree/taxon_spec.rb @@ -269,4 +269,28 @@ end end end + + context 'stores history of permalinks' do + let(:taxonomy) { create(:taxonomy, name: 'brands') } + let(:root) { taxonomy.root } + let(:taxon_name) { "ruby on rails" } + let(:new_permalink) { "rails for ruby" } + let(:expected_initial_slug) { "brands/ruby-on-rails" } + let(:expected_updated_slug) { "brands/rails-for-ruby" } + + let!(:taxon) { create(:taxon, name: taxon_name, parent: root) } + + it 'should store the previous slug when permalink is updated' do + expect(taxon.slugs.count).to eq(1) + expect(expected_initial_slug).to eq(taxon.slugs.last.slug) + + taxon.update(permalink: new_permalink) + + expect(expected_updated_slug).to eq(taxon.permalink) + expect(taxon.slugs.count).to eq(2) + + expect(taxon.slugs.pluck(:slug)).to include(expected_initial_slug) + expect(taxon.slugs.pluck(:slug)).to include(expected_updated_slug) + end + end end