From f81f52471e3256a2cfec97d2921a3ff887d077bb Mon Sep 17 00:00:00 2001 From: Jeremy Williams Date: Fri, 20 May 2022 16:25:21 -0400 Subject: [PATCH] Add configurable support for using a money adapter Unfortunately `shopify-money` and `money` do not play well together. Both gems provide a `Money` class and an entry point into the gem at `lib/money.rb`. This makes it pretty difficult to include double_entry in a codebase that makes use of the `shopify-money` gem. To work around this I've added a configuration option `money_adapter` that allows double_entry to be configured to internally delegate methods to this adapter instead of using the `money` gem directly. This allows users of double_entry to provide an adapter class that allows integration with arbitrary money backends for better interoperability with their system. This was done by adding a `DoubleEntry::Money` class that delegates its singleton methods to the adapter. --- lib/double_entry.rb | 2 +- lib/double_entry/configuration.rb | 8 ++++++++ lib/double_entry/money.rb | 15 +++++++++++++++ spec/double_entry/money_spec.rb | 16 ++++++++++++++++ spec/support/money.rb | 3 ++- 5 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 lib/double_entry/money.rb create mode 100644 spec/double_entry/money_spec.rb diff --git a/lib/double_entry.rb b/lib/double_entry.rb index bdabbc84..85cf0532 100644 --- a/lib/double_entry.rb +++ b/lib/double_entry.rb @@ -3,7 +3,6 @@ require 'active_record/locking_extensions' require 'active_record/locking_extensions/log_subscriber' require 'active_support/all' -require 'money' require 'rails/railtie' require 'double_entry/version' @@ -16,6 +15,7 @@ require 'double_entry/locking' require 'double_entry/transfer' require 'double_entry/validation' +require 'double_entry/money' # Keep track of all the monies! # diff --git a/lib/double_entry/configuration.rb b/lib/double_entry/configuration.rb index 9d361dac..7e60249f 100644 --- a/lib/double_entry/configuration.rb +++ b/lib/double_entry/configuration.rb @@ -4,11 +4,19 @@ module DoubleEntry class Configuration attr_accessor :json_metadata + attr_writer :money_adapter def initialize @json_metadata = false end + def money_adapter + @money_adapter ||= begin + require 'money' + ::Money + end + end + delegate( :accounts, :accounts=, diff --git a/lib/double_entry/money.rb b/lib/double_entry/money.rb new file mode 100644 index 00000000..db9dc717 --- /dev/null +++ b/lib/double_entry/money.rb @@ -0,0 +1,15 @@ +# encoding: utf-8 +module DoubleEntry + module Money + class << self + attr_writer :adapter + + def adapter + @adapter ||= DoubleEntry.config.money_adapter + end + + delegate(:new, to: :adapter) + delegate_missing_to(:adapter) + end + end +end diff --git a/spec/double_entry/money_spec.rb b/spec/double_entry/money_spec.rb new file mode 100644 index 00000000..7c5eab49 --- /dev/null +++ b/spec/double_entry/money_spec.rb @@ -0,0 +1,16 @@ +RSpec.describe DoubleEntry::Money do + it 'delegates singleton methods to the adapter' do + DoubleEntry::Money.adapter = Class.new do + def self.zero + 0 + end + + def test + 12345 + end + end + expect(DoubleEntry::Money.new.test).to eq(12345) + expect(DoubleEntry::Money.zero).to eq(0) + DoubleEntry::Money.adapter = ::Money + end +end diff --git a/spec/support/money.rb b/spec/support/money.rb index 452a5f50..4765ec87 100644 --- a/spec/support/money.rb +++ b/spec/support/money.rb @@ -1 +1,2 @@ -Money.locale_backend = :i18n +require 'money' +::Money.locale_backend = :i18n