From 5618cc651ce85f3c5d5a8ca38cd15b4342e1b652 Mon Sep 17 00:00:00 2001 From: Mayur Shah Date: Wed, 5 Feb 2025 19:36:30 +0530 Subject: [PATCH] Add permalink history for taxon on friendly-id - Introduced FriendlyId to the Taxon model to enable slug history tracking. - Replaced before_create and before_update callbacks with a before_save callback for better slug management. - Implemented a custom should_generate_new_friendly_id? method to control when a new slug is generated, specifically when the permalink changes. - Added a custom normalize_friendly_id method to ensure proper slug formatting for nested taxons. - Included a test to verify that the history of permalinks is correctly stored when a taxon's permalink is updated, ensuring both initial and updated slugs are retained. This change enhances the flexibility and reliability of handling slugs for taxons. --- core/app/models/spree/taxon.rb | 24 ++++++++++++++++++++++-- core/spec/models/spree/taxon_spec.rb | 24 ++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) 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