Skip to content
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

WIP #2257 cache store url and enchance by_url scope #2262

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions app/finders/spree_cm_commissioner/stores/find_current_url.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module SpreeCmCommissioner
module Stores
class FindCurrentUrl
def initialize(scope: nil, url: nil)
@scope = scope || Spree::Store
@url = url
end

def execute
by_url(scope) || scope.default
end

protected

attr_reader :scope, :url

def by_url(scope)
return if url.blank?

scope.by_url(url)
end
end
end
end
15 changes: 15 additions & 0 deletions app/models/spree_cm_commissioner/store_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,21 @@ 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

# Optimized by_url scope with exact and partial match, caching results for 1 hour.
base.scope :by_url, lambda { |url|
Rails.cache.fetch("store_by_url_#{url}", expires_in: 1.hour) do
if url.present?
where('url = ? OR url LIKE ?', url, "%#{url}%").first
else
default
end
end
}
end

def self.current(url)
SpreeCmCommissioner::Stores::FindCurrentUrl.new(url: url).execute
end
end
end
Expand Down
22 changes: 22 additions & 0 deletions lib/spree_cm_commissioner/test_helper/factories/store_factory.rb
Original file line number Diff line number Diff line change
@@ -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 { "[email protected]" }
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
75 changes: 75 additions & 0 deletions spec/models/spree/store_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
require 'spec_helper'

RSpec.describe Spree::Store, type: :model do
let!(:store1) { create(:store, url: 'api-production.bookme.plus') }
let!(:store2) { create(:store, url: 'images.bookme.plus') }
let!(:store3) { create(:store, url: 'static.bookme.plus') }
let!(:store4) { create(:store, url: 'images.bookme') }
let!(:default_store) { create(:store, default: true) }

describe '.by_url' do
context 'when URL matches exactly' do
it 'returns the exact match store' do
expect(Spree::Store.by_url('api-production.bookme.plus')).to eq(store1)
expect(Spree::Store.by_url('images.bookme.plus')).to eq(store2)
expect(Spree::Store.by_url('static.bookme.plus')).to eq(store3)
end
end

context 'when URL partially matches' do
it 'returns the first matching store based on partial match' do
# Test for partial match
expect(Spree::Store.by_url('bookme.plus')).to eq(store1) # Returns store1 first
end

it 'returns the correct store when multiple stores match partially' do
# Multiple stores should be returned if matching pattern exists
expect(Spree::Store.by_url('bookme.plus')).to eq(store1) # Returns store1 first
expect(Spree::Store.by_url('images.bookme.plus')).to eq(store2)
end
end

context 'when URL is nil or empty' do
it 'returns the default store' do
expect(Spree::Store.by_url(nil)).to eq(default_store)
expect(Spree::Store.by_url('')).to eq(default_store)
end
end

context 'when caching is involved' do
it 'caches the store lookup for exact matches' do
expect(Rails.cache.read("store_by_url_#{store1.url}")).to be_nil
Spree::Store.by_url(store1.url)
expect(Rails.cache.read("store_by_url_#{store1.url}")).not_to be_nil
end

it 'caches the store lookup for partial matches' do
expect(Rails.cache.read("store_by_url_#{store2.url}")).to be_nil
Spree::Store.by_url(store2.url)
expect(Rails.cache.read("store_by_url_#{store2.url}")).not_to be_nil
end
end
end

describe '.current' do
context 'when URL is present' do
it 'returns the store corresponding to the URL (exact match)' do
expect(SpreeCmCommissioner::StoreDecorator.current('api-production.bookme.plus')).to eq(store1)
expect(SpreeCmCommissioner::StoreDecorator.current('images.bookme.plus')).to eq(store2)
expect(SpreeCmCommissioner::StoreDecorator.current('static.bookme.plus')).to eq(store3)
end

it 'returns the first matching store for partial URLs' do
# Testing that multiple stores match partially, but the first store is returned
expect(SpreeCmCommissioner::StoreDecorator.current('bookme.plus')).to eq(store1) # Should return store1 first
expect(SpreeCmCommissioner::StoreDecorator.current('images.bookme')).to eq(store2) # Should return store2 first
end
end

context 'when URL is nil' do
it 'returns the default store' do
expect(SpreeCmCommissioner::StoreDecorator.current(nil)).to eq(default_store)
end
end
end
end
Loading