diff --git a/README.md b/README.md index 019bcf6..f51b6cc 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,16 @@ Time zone objects also work. To see a list of available time zones in Rails, run See [date storage](#date-storage) for how dates are stored. +### Multiple Databases + +Specify a `writing_role` when you want to explicitly switch the database role when writing the rollup to the database. + +```ruby +Rollup.writing_role = :writing +``` + +See [ActiveRecord::Base.connected_to](https://guides.rubyonrails.org/active_record_multiple_databases.html#connecting-to-the-database) for more information. + ### Calculations Rollups use `count` by default. For other calculations, use: diff --git a/lib/rollup.rb b/lib/rollup.rb index 91fa723..af30d49 100644 --- a/lib/rollup.rb +++ b/lib/rollup.rb @@ -5,6 +5,7 @@ class Rollup < ActiveRecord::Base class << self attr_accessor :week_start + attr_accessor :writing_role attr_writer :time_zone end self.week_start = :sunday diff --git a/lib/rollup/aggregator.rb b/lib/rollup/aggregator.rb index 99d6189..9e11007 100644 --- a/lib/rollup/aggregator.rb +++ b/lib/rollup/aggregator.rb @@ -19,7 +19,9 @@ def rollup(name, column: nil, interval: "day", dimension_names: nil, time_zone: records = prepare_result(result, name, dimension_names, interval) maybe_clear(clear, name, interval) do - save_records(records) if records.any? + with_writing_role do + save_records(records) if records.any? + end end end @@ -184,6 +186,14 @@ def maybe_clear(clear, name, interval) end end + def with_writing_role(&block) + if Rollup.writing_role.present? + ActiveRecord::Base.connected_to(role: Rollup.writing_role, &block) + else + block.call + end + end + def save_records(records) # order must match unique index # consider using index name instead diff --git a/test/aggregator_test.rb b/test/aggregator_test.rb index 3e92c54..de963f0 100644 --- a/test/aggregator_test.rb +++ b/test/aggregator_test.rb @@ -133,4 +133,37 @@ def test_range_current end assert_equal "Cannot use range and current together", error.message end + + def test_writing_role_switching + connected_to_args = nil + ActiveRecord::Base.singleton_class.define_method(:connected_to) do |role:, &block| + connected_to_args = role + block.call + end + + create_users + Rollup.writing_role = :writing + User.rollup("Test") + + assert_equal :writing, connected_to_args, "Expected connected_to to be called with writing role" + ensure + ActiveRecord::Base.singleton_class.remove_method(:connected_to) + Rollup.writing_role = nil + end + + def test_no_writing_role_switching + connected_to_called = false + ActiveRecord::Base.singleton_class.define_method(:connected_to) do |role:, &block| + connected_to_called = true + block.call + end + + create_users + Rollup.writing_role = nil + User.rollup("Test") + + refute connected_to_called, "Expected connected_to not to be called when writing_role is nil" + ensure + ActiveRecord::Base.singleton_class.remove_method(:connected_to) + end end