Class: EasyAttributes::Definition

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/easy_attributes.rb

Overview

EasyAttributes::Definition - Class of a attribute values definition

attribute    - symbolic name of the attribute, field, or column.
symbols      - Hash of {symbolic_value:value, ...}
values       - Hash of {value => :symbolic_value, ...}
options      - Hash of {option_name:value} for attribute settings
attr_options - Hash of {value_name: {option_name:value, ...}, e.g.
                       :name  - Alternate text for the value name
                       :title - Alternate text for value definition
                       :role  - Identifier for a role allowed to set/see

Constant Summary collapse

KB =

Official Definitions for kilobyte and kibibyte quantity units

1000
MB =
KB ** 2
GB =
KB ** 3
TB =
KB ** 4
PB =
KB ** 5
EB =
KB ** 6
ZB =
KB ** 7
YB =
KB ** 8
KiB =
1024
MiB =
KiB**2
GiB =
KiB**3
TiB =
KiB**4
PiB =
KiB**5
EiB =
KiB**6
ZiB =
KiB**7
YiB =
KiB**8
BINARY_UNITS =
{:B=>1,:KiB=>KiB,:MiB=>MiB,:GiB=>GiB,:TiB=>TiB,:PiB=>PiB,:EiB=>EiB,:ZiB=>ZiB,:YiB=>YiB}
DECIMAL_UNITS =
{:B=>1,:KB=>KB,  :MB=>MB,  :GB=>GB,  :TB=>TB,  :PB=>PB,  :EB=>EB,  :ZB=>ZB,  :YB=>YB}
JEDEC_UNITS =
{:B=>1,:KB=>KiB, :MB=>MiB, :GB=>GiB, :TB=>TiB, :PB=>PiB, :EB=>EiB, :ZB=>ZiB, :YB=>YiB}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attribute, *definition) ⇒ Definition

Public: Creates a new Definition for the attribute and definition list Call this method to create a non-shared definition, else call find_or_create

Examples

Definition.new(:status, active:1, inactive:2)

Returns the new instance



105
106
107
108
109
110
111
112
# File 'lib/easy_attributes.rb', line 105

def initialize(attribute, *definition)
  self.attribute = attribute.to_sym
  self.values = {}
  self.symbols = {}
  self.options = {}
  self.attr_options = {}
  self.define(*definition)
end

Instance Attribute Details

#attr_optionsObject

Returns the value of attribute attr_options.



52
53
54
# File 'lib/easy_attributes.rb', line 52

def attr_options
  @attr_options
end

#attributeObject

Returns the value of attribute attribute.



52
53
54
# File 'lib/easy_attributes.rb', line 52

def attribute
  @attribute
end

#optionsObject

Returns the value of attribute options.



52
53
54
# File 'lib/easy_attributes.rb', line 52

def options
  @options
end

#symbolsObject

Returns the value of attribute symbols.



52
53
54
# File 'lib/easy_attributes.rb', line 52

def symbols
  @symbols
end

#valuesObject

Returns the value of attribute values.



52
53
54
# File 'lib/easy_attributes.rb', line 52

def values
  @values
end

Class Method Details

.byte_units(kb_size = 0) ⇒ Object

Public: Maps the kb_size into a hash of desired unit_symbol=>bytes.

kb_size - For decimal units: 1000, :decimal, :si, :kb

For binary units : 1024, :jedec, :old, :kib
Otherwise a hash of combined values is returned

Returns a hash of prefix names to decimal quantities for the given setting



355
356
357
358
359
360
361
362
# File 'lib/easy_attributes.rb', line 355

def self.byte_units(kb_size=0)
  case kb_size
  when 1000, :decimal, :si, :kb, :KB then DECIMAL_UNITS
  when :old, :jedec, 1024, :kib, :KiB then JEDEC_UNITS
  when :new, :iec then BINARY_UNITS
  else DECIMAL_UNITS.merge(BINARY_UNITS) # Both? What's the least surprise?
  end
end

.definitionsObject



89
90
91
# File 'lib/easy_attributes.rb', line 89

def self.definitions
  @attributes
end

.find_or_create(attribute, *definition) ⇒ Object

Public: Returns an existing or new definition for the atribute name Call this method to define a global or shared setting

attribute - The name of the attribute definition - The optional definition list passed to initialize

A has of symbol_name => values
Make sure the type of value matches your use,
either a string "42" or integer "42".to_i

attr_options - A optional Hash of attribute names to a hash of additional info

{status:{help:"...", title:"Status"}}

Examples

defn = Definition.find_or_create(:status).add_symbol(:retired, 3)
defn = Definition.find_or_create(:status, active:1, inactive:2)
defn = Definition.find_or_create(:storage, {}, {kb_size:1000})
defn.values #=> {value=>:symbol,...}
defn.symbols #=> {:symbol=>:value,...}

Returns an existing or new instance of Definition



76
77
78
79
80
81
82
83
# File 'lib/easy_attributes.rb', line 76

def self.find_or_create(attribute, *definition)
  attribute = attribute.to_sym
  @attributes ||= {}
  unless @attributes.has_key?(attribute)
    @attributes[attribute] = Definition.new(attribute, *definition)
  end
  @attributes[attribute]
end

.shared(attribute, *definition) ⇒ Object



93
94
95
# File 'lib/easy_attributes.rb', line 93

def self.shared(attribute, *definition)
  find_or_create(attribute, *definition)
end

Instance Method Details

#<=>(other) ⇒ Object

Defines <=>() for Enumberable comparisons



326
327
328
# File 'lib/easy_attributes.rb', line 326

def <=>(other)
  @definition.cmp(@value,other)
end

#add_symbol(symbol, value = nil, attr_options = {}) ⇒ Object

Public: Defines an Symbol/Value for the attribute

attrib - name of the attribute or database column symbol - internal symbolic name for the value

- If nil, it will use the next value from the set of current values

value - Value to store in class or database options - Hash of name:value,… to track for the symbol. Optional.

Examples

definition.add_symbol(:active, 1)
EasyAttributes::Config.define_value :status, :active, 1, name:"Active"


160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/easy_attributes.rb', line 160

def add_symbol(symbol, value=nil, attr_options={})
  symbol = symbol.to_sym
  if value.nil?
    if a.size > 0
      value = self.values.keys.max.next
    else
      value = 0
    end
  end

  value = self.values.keys.max || 0  if value.nil?
  self.symbols[symbol] = value
  self.values[value] = symbol
  self.attr_options[symbol] = attr_options
end

#between(value, op, symbol1, symbol2 = nil) ⇒ Object

Public: Compares the value to be between the representation of of the two symbolic names Returns true if value withing the designated range, false otherwise



267
268
269
270
271
# File 'lib/easy_attributes.rb', line 267

def between(value, op, symbol1, symbol2=nil)
  v1 = value_of(symbol1)
  v2 = value_of(symbol2)
  value >= v1  && value <= v2
end

#cmp(value, symbol) ⇒ Object

Public: Implements the comparison operator (cmp, <=>) for a value against a symbolic name

Examples

definition.cmp(1,:active)  # => -1. 0, or 1 according to the <=> op defined on the value class

Returns -1 if value < symbol, 0 if value == symbol, or 1 of value < symbol



260
261
262
263
# File 'lib/easy_attributes.rb', line 260

def cmp(value, symbol)
  other = value_of(symbol)
  value <=> other
end

#define(*args) ⇒ Object

Public: Create an attribute definition

symbols - Hash of symbol:value,… for the attribute, or

- Array of enum definitions for the attribute, or
- Hash of {value:value, title:text, name:text, option_name:etc}

options - Hash of name:value,… to track for the attribute. Optional.

attr_options: {attribute: {....}, ...}

Examples

definition.define(active:1, inactive:2)
definition.define(:active, :inactive)


127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/easy_attributes.rb', line 127

def define(*args)
  return if args.first.nil?
  return define_enum(*args) if args.first.is_a?(Array)

  symbols = {}
  options = {}
  args.first.each do |k,v|
     if v.is_a?(Hash)
       symbols[k.to_sym] = v.delete(:value) {k.to_s}
       options[k.to_sym] = v
     else
       symbols[k.to_sym] = v
     end
  end

  self.symbols.merge!(symbols)
  self.values = Hash[* self.symbols.collect {|k,v| [v, k]}.flatten]
  self.attr_options.merge!(options)
end

#define_enum(args, opt = {}) ⇒ Object

Public: Defines an attribute as an enumerated set of symbol/values

args - list of symbols, reset values, with an optional options Hash

a non-symbolic arg resets the counter to that value
Non-integer values can be given if the #next() method is provided
nil can be passed to skip the positional value

Examples

definition.define_enum(:active, :inactive)
definition.define_enum(:active, :inactive, start:1, step:10)
definition.define_enum(:active, 11, :retired, nil, :inactive)


189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/easy_attributes.rb', line 189

def define_enum(args, opt={})
  opt = {step:1}.merge(opt)
  opt[:start] ||= self.values.keys.max ? self.values.keys.max + opt[:step] : Config.enum_start
  hash = {}
  i = opt[:start]
  args.flatten.each do |arg|
    if arg.is_a?(Symbol) || arg.nil?
      hash[arg] = i unless arg.nil?
      opt[:step].times {i = i.next}
    else
      i = arg
    end
  end
  define(hash)
end

#eachObject

Defines each() for Enumerable



321
322
323
# File 'lib/easy_attributes.rb', line 321

def each
  @definition.symbols.each {|s,v| yield(s,v)}
end

#format_bytes(v, *args) ⇒ Object

Private: Formats an integer as a byte-representation

v        - Integer value of bytes
unit     - Optional Unit to use for representation, regardless of magnitude
opt      - Optional hash of overrides for :kb_size, :precision, etc.

Example:

format_bytes(1000, :kb) # => "1 KB"

Returns a string like “n.nn XB” representing the approximate bytes



375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
# File 'lib/easy_attributes.rb', line 375

def format_bytes(v, *args)
  return v if v.nil?
  opt = args.last.is_a?(Hash) ? args.pop : {}
  opt = attr_options.merge(opt)
  unit = args.shift
  units = Definition.byte_units(opt[:kb_size]||Config.kb_size||1000)
  precision = opt[:precision] || attr_options[:precision] || 0

  if unit
    units = Definition.byte_units() unless units.has_key?(unit)
    v = "%.#{precision}f" % (1.0 * v / (units[unit]||1))
    return "#{v} #{unit}"
  end

  units.sort{|a,b| a[1]<=>b[1]}.reverse.each do |pv|
    next if pv[1] > v
    v = "%.#{precision}f" % (1.0 * v / pv[1])
    v.gsub!(/\.0*$/, '')
    return "#{v} #{pv[0]}"
  end
  v.to_s
end

#inspectObject



335
336
337
# File 'lib/easy_attributes.rb', line 335

def inspect
  @value
end

#next(value, default = nil) ⇒ Object Also known as: succ

Public: Returns the next value in the definition from the given value



274
275
276
277
# File 'lib/easy_attributes.rb', line 274

def next(value, default=nil)
  self.values.keys.sort.each {|i| return i if i > value }
  default
end

#parse_bytes(v, *args) ⇒ Object

Private: Parses a “1.23 kb” style string and converts into an integer v - String to parse of the format “1.23 kb” or so

Optionally, this can be an array of [1.23, :kb]

options - Hash of options to override defaults

kb_size:1000

Returns an integer of the parsed value.



405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
# File 'lib/easy_attributes.rb', line 405

def parse_bytes(v, *args)
  opt = args.last.is_a?(Hash) ? args.pop : {}
  opt = attr_options.merge(opt)
  # Handle v= [100, :KB]
  if v.is_a?(Array)
    bytes = v.shift
    v = "#{bytes} #{v.shift}"
  else
    bytes = v.to_f
  end

  if v.downcase =~ /^\s*(?:[\d\.]+)\s*([kmgtpezy]i?b)/i
    unit = ($1.size==2 ? $1.upcase : $1[0,1].upcase+$1[1,1]+$1[2,1].upcase).to_sym
    units = Definition.byte_units(opt[:kb_size]||Config.kb_size||1000)
    units = Definition.byte_units(:both) unless units.has_key?(unit)
    bytes *= units[unit] if units.has_key?(unit)
  end
  (bytes*100 + 0.00001).to_i/100
end

#previous(value, default = nil) ⇒ Object

Public: Returns the next value in the definition from the given value



281
282
283
284
# File 'lib/easy_attributes.rb', line 281

def previous(value, default=nil)
  self.values.keys.sort.reverse.each {|i| return i if i < value }
  default
end

#select_option_symbols(*args) ⇒ Object

Private: Builds a list of [option_name, symbol] pairs useful for HTML select options Where option_name is as defined in selection_option_values

attribute - symbolic name of attribute

Returns an array of [option_name, symbol] pairs.



306
307
308
# File 'lib/easy_attributes.rb', line 306

def select_option_symbols(*args)
  self.symbols.collect {|s,v| [symbol_option_name(s,*args), s]}
end

#select_option_values(*args) ⇒ Object

Public: Builds a list of [option_name, value] pairs useful for HTML select options Where option_name is the first found of:

- attr_options[:option_name]
- attr_options[:title]
- attr_options[:name]
- capitalized attribute name

attribute - symbolic name of attribute

Returns an array of [option_name, value] pairs.



296
297
298
# File 'lib/easy_attributes.rb', line 296

def select_option_values(*args)
  self.symbols.collect {|s,v| [symbol_option_name(s,*args), v]}
end

#symbol_of(value, default = nil) ⇒ Object

Public: Returns the defined symbol for the given value, or returns the supplied default, nil, or a value yeilded by a block

value - raw value of attribute, eg. 1

Examples

definition.symbol_of(1)  # => :active

Returns the defined symbol (eg.:active) for the given value on the attribute



229
230
231
# File 'lib/easy_attributes.rb', line 229

def symbol_of(value, default=nil)
  self.values.fetch(value) { block_given? ? yield(value) : default }
end

#symbol_option_name(s, *args) ⇒ Object



310
311
312
313
314
315
316
317
318
# File 'lib/easy_attributes.rb', line 310

def symbol_option_name(s, *args)
  if @attr_options.has_key?(s)
    args.each {|arg| return @attr_options[s][arg] if @attr_options[s].has_key?(arg) }
    [:option_name, :title, :name] .each do |f|
      return @attr_options[s][f] if @attr_options[s].has_key?(f)
    end
  end
  s.to_s.capitalize.gsub(/_/, ' ')
end

#to_sObject



85
86
87
# File 'lib/easy_attributes.rb', line 85

def to_s
  "<#EasyAttributes::Definition #{@attribute} #{@symbols.inspect}>"
end

#value(v) ⇒ Object

For the experimental Value class. Takes a value or symbol



331
332
333
# File 'lib/easy_attributes.rb', line 331

def value(v)
  Value.new(self, v)
end

#value_in(value, *args) ⇒ Object

Public: Returns true if the current value of the attribute is (or is in the list of values) referenced by their symbolic names

value - The value to match symbols - array of symbolic value names, eg. :active, :inactive

Examples

definition.value_in(self.status, :active)         # => false (maybe)
definition.value_in(self.:status, :active, :inactive)  # => true (maybe)
self.value_in(:status, :between, :active, :inactive)  # => true (maybe)

Returns true if the value matches



246
247
248
249
250
251
# File 'lib/easy_attributes.rb', line 246

def value_in(value, *args)
  args.each do |arg|
    return true if value == value_of(arg)
  end
  false
end

#value_of(sym, default = nil) ⇒ Object

Public: Returns the defined value for the given symbol, or returns the supplied default, nil, or a value yeilded by a block

symbol - symbolic name of value, eg. :active

Examples

definition.value_of(:active)  # => 1

Returns the defined value of symbol for the attribute



215
216
217
# File 'lib/easy_attributes.rb', line 215

def value_of(sym, default=nil)
  self.symbols.fetch(sym.to_sym) { block_given? ? yield(sym) : default }
end