Class: RCite::Option

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/rcite/option.rb

Overview

Represents an option. Option objects provide useful helper methods for the flexible validation and transformation of option values.

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (Option) initialize(name, options = {}, &block)

Creates a new Option. All instance variables can be set using the options hash.

Examples:

Option.new(:opt_name, allow_nil:   false,
                      validator:   { |val| ! val.empty? }) do |val|
  val.is_a?(Array) ? val.map(&:strip) : val
end

Parameters:

  • name (#to_sym)

    This option's name. May neither be nil nor an empty string. Please make sure that no two options have the same name, as this would likely lead to confusion.

  • options (Hash) (defaults to: {})

    Options hash. Keys correspond to public attributes of this class; values are their value.

  • &block

    The block, if one is given, is turned into a Proc object and assigned to the #transformer attribute.

Raises:

  • ArgumentError if name is nil or empty.



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/rcite/option.rb', line 105

def initialize(name, options = {}, &block)
  raise ArgumentError, 'name cannot be empty' unless name && name != ''

  @name = name.to_sym
  @transformer = Proc.new if block_given?
  @allow_nil = true
  @good_values, @bad_values = [], []

  options.each_pair do |k,v|
    method = (k.to_s+'=').to_sym
    raise ArgumentError, 'invalid option: #{k}' unless respond_to?(method)
    send(method, v)
  end

  @values ||= @default
end

Instance Attribute Details

- (true, false) allow_nil

Returns Determines whether nil values are allowed.

Returns:

  • (true, false)

    Determines whether nil values are allowed.



60
61
62
# File 'lib/rcite/option.rb', line 60

def allow_nil
  @allow_nil
end

- (Array<Object>) bad_values

List of objects that are invalid values for this option.

#good_values takes precedence over this list, so if an item is present on that list as well, it is considered valid.

Returns:

  • (Array<Object>)

    List of objects that are invalid values for this option.



84
85
86
# File 'lib/rcite/option.rb', line 84

def bad_values
  @bad_values
end

- (Object?) default

Returns Default value for this option. Needs not be valid in the sense of #validate. May be an array of arbitrary objects (including other arrays).

Returns:

  • (Object, nil)

    Default value for this option. Needs not be valid in the sense of #validate. May be an array of arbitrary objects (including other arrays).



54
55
56
# File 'lib/rcite/option.rb', line 54

def default
  @default
end

- (Array<Object>) good_values

List of objects that are valid values for this option. This list is non-exclusive, so items that are not on it may still be valid according to the #validator.

This list takes precedence over #bad_values, so if an item is listed on both, it is considered valid.

Examples:

Making good_values exclusive

# With the following options set, all values that are not on this
# list will be discarded.
style.good_values = [:good, :values]
style.validator   = proc { false }

Returns:

  • (Array<Object>)

    List of objects that are valid values for this option.



76
77
78
# File 'lib/rcite/option.rb', line 76

def good_values
  @good_values
end

- (Symbol) name

Returns This option's name. Should be descriptive yet short because Style creates helper methods whose names are derived from this attribute.

Returns:

  • (Symbol)

    This option's name. Should be descriptive yet short because Style creates helper methods whose names are derived from this attribute.



11
12
13
# File 'lib/rcite/option.rb', line 11

def name
  @name
end

- (Object) transformer

An Object indicating which transformation should be applied to values that are added using #set. Can be one of the following:

  1. A Proc object -- for each value transformation, the Proc is called with the value as the only argument.
  2. One of the standard classes String, Symbol, Integer and Float -- this option will attempt to transform each value to an object of the given class. Transforms to nil if the value does not respond to the respective conversion method.
  3. true or false -- values are converted to true or false. If a value is false, nil, "false" or :false, it is converted to false; other values are converted to true.
  4. Any Class objects -- values are replaced with the return value of class.new(value). Transforms to nil if the given class does not respond to new. May throw errors if the class's constructor demands other parameters.

Examples:

Proc object

style.transformer = proc { |val| val.map(&:strip) }
style.transform(' stuff ') # => 'stuff'

Standard classes

style.transformer = String
style.transform(:symbol)   # => 'symbol'

true/false

style.transformer = true
style.transform(:false)    # => false

other classes

style.transformer = Option
style.transform(:opt_name) # => Option (with name == :opt_name)

Returns:

  • (Object)

    This options's transformer.



50
51
52
# File 'lib/rcite/option.rb', line 50

def transformer
  @transformer
end

- (Proc?) validator

Returns A Proc that is used to determine (together with #good_values, #bad_values and #allow_nil) whether

Returns:

  • (Proc, nil)

    A Proc that is used to determine (together with #good_values, #bad_values and #allow_nil) whether



58
59
60
# File 'lib/rcite/option.rb', line 58

def validator
  @validator
end

- (Object?) values Also known as: get

This option's current value(s). If the option has multiple values, they are represented by an Array (which may include more Arrays for value tupels and such).

Returns:

  • (Object, nil)

    This option's current value(s). May be nil if the option has not yet been set.



17
18
19
# File 'lib/rcite/option.rb', line 17

def values
  @values
end

Instance Method Details

- (-1, ...) <=>(other)

Compares this option with other. The option's #name is the sole criterion for comparison. Therefore you are advised to make sure that no two options share the same name.

Parameters:

  • other (Option)

    Another option.

Returns:

  • (-1, 0, 1)

    self.name <=> other.name



254
255
256
# File 'lib/rcite/option.rb', line 254

def <=>(other)
  @name <=> other.name
end

- (Array<Object>, ...) set(*values) Also known as: values=

Assigns one or more values to this option. Performs all validations and transformations prior to assignment. Validation is performed after transformation so you have the possibility of 'rescuing' invalid values by transforming them.

If multiple values are given, they are turned into a flattened array and compacted before the assignment. The #allow_nil directive is only considered violated if all elements of values are nil. This is determined prior to transformation and validation.

If values contains exactly one element after validation and transformation, #values is assinged a single object rather than an Array.

Parameters:

  • values (Array<Object>)

    One or more values that should be assigned to this option.

Returns:

  • (Array<Object>, Object, nil)

    The final value assigned to #values.



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/rcite/option.rb', line 139

def set(*values)
  vals = values.flatten.compact

  if vals.empty?
    unless @default || @allow_nil
      raise ArgumentError, "Nil values are not allowed for option #{@name}."
    end
    return @values = @default
  end

  vals.each do |val|
    transform!(val)
    unless validate(val)
      raise ArgumentError, "Invalid value for option #{@name}: '#{val}'."
    end
  end

  @values = vals.size == 1 ? vals[0] : vals
end

- (Object) transform!(value)

Transforms value in-place according to the procedure specified by #transformer. See the discussion there for further information.

Parameters:

  • value (Object)

    the value that should be transformed.

Returns:

  • (Object)

    the transformed value.



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/rcite/option.rb', line 187

def transform!(value)
  if @transformer.is_a?(Class)
    return case @transformer.to_s
    when 'String'  then value.respond_to?(:to_s)   ? value.to_s   : nil
    when 'Symbol'  then value.respond_to?(:to_sym) ? value.to_sym : nil
    when 'Integer' then value.respond_to?(:to_i)   ? value.to_i   : nil
    when 'Float'   then value.respond_to?(:to_f)   ? value.to_f   : nil
    else @transformer.respond_to?(:new) ? @transformer.new(value) : nil
    end
  end

  case @transformer
  when true, false
    case value
    when true, false          then value
    when nil, "false", :false then false
    else true
    end
  when Proc
    @transformer.call(value)
  else
    value
  end
end

- (true, false) validate(value)

Validates a value for this option. Tests the following conditions (in the specified order):

  1. #good_values includes the value; if so true is returned and all other validations are skipped.
  2. #bad_values includes the value; if so false is returned and all other validations are skipped.
  3. #validator is nil; if so true is returned.
  4. If the above validations don't succeed or fail, the return value of #validator.call(value) is returned.

Parameters:

  • value (Object)

    The value whose validity should be determined.

Returns:

  • (true, false)

    true if value is valid, false otherwise.



175
176
177
178
179
180
# File 'lib/rcite/option.rb', line 175

def validate(value)
  return true  if @good_values.include?(value)
  return false if @bad_values. include?(value)
  return true  unless @validator
  return @validator.call(value)
end