Replace proxies with modules

This commit is contained in:
Rohan Mitchell
2014-12-18 10:20:31 +11:00
parent 0832a8f63d
commit e6eecd3ae2
7 changed files with 60 additions and 107 deletions

View File

@@ -1,4 +1,4 @@
require 'open_food_network/variant_proxy'
require 'open_food_network/scope_variant_to_hub'
class Api::ProductSerializer < ActiveModel::Serializer
# TODO
@@ -43,9 +43,13 @@ class Api::CachedProductSerializer < ActiveModel::Serializer
has_one :master, serializer: Api::VariantSerializer
def variants
# We use the in_stock? method here instead of the in_stock scope because we need to
# look up the stock as overridden by VariantOverrides, and the scope method is not affected
# by them.
object.variants.
for_distribution(options[:current_order_cycle], options[:current_distributor]).
in_stock.
map { |v| OpenFoodNetwork::VariantProxy.new(v, options[:current_distributor]) }
each { |v| v.scope_to_hub options[:current_distributor] }.
select(&:in_stock?)
end
end

View File

@@ -1,23 +0,0 @@
require 'open_food_network/variant_proxy'
module OpenFoodNetwork
# Variants can have several fields overridden on a per-enterprise basis by the
# VariantOverride model. These overrides can be applied to variants by wrapping their
# products in this proxy, which wraps the product's variants in VariantProxy.
class ProductProxy
instance_methods.each { |m| undef_method m unless m =~ /(^__|^send$|^object_id$)/ }
def initialize(product, hub)
@product = product
@hub = hub
end
def variants
@product.variants.map { |v| VariantProxy.new(v, @hub) }
end
def method_missing(name, *args, &block)
@product.send(name, *args, &block)
end
end
end

View File

@@ -0,0 +1,18 @@
module OpenFoodNetwork
module ScopeVariantToHub
def price
VariantOverride.price_for(@hub, self) || super
end
def count_on_hand
VariantOverride.count_on_hand_for(@hub, self) || super
end
end
end
Spree::Variant.class_eval do
def scope_to_hub(hub)
extend OpenFoodNetwork::ScopeVariantToHub
@hub = hub
end
end

View File

@@ -1,27 +0,0 @@
module OpenFoodNetwork
# Variants can have several fields overridden on a per-enterprise basis by the
# VariantOverride model. These overrides can be applied to variants by wrapping in an
# instance of the VariantProxy class. This class proxies most methods back to the wrapped
# variant, but checks for overrides when fetching some properties.
class VariantProxy
instance_methods.each { |m| undef_method m unless m =~ /(^__|^send$|^object_id$)/ }
def initialize(variant, hub)
@variant = variant
@hub = hub
end
def price
VariantOverride.price_for(@hub, @variant) || @variant.price
end
def price_with_fees(distributor, order_cycle)
price + @variant.fees_for(distributor, order_cycle)
end
def method_missing(name, *args, &block)
@variant.send(name, *args, &block)
end
end
end

View File

@@ -1,27 +0,0 @@
require 'open_food_network/product_proxy'
require 'open_food_network/variant_proxy'
module OpenFoodNetwork
describe ProductProxy do
let(:hub) { double(:hub) }
let(:p) { double(:product, name: 'name') }
let(:pp) { ProductProxy.new(p, hub) }
describe "delegating calls to proxied product" do
it "delegates name" do
pp.name.should == 'name'
end
end
describe "fetching the variants" do
let(:v1) { double(:variant) }
let(:v2) { double(:variant) }
let(:p) { double(:product, variants: [v1, v2]) }
it "returns variants wrapped in VariantProxy" do
# #class is proxied too, so we test that it worked by #object_id
pp.variants.map(&:object_id).sort.should_not == [v1.object_id, v2.object_id].sort
end
end
end
end

View File

@@ -0,0 +1,35 @@
require 'open_food_network/scope_variant_to_hub'
module OpenFoodNetwork
describe ScopeVariantToHub do
let(:hub) { create(:distributor_enterprise) }
let(:v) { create(:variant, price: 11.11, count_on_hand: 1) }
let(:vo) { create(:variant_override, hub: hub, variant: v, price: 22.22, count_on_hand: 2) }
describe "overriding price" do
it "returns the overridden price when one is present" do
vo
v.scope_to_hub hub
v.price.should == 22.22
end
it "returns the variant's price otherwise" do
v.scope_to_hub hub
v.price.should == 11.11
end
end
describe "overriding stock levels" do
it "returns the overridden stock level when one is present" do
vo
v.scope_to_hub hub
v.count_on_hand.should == 2
end
it "returns the variant's stock level otherwise" do
v.scope_to_hub hub
v.count_on_hand.should == 1
end
end
end
end

View File

@@ -1,27 +0,0 @@
require 'open_food_network/variant_proxy'
module OpenFoodNetwork
describe VariantProxy do
let(:hub) { double(:hub) }
let(:v) { double(:variant, sku: 'sku123', price: 'global price') }
let(:vp) { VariantProxy.new(v, hub) }
describe "delegating calls to proxied variant" do
it "delegates sku" do
vp.sku.should == 'sku123'
end
end
describe "looking up the price" do
it "returns the override price when there is one" do
VariantOverride.stub(:price_for) { 'override price' }
vp.price.should == 'override price'
end
it "returns the global price otherwise" do
VariantOverride.stub(:price_for) { nil }
vp.price.should == 'global price'
end
end
end
end