Add CachedProductsRenderer - wraps ProductsRenderer using Rails cache

This commit is contained in:
Rohan Mitchell
2016-02-04 11:22:37 +11:00
parent 339f3fc2f0
commit d0b7b4ee50
2 changed files with 115 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
require 'open_food_network/products_renderer'
# Wrapper for ProductsRenderer that caches the JSON output.
# ProductsRenderer::NoProducts is represented in the cache as nil,
# but re-raised to provide the same interface as ProductsRenderer.
module OpenFoodNetwork
class CachedProductsRenderer
def initialize(distributor, order_cycle)
@distributor = distributor
@order_cycle = order_cycle
end
def products_json
products_json = Rails.cache.fetch("products-json-#{@distributor.id}-#{@order_cycle.id}") do
begin
uncached_products_json
rescue ProductsRenderer::NoProducts
nil
end
end
raise ProductsRenderer::NoProducts.new if products_json.nil?
products_json
end
private
def uncached_products_json
ProductsRenderer.new(@distributor, @order_cycle).products_json
end
end
end

View File

@@ -0,0 +1,80 @@
require 'spec_helper'
require 'open_food_network/cached_products_renderer'
require 'open_food_network/products_renderer'
module OpenFoodNetwork
describe CachedProductsRenderer do
let(:distributor) { double(:distributor, id: 123) }
let(:order_cycle) { double(:order_cycle, id: 456) }
let(:cpr) { CachedProductsRenderer.new(distributor, order_cycle) }
describe "when the products JSON is already cached" do
before do
Rails.cache.write "products-json-#{distributor.id}-#{order_cycle.id}", 'products'
end
it "returns the cached JSON" do
expect(cpr.products_json).to eq 'products'
end
it "raises an exception when there are no products" do
Rails.cache.write "products-json-#{distributor.id}-#{order_cycle.id}", nil
expect { cpr.products_json }.to raise_error ProductsRenderer::NoProducts
end
end
describe "when the products JSON is not cached" do
let(:cached_json) { Rails.cache.read "products-json-#{distributor.id}-#{order_cycle.id}" }
let(:cache_present) { Rails.cache.exist? "products-json-#{distributor.id}-#{order_cycle.id}" }
before do
Rails.cache.clear
cpr.stub(:uncached_products_json) { 'fresh products' }
end
describe "when there are products" do
it "returns products as JSON" do
expect(cpr.products_json).to eq 'fresh products'
end
it "caches the JSON" do
cpr.products_json
expect(cached_json).to eq 'fresh products'
end
end
describe "when there are no products" do
before { cpr.stub(:uncached_products_json).and_raise ProductsRenderer::NoProducts }
it "raises an error" do
expect { cpr.products_json }.to raise_error ProductsRenderer::NoProducts
end
it "caches the products as nil" do
expect { cpr.products_json }.to raise_error ProductsRenderer::NoProducts
expect(cache_present).to be
expect(cached_json).to be_nil
end
end
describe "logging a warning" do
it "logs a warning when in production"
it "logs a warning when in staging"
it "does not log a warning in development"
it "does not log a warning in test"
end
end
describe "fetching uncached products from ProductsRenderer" do
let(:pr) { double(:products_renderer, products_json: 'uncached products') }
before do
ProductsRenderer.stub(:new) { pr }
end
it "returns the uncached products" do
expect(cpr.send(:uncached_products_json)).to eq 'uncached products'
end
end
end
end