diff --git a/app/models/spree_cm_commissioner/store_decorator.rb b/app/models/spree_cm_commissioner/store_decorator.rb index 6ec8c80e2..d6c96e9d8 100644 --- a/app/models/spree_cm_commissioner/store_decorator.rb +++ b/app/models/spree_cm_commissioner/store_decorator.rb @@ -5,6 +5,22 @@ def self.prepended(base) base.has_one :default_notification_image, class_name: 'SpreeCmCommissioner::FeatureImage', dependent: :destroy, as: :viewable base.accepts_nested_attributes_for :default_notification_image, reject_if: :all_blank + + # Override by_url scope + # Optimized by_url scope with exact match, partial match, adn caching + # Cache the result for 1 hour to avoid repeated queries + # First attempt exact match, then partial match if no exact match is found + # Ensure we always return the default store when url is nil or empty + base.scope :by_url, lambda { |url| + Rails.cache.fetch("store_by_url_#{url}", expired_in: 1.hour) do + if url.present? + store = find_by('url = ?', url) || where('url like ?', "%#{url}%").first + store + else + default + end + end + } end end end diff --git a/lib/spree_cm_commissioner/test_helper/factories/store_factory.rb b/lib/spree_cm_commissioner/test_helper/factories/store_factory.rb new file mode 100644 index 000000000..f6456c376 --- /dev/null +++ b/lib/spree_cm_commissioner/test_helper/factories/store_factory.rb @@ -0,0 +1,22 @@ +FactoryBot.define do + factory :cm_store, class: 'Spree::Store' do + sequence(:name) { |n| "Spree Test Store #{n}" } + sequence(:url) { |n| "www.example#{n}.com" } + meta_description { nil } + meta_keywords { nil } + seo_title { nil } + mail_from_address { "no-reply@example.com" } + default_currency { "USD" } + sequence(:code) { |n| "spree_#{n}" } + default { false } + supported_currencies { "USD,EUR,GBP" } + facebook { "spreecommerce" } + twitter { "spreecommerce" } + created_at { Time.now } + updated_at { Time.now } + + trait :default do + default { true } + end + end +end diff --git a/spec/models/spree/store_spec.rb b/spec/models/spree/store_spec.rb new file mode 100644 index 000000000..be89ade73 --- /dev/null +++ b/spec/models/spree/store_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +RSpec.describe Spree::Store, type: :model do + describe '.by_url' do + let!(:store1) { create(:cm_store, url: 'api-production.bookme.plus', code: 'store1', default: false) } + let!(:store2) { create(:cm_store, url: 'images.bookme.plus', code: 'store2', default: false) } + let!(:store3) { create(:cm_store, url: 'static.bookme.plus', code: 'store3', default: false) } + let!(:default_store) { create(:cm_store, url: 'www.example.com', code: 'default_store', default: true) } + + before do + Rails.cache.clear + end + + it 'returns the store with an exact match' do + expect(Spree::Store.by_url('api-production.bookme.plus')).to eq(store1) + end + + it 'returns the store with a partial match if no exact match is found' do + expect(Spree::Store.by_url('bookme.plus')).to eq(store1) + end + + it 'returns the default store if no URL is provided' do + expect(Spree::Store.by_url(nil)).to eq(default_store) + end + + it 'caches the result for 1 hour' do + Spree::Store.by_url('api-production.bookme.plus') + expect(Rails.cache.exist?("store_by_url_api-production.bookme.plus")).to be true + end + end +end