Reputation: 2761
I'm trying to figure out the best way to model something and haven't found much yet to help.
My app has a sort of reporting hierarchy. Users are a part of an organization which is part of an account.
I'm trying to figure out the right way to model "Settings". So a given account can default values for settings for all accounts under then. Those defaults can be overridden at the organization level and the user can further override them.
Do far I've handled this by just mapping each record to the appropriate parent record (user, account, org) but on a query there's a lot of work to combine them all and get the final definitive settings list.
Any thoughts on the right way to handle this?
Upvotes: 0
Views: 62
Reputation: 2877
My key thoughts:
Hash
jsonb
as PostgreSQL example)Hash#deep_merge
to override SettingsExample:
class User < ApplicationRecord
belongs_to :organization
# settings | jsonb | not null default '{}'::jsonb
# ...
class Organization < ApplicationRecord
belongs_to :account
# settings | jsonb | not null default '{}'::jsonb
# ...
class Account < ApplicationRecord
# settings | jsonb | not null default '{}'::jsonb
# ...
Then
class Settings
cattr_reader :global_settings do
# hash = ... read global settings somehow
hash.freeze # prevent global settings from changes
end
def self.settings_for(user_id)
User
.joins(organization: :account)
.where(id: user_id)
.limit(1)
.pluck(*%w[ accounts.settings organizations.settings users.settings ])
.first
.reduce(global_settings){ |memo, e| memo.deep_merge(e) }
# or
# .each_with_object(global_settings.dup){ |e, memo| memo.deep_merge!(e) }
end
# ...
Settings.settings_for(111)
It costs one fast DB query( deep_merge
<< DB query), front-end likes to deal with JSON. So it will work. At least for start.
Upvotes: 1