module AttrMasker module Model def self.extended(base) # :nodoc: base.class_eval do attr_writer :attr_masker_options @attr_masker_options = {} @masker_attributes = {} end end # Generates attr_accessors that mask attributes transparently # # Options (any other options you specify are passed to the masker's mask # methods) # # [:masker] # The object to use for masking. It must respond to +#mask+. Defaults to # AttrMasker::Maskers::Simple. # # [:if] # Attributes are only masker if this option evaluates to true. If you # pass a symbol representing an instance method then the result of # the method will be evaluated. Any objects that respond to # :call are evaluated as well. Defaults to true. # # [:unless] # Attributes are only masker if this option evaluates to false. If you # pass a symbol representing an instance method then the result of # the method will be evaluated. Any objects that respond to # :call are evaluated as well. Defaults to false. # # [:marshal] # If set to true, attributes will be marshaled as well as masker. This # is useful if you're planning on masking something other than a string. # Defaults to false unless you're using it with ActiveRecord or # DataMapper. # # [:marshaler] # The object to use for marshaling. Defaults to Marshal. # # [:dump_method] # The dump method name to call on the :marshaler object to. # Defaults to 'dump'. # # [:load_method] # The load method name to call on the :marshaler object. # Defaults to 'load'. # # You can specify your own default options # # class User # # now all attributes will be encoded and marshaled by default # attr_masker_options.merge!(:marshal => true, :another_option => true) # attr_masker :configuration # end # # # Example # # class User # attr_masker :email, :credit_card # attr_masker :configuration, :marshal => true # end # # @user = User.new # @user.masker_email # nil # @user.email? # false # @user.email = 'test@example.com' # @user.email? # true # @user.masker_email # returns the masker version of 'test@example.com' # # @user.configuration = { :time_zone => 'UTC' } # @user.masker_configuration # returns the masker version of configuration # # See README for more examples def attr_masker(*args) default_options = { if: true, unless: false, column_name: nil, marshal: false, marshaler: Marshal, dump_method: "dump", load_method: "load", masker: AttrMasker::Maskers::SIMPLE, } options = args.extract_options!. reverse_merge(attr_masker_options). reverse_merge(default_options) args.each do |attribute_name| attribute = Attribute.new(attribute_name, self, options) masker_attributes[attribute.name] = attribute end end # Default options to use with calls to attr_masker # XXX:Keep # # It will inherit existing options from its superclass def attr_masker_options @attr_masker_options ||= superclass.attr_masker_options.dup end # Checks if an attribute is configured with attr_masker # XXX:Keep # # Example # # class User # attr_accessor :name # attr_masker :email # end # # User.attr_masker?(:name) # false # User.attr_masker?(:email) # true def attr_masker?(attribute) masker_attributes.has_key?(attribute.to_sym) end # Contains a hash of masker attributes with virtual attribute names as keys # and their corresponding options as values # XXX:Keep # # Example # # class User # attr_masker :email # end # # User.masker_attributes # { :email => { :attribute => 'masker_email' } } def masker_attributes @masker_attributes ||= superclass.masker_attributes.dup end end end