Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ShopifyEng/777ab36ff924d5c3b8d9f06455f9d74e to your computer and use it in GitHub Desktop.
Save ShopifyEng/777ab36ff924d5c3b8d9f06455f9d74e to your computer and use it in GitHub Desktop.
Repository Pattern
# ----------------------------- Gem -----------------------------
module PricingEngine
module PricingRepositoryInterface
extend T::Sig
extend T::Helpers
interface!
sig { abstract.params(ids: T::Array[Integer]).returns(T::Array[Schema::Variant]) }
def variants_by_ids(ids);end
sig { abstract.params(titles: T::Array[String]).returns(T::Array[Schema::Variant]) }
def variants_by_titles(titles);end
end
module Schema
class Variant
extend T::Sig
sig { returns(String) }
attr_accessor :title
sig { returns(Money) }
attr_accessor :price
sig { params(title: String, price: Money).void }
def initialize(title:, price:)
@title = title
@price = price
end
end
end
end
module PricingEngine
class Engine
sig do
params(
repository: PricingEngine::PricingRepositoryInterface
).void
end
# @param repository [PricingEngine::PricingRepositoryInterface] environment specific functions to
# access db and cache data.
#
# @return [void]
def initialize(repository)
@repository = repository
end
#...
sig do
params(
context: [Schema::BuyerContext]
).returns(T::Array[PricingEngine::Schema::Price])
end
# Calculates the price for variants given the buyer context.
#
# @param context [Schema::BuyerContext] the buyer context.
#
# @return [Array<PricingEngine::Schema::Price>] An array of prices for the context passed.
def calculate_prices_for_variants(context)
variant_ids = get_variant_ids_from_context(context)
variants = @repository.variants_by_ids(variant_ids)
process(variants)
end
end
end
# ----------------------------- Consumer 1 Logic -----------------------------
require 'pricing_engine'
module ShopifyCore
class PricingRepository
extend T::Sig
include(PricingEngine::PricingRepositoryInterface)
sig { override.params(ids: T::Array[Integer]).returns(T::Array[PricingEngine::Schema::Variant]) }
def variants_by_ids(ids)
variants = ProductVariant.where(id: ids).select(:title, :price).limit(50)
variants.map { |variant| PricingEngine::Schema::Variant.new(title: variant.title, price: variant.price) }
end
sig { override.params(titles: T::Array[String]).returns(T::Array[PricingEngine::Schema::Variant]) }
def variants_by_titles(titles)
variants = ProductVariant.where(title: titles).select(:title, :price).limit(50)
variants.map { |variant| PricingEngine::Schema::Variant.new(title: variant.title, price: variant.price) }
end
end
end
# ----------------------------- Consumer 2 Logic -----------------------------
require 'pricing_engine'
module StorefrontRenderer
class PricingRepository
extend T::Sig
include(PricingEngine::PricingRepositoryInterface)
sig { override.params(ids: T::Array[String]).returns(T::Array[PricingEngine::Schema::Variant]) }
def variants_by_ids(ids)
variants = DataStoreConnection.execute("SELECT title, price FROM variants WHERE id in (?)", ids).limit(50)
variants.map { |variant| PricingEngine::Schema::Variant.new(title: variant.title, price: variant.price) }
end
sig { override.params(titles: T::Array[String]).returns(T::Array[PricingEngine::Schema::Variant]) }
def variants_by_titles(titles)
variants = DataStoreConnection.execute("SELECT title, price FROM variants WHERE title in (?)", titles).limit(50)
variants.map { |variant| PricingEngine::Schema::Variant.new(title: variant.title, price: variant.price) }
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment