attr_masker icon indicating copy to clipboard operation
attr_masker copied to clipboard

Enhancement: Brand new DSL

Open synth opened this issue 3 years ago • 11 comments

First, Thank you for this gem!

So, I definitely see an argument for putting the attr_masker calls inside the models as its currently implemented. But there is also an argument for a centralized global configuration so all the masker calls are together and managed independently of the ORM (ActiveRecord) models. Further, this enables common conditions and custom maskers to be reused across models.

Thanks to the beauty of ruby, this is easy to do. Here is a sample from our app

# config/initializers/attr_masker.rb
require 'faker' # Faker gem for simple realistic data masking
leave_alone_domains = ["primarydomain.com", "secondarydomain.io"]

Company.class_eval do
  condition = ->(company) { !company.domain.in?(leave_alone_domains) }
  domain_mask = ->(**) { "#{Faker::Internet.unique.domain_word}.fake.#{Faker::Internet.domain_suffix}" }

  attr_masker :domain, if: condition, masker: domain_mask
end

User.class_eval do
  condition = ->(user) { user.network.in?(leave_alone_domains) }
  email_mask = ->(model:, **) { "user#{model.id}@example.com" }

  attr_masker :email, unless: condition, masker: email_mask
  attr_masker :name, unless: condition
end

The above works beautifully but obviously is a bit cumbersome syntax. We can do better if this gem supported a higher level dsl. Here is one suggestion:

# config/initializers/attr_masker.rb

condition = ->(company) { !company.domain.in?(leave_alone_domains) }
domain_mask = ->(**) { "#{Faker::Internet.unique.domain_word}.fake.#{Faker::Internet.domain_suffix}" }
email_mask = ->(model:, **) { "user#{model.id}@example.com" }

attr_masker Company, :domain, if: condition, masker: domain_mask
attr_masker User, :email, if: condition, masker: email_mask

# or alternately do it in a block

attr_masker do
  mask Company, :domain, if: condition, masker: domain_mask
  mask User, :email, if: condition, masker: email_mask
end

I think something like this would be fairly simple to implement. I could potentially submit a PR if you think this is useful. Let me know! Thanks again!

synth avatar Feb 28 '21 18:02 synth