Class: Passlib::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/passlib/configuration.rb

Overview

Thread-safe, chainable configuration object.

Each algorithm class has its own configuration subclass (e.g. Configuration::BCrypt) whose options are auto-registered via the options DSL macro in the algorithm class body. A child configuration inherits defaults from a parent and can override individual options without mutating the parent.

The global Passlib configuration is accessible via Passlib.configuration (aliased as Passlib.config).

Examples:

Reading a configuration value

Passlib.configuration.bcrypt.cost  # => nil (use algorithm default)

Setting a global default

Passlib.config.bcrypt.cost = 12

Direct Known Subclasses

Passlib

Defined Under Namespace

Modules: Context Classes: Passlib

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*arguments, &block) ⇒ Configuration

Creates a new configuration instance.

Parameters:

  • arguments (Array<Configuration, Hash, Proc, nil>)

    zero or more parent configurations (at most one) and/or option hashes to apply immediately, nil entries are silently ignored

  • block (Proc)

    if given, used as a lazy parent configuration



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/passlib/configuration.rb', line 88

def initialize(*arguments, &block)
  super()
  arguments << block if block

  @parent  = nil
  @options = Concurrent::Map.new

  arguments.flatten.each do |argument|
    case argument
    when nil
      # ignore
    when Configuration, Proc
      raise ArgumentError, "cannot set multiple parent configurations" if @parent
      @parent = argument
    else
      apply(argument.to_hash)
    end
  end
end

Class Method Details

.available_optionsObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



76
77
78
79
80
# File 'lib/passlib/configuration.rb', line 76

def self.available_options
  inherited = superclass.respond_to?(:available_options) ? superclass.available_options : []
  @available_options ||= []
  inherited + @available_options
end

.newObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



25
# File 'lib/passlib/configuration.rb', line 25

def self.new(...) = self == Configuration ? Passlib.new(...) : super(...)

.option(key, default = nil) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/passlib/configuration.rb', line 28

def self.option(key, default = nil)
  @available_options << key unless available_options.include? key

  if const_defined?(:Generated, false)
    mixin = const_get(:Generated, false)
  else
    mixin = Module.new
    const_set(:Generated, mixin)
    include mixin
  end

  mixin.module_eval do
    if default.is_a? Configuration
      define_method("#{key}=") { public_send(key).set(it) }
      define_method(key) do
        @options.compute_if_absent(key) do
          result = default.class.new(parent ? parent.public_send(key) : default)
          frozen? ? result.freeze : result
        end
      end
    else
      define_method("#{key}=") do |value|
        raise FrozenError, "can't modify frozen configuration" if frozen?
        @options[key] = value
      end
      define_method(key) do
        @options.fetch(key) do
          value = parent ? parent.public_send(key) : default
          value = value.dup.freeze unless value.frozen?
          value
        end
      end
    end
  end
end

.options(*list) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



65
66
67
68
69
70
71
72
73
# File 'lib/passlib/configuration.rb', line 65

def self.options(*list)
  list.each do |entry|
    case entry
    when Symbol then option(entry)
    when Hash   then entry.each { option(_1, _2) }
    else raise ArgumentError, "invalid option: #{entry.inspect}"
    end
  end
end

Instance Method Details

#apply(options) ⇒ void

This method returns an undefined value.

Applies a hash of option values by calling the corresponding setters.

Parameters:

  • options (#each)

    key/value pairs to apply



128
# File 'lib/passlib/configuration.rb', line 128

def apply(options) = options.each { public_send(:"#{_1}=", _2) }

#freezeself

Freezes this configuration and all nested option values in place. Changes to a parent configuration will no longer have any effect.

Returns:

  • (self)


159
160
161
162
163
164
165
166
167
# File 'lib/passlib/configuration.rb', line 159

def freeze
  return self if frozen?
  @parent = @parent&.call
  self.class.available_options.each { @options[it] = public_send(it).freeze }
  @to_h ||= to_h.freeze
  super
rescue FrozenError
  self
end

#hashInteger

Returns a hash value for this configuration, based on the hash of the options hash returned by #to_h.

Returns:

  • (Integer)


153
# File 'lib/passlib/configuration.rb', line 153

def hash = to_h.hash

#inspectString

Returns a human-readable representation of this configuration.

Returns:

  • (String)


171
# File 'lib/passlib/configuration.rb', line 171

def inspect = "#<Passlib::Configuration #{to_h.inspect}>"

#parentConfiguration?

The parent configuration from which defaults are inherited, or nil.

Returns:



110
# File 'lib/passlib/configuration.rb', line 110

def parent = @parent&.call

#pretty_print(pp) ⇒ void

This method returns an undefined value.

Pretty-print support for pp.

Parameters:

  • pp (PP)

    the pretty-printer instance



176
177
178
179
180
181
# File 'lib/passlib/configuration.rb', line 176

def pretty_print(pp)
  pp.group(1, "#<Passlib::Configuration", ">") do
    pp.breakable
    pp.pp to_h
  end
end

#set(options) ⇒ void

This method returns an undefined value.

Replaces all current options.

If options is a Passlib::Configuration it becomes the new parent, otherwise the options map is cleared and the hash is applied via #apply.

Parameters:



119
120
121
122
# File 'lib/passlib/configuration.rb', line 119

def set(options)
  @options.clear
  options.is_a?(Configuration) ? @parent = options : apply(options)
end

#to_hHash{Symbol => Object} Also known as: to_hash

Returns all explicitly-set options (and nested configurations) as a Hash.

Nested Passlib::Configuration values are converted recursively, empty nested hashes are omitted.

Returns:

  • (Hash{Symbol => Object})


136
137
138
139
140
141
142
143
144
145
146
# File 'lib/passlib/configuration.rb', line 136

def to_h
  return @to_h if instance_variable_defined?(:@to_h)
  self.class.available_options.to_h do |key|
    value = public_send(key)
    if value.is_a? Configuration
      value = value.to_h
      value = nil if value.empty?
    end
    [key, value]
  end.compact
end