mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Merge pull request #5319 from Matt-Yorkley/caching-by-class
[Caching] Caching data by class
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
class DistributorShippingMethod < ActiveRecord::Base
|
||||
self.table_name = "distributors_shipping_methods"
|
||||
belongs_to :shipping_method, class_name: Spree::ShippingMethod
|
||||
belongs_to :shipping_method, class_name: Spree::ShippingMethod, touch: true
|
||||
belongs_to :distributor, class_name: Enterprise, touch: true
|
||||
end
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
Spree::Classification.class_eval do
|
||||
belongs_to :product, class_name: "Spree::Product", touch: true
|
||||
belongs_to :taxon, class_name: "Spree::Taxon", touch: true
|
||||
|
||||
before_destroy :dont_destroy_if_primary_taxon
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ Spree::Product.class_eval do
|
||||
has_many :option_types, through: :product_option_types, dependent: :destroy
|
||||
|
||||
belongs_to :supplier, class_name: 'Enterprise', touch: true
|
||||
belongs_to :primary_taxon, class_name: 'Spree::Taxon'
|
||||
belongs_to :primary_taxon, class_name: 'Spree::Taxon', touch: true
|
||||
|
||||
delegate_belongs_to :master, :unit_value, :unit_description
|
||||
delegate :images_attributes=, :display_as=, to: :master
|
||||
|
||||
@@ -22,4 +22,17 @@ class CacheService
|
||||
def self.latest_timestamp_by_class(cached_class)
|
||||
cached_class.maximum(:updated_at).to_i
|
||||
end
|
||||
|
||||
module FragmentCaching
|
||||
# Rails' caching in views is called "Fragment Caching" and uses some slightly different logic.
|
||||
# Note: supplied keys are actually prepended with "view/" under the hood.
|
||||
|
||||
def self.ams_all_taxons_key
|
||||
"inject-all-taxons-#{CacheService.latest_timestamp_by_class(Spree::Taxon)}"
|
||||
end
|
||||
|
||||
def self.ams_all_properties_key
|
||||
"inject-all-properties-#{CacheService.latest_timestamp_by_class(Spree::Property)}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -48,8 +48,10 @@
|
||||
= inject_current_hub
|
||||
= inject_current_user
|
||||
= inject_rails_flash
|
||||
= inject_taxons
|
||||
= inject_properties
|
||||
- cache CacheService::FragmentCaching.ams_all_taxons_key do
|
||||
= inject_taxons
|
||||
- cache CacheService::FragmentCaching.ams_all_properties_key do
|
||||
= inject_properties
|
||||
= inject_current_order
|
||||
= inject_currency_config
|
||||
= yield :injection_data
|
||||
|
||||
@@ -10,11 +10,25 @@ module OpenFoodNetwork
|
||||
end
|
||||
|
||||
def shipping_method_services
|
||||
@shipping_method_services ||= Spree::ShippingMethod.services
|
||||
@shipping_method_services ||= begin
|
||||
CacheService.cached_data_by_class("shipping_method_services", Spree::ShippingMethod) do
|
||||
# This result relies on a simple join with DistributorShippingMethod.
|
||||
# Updated DistributorShippingMethod records touch their associated Spree::ShippingMethod.
|
||||
Spree::ShippingMethod.services
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def supplied_taxons
|
||||
@supplied_taxons ||= Spree::Taxon.supplied_taxons
|
||||
@supplied_taxons ||= begin
|
||||
CacheService.cached_data_by_class("supplied_taxons", Spree::Taxon) do
|
||||
# This result relies on a join with associated supplied products, through the
|
||||
# class Classification which maps the relationship. Classification records touch
|
||||
# their associated Spree::Taxon when updated. A Spree::Product's primary_taxon
|
||||
# is also touched when changed.
|
||||
Spree::Taxon.supplied_taxons
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def all_distributed_taxons
|
||||
|
||||
76
spec/features/consumer/caching/darkwarm_caching_spec.rb
Normal file
76
spec/features/consumer/caching/darkwarm_caching_spec.rb
Normal file
@@ -0,0 +1,76 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
feature "Darkswarm data caching", js: true, caching: true do
|
||||
let!(:taxon) { create(:taxon, name: "Cached Taxon") }
|
||||
let!(:property) { create(:property, presentation: "Cached Property") }
|
||||
|
||||
let!(:producer) { create(:supplier_enterprise) }
|
||||
let!(:distributor) { create(:distributor_enterprise, with_payment_and_shipping: true, is_primary_producer: true) }
|
||||
let!(:product) { create(:simple_product, supplier: producer, primary_taxon: taxon, taxons: [taxon], properties: [property]) }
|
||||
let!(:order_cycle) { create(:simple_order_cycle, distributors: [distributor], coordinator: distributor) }
|
||||
let(:exchange) { order_cycle.exchanges.outgoing.where(receiver_id: distributor.id).first }
|
||||
|
||||
before do
|
||||
exchange.variants << product.variants.first
|
||||
end
|
||||
|
||||
describe "caching injected taxons and properties" do
|
||||
it "caches taxons and properties" do
|
||||
expect(Spree::Taxon).to receive(:all) { [taxon] }
|
||||
expect(Spree::Property).to receive(:all) { [property] }
|
||||
|
||||
visit shops_path
|
||||
|
||||
expect(Spree::Taxon).to_not receive(:all)
|
||||
expect(Spree::Property).to_not receive(:all)
|
||||
|
||||
visit shops_path
|
||||
end
|
||||
|
||||
it "invalidates caches for taxons and properties" do
|
||||
visit shops_path
|
||||
|
||||
taxon_timestamp1 = CacheService.latest_timestamp_by_class(Spree::Taxon)
|
||||
expect_cached "views/#{CacheService::FragmentCaching.ams_all_taxons_key}"
|
||||
|
||||
property_timestamp1 = CacheService.latest_timestamp_by_class(Spree::Property)
|
||||
expect_cached "views/#{CacheService::FragmentCaching.ams_all_properties_key}"
|
||||
|
||||
toggle_filters
|
||||
|
||||
within "#hubs .filter-row" do
|
||||
expect(page).to have_content taxon.name
|
||||
expect(page).to have_content property.presentation
|
||||
end
|
||||
|
||||
taxon.name = "Changed Taxon"
|
||||
taxon.save
|
||||
property.presentation = "Changed Property"
|
||||
property.save
|
||||
|
||||
visit shops_path
|
||||
|
||||
taxon_timestamp2 = CacheService.latest_timestamp_by_class(Spree::Taxon)
|
||||
expect_cached "views/#{CacheService::FragmentCaching.ams_all_taxons_key}"
|
||||
|
||||
property_timestamp2 = CacheService.latest_timestamp_by_class(Spree::Property)
|
||||
expect_cached "views/#{CacheService::FragmentCaching.ams_all_properties_key}"
|
||||
|
||||
expect(taxon_timestamp1).to_not eq taxon_timestamp2
|
||||
expect(property_timestamp1).to_not eq property_timestamp2
|
||||
|
||||
toggle_filters
|
||||
|
||||
within "#hubs .filter-row" do
|
||||
expect(page).to have_content "Changed Taxon"
|
||||
expect(page).to have_content "Changed Property"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def expect_cached(key)
|
||||
expect(Rails.cache.exist?(key)).to be true
|
||||
end
|
||||
end
|
||||
@@ -16,8 +16,8 @@ feature '
|
||||
let(:taxon_fruit) { create(:taxon, name: 'Fruit') }
|
||||
let(:taxon_veg) { create(:taxon, name: 'Vegetables') }
|
||||
|
||||
let!(:product1) { create(:simple_product, supplier: producer1, taxons: [taxon_fruit]) }
|
||||
let!(:product2) { create(:simple_product, supplier: producer2, taxons: [taxon_veg]) }
|
||||
let!(:product1) { create(:simple_product, supplier: producer1, primary_taxon: taxon_fruit, taxons: [taxon_fruit]) }
|
||||
let!(:product2) { create(:simple_product, supplier: producer2, primary_taxon: taxon_veg, taxons: [taxon_veg]) }
|
||||
|
||||
let(:shop) { create(:distributor_enterprise) }
|
||||
let!(:er) { create(:enterprise_relationship, parent: shop, child: producer1) }
|
||||
|
||||
@@ -110,13 +110,13 @@ feature 'Shops', js: true do
|
||||
|
||||
describe "taxon badges" do
|
||||
let!(:closed_oc) { create(:closed_order_cycle, distributors: [shop], variants: [p_closed.variants.first]) }
|
||||
let!(:p_closed) { create(:simple_product, taxons: [taxon_closed]) }
|
||||
let!(:p_closed) { create(:simple_product, primary_taxon: taxon_closed, taxons: [taxon_closed]) }
|
||||
let(:shop) { create(:distributor_enterprise, with_payment_and_shipping: true) }
|
||||
let(:taxon_closed) { create(:taxon, name: 'Closed') }
|
||||
|
||||
describe "open shops" do
|
||||
let!(:open_oc) { create(:open_order_cycle, distributors: [shop], variants: [p_open.variants.first]) }
|
||||
let!(:p_open) { create(:simple_product, taxons: [taxon_open]) }
|
||||
let!(:p_open) { create(:simple_product, primary_taxon: taxon_open, taxons: [taxon_open]) }
|
||||
let(:taxon_open) { create(:taxon, name: 'Open') }
|
||||
|
||||
it "shows taxons for open order cycles only" do
|
||||
|
||||
@@ -109,5 +109,15 @@ module Spree
|
||||
expect(shipping_method.include?(address)).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe "touches" do
|
||||
let!(:distributor) { create(:distributor_enterprise) }
|
||||
let!(:shipping_method) { create(:shipping_method) }
|
||||
let(:add_distributor) { shipping_method.distributors << distributor }
|
||||
|
||||
it "is touched when applied to a distributor" do
|
||||
expect{ add_distributor }.to change { shipping_method.reload.updated_at}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -28,5 +28,23 @@ module Spree
|
||||
expect(Taxon.distributed_taxons(:current)).to eq(e.id => Set.new([t1.id]))
|
||||
end
|
||||
end
|
||||
|
||||
describe "touches" do
|
||||
let!(:taxon1) { create(:taxon) }
|
||||
let!(:taxon2) { create(:taxon) }
|
||||
let!(:taxon3) { create(:taxon) }
|
||||
let!(:product) { create(:simple_product, primary_taxon: taxon1, taxons: [taxon1, taxon2]) }
|
||||
|
||||
it "is touched when a taxon is applied to a product" do
|
||||
expect{ product.taxons << taxon3 }.to change { taxon3.reload.updated_at }
|
||||
end
|
||||
|
||||
it "is touched when assignment of primary_taxon on a product changes" do
|
||||
expect do
|
||||
product.primary_taxon = taxon2
|
||||
product.save
|
||||
end.to change { taxon2.reload.updated_at }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user