Class: CsvHuman::Tag

Inherits:
Object
  • Object
show all
Defined in:
lib/csvhuman/tag.rb

Constant Summary collapse

SEP_REGEX =

1) plus (with optional hashtag and/or optional leading and trailing spaces)

2) hashtag (with optional leading and trailing spaces)
3) spaces only (not followed by plus) or
 note: plus pattern must go first (otherwise "sector  + en" becomes ["sector", "", "en"])
/(?:  \s*\++
          (?:\s*\#+)?
      \s*  )
     |
 (?:  \s*\#+\s*  )
     |
 (?:  \s+)
/x

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, attributes = nil, type = String) ⇒ Tag

Returns a new instance of Tag.



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/csvhuman/tag.rb', line 98

def initialize( name, attributes=nil, type=String )
  @name       = name
  ## sorted a-z - note: make sure attributes is [] NOT nil if empty - why? why not?
  @attributes = attributes || []
  ## todo/check attributes:
  ##  "extract" two-letter language codes e.g. en, etc. - why? why not?
  ##  "extract" type codes e.g. num, date - why? why not?

  ## type as
  ##  - class (defaults to String) or
  ##  - "custom" symbol (e.g. :geo, :geo_lat_lon,:geo_coords,:code,:id, etc.)
  @type       = type

  if @type == String    ## note: String gets passed through as-is 1:1 (no converter required)
    @conv = nil
  else
    @conv = TYPE_CONVERTERS[ @type ]

    if @conv.nil?
      ## todo/check: use a different exception - why? why not?
      ##  default to string (and warning only) - why? why not?
      raise ArgumentError, "missing type converter >#{type.inspect}< for tag >#{to_s}<"
    end
  end
end

Instance Attribute Details

#attributesObject (readonly)

use attribs or something shorter - why? why not?



94
95
96
# File 'lib/csvhuman/tag.rb', line 94

def attributes
  @attributes
end

#nameObject (readonly)

Returns the value of attribute name.



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

def name
  @name
end

#typeObject (readonly)

Returns the value of attribute type.



95
96
97
# File 'lib/csvhuman/tag.rb', line 95

def type
  @type
end

Class Method Details

.normalize(value) ⇒ Object

todo: rename to pretty or something or add alias



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/csvhuman/tag.rb', line 43

def self.normalize( value )   ## todo: rename to pretty or something or add alias
  parts = split( value )
  name       = parts[0]
  attributes = parts[1..-1]   ## note: might be nil

  buf = ''
  if name  ## note: name might be nil too e.g. value = "" or value = "   "
    buf << '#' + name
    if attributes && attributes.size > 0
      buf << ' +'
      buf << attributes.join(' +')
    end
  end
  buf
end

.parse(value, types: nil) ⇒ Object

todo/check: find a better name for optional types keyword/option - why? why not?



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/csvhuman/tag.rb', line 62

def self.parse( value, types: nil )
  parts = split( value )

  name       = parts[0]
  attributes = parts[1..-1]   ## todo/fix: check if nil (make it empty array [] always) - why? why not?


  ## fix!!!!
  ##   move types up to parser itself (only one lookup for datafile)!!!

  ## guess / map type
  types = :default   if types.nil?

  if types.is_a?( Proc )    ## allow/support "custom" mapping procs
    guess_type = types
  else  ## assume symbol (for lookup pre-built/known mapping procs)
    guess_type = TYPE_MAPPINGS[ types ]
    if guess_type.nil?
      ## todo/check: issue warning only (and fallback to none/String) - why? why not?
      raise ArgumentError, "missing type mapping >#{types.inspect}< for tag >#{name}<"
    end
  end

  type       = guess_type.call( name, attributes )

  new( name, attributes, type )
end

.split(value) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/csvhuman/tag.rb', line 24

def self.split( value )
  value = value.strip
  value = value.downcase
  while value.start_with?('#') do   ## allow one or more hashes
    value = value[1..-1]    ## remove leading #
    value = value.strip   ## strip (optional) leading spaces (again)
  end
  ## pp value
  parts = value.split( SEP_REGEX )

  ## sort attributes a-z
  if parts.size > 2
     [parts[0]] + parts[1..-1].sort
  else
    parts
  end
end

Instance Method Details

#keyObject



132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/csvhuman/tag.rb', line 132

def key
  ## convenience short cut for "standard/default" string key
  ##   cache/pre-built/memoize - why? why not?
  ##  builds:
  ##   population+affected+children+f

  buf = ''
  buf << @name
  if @attributes && @attributes.size > 0
    buf << '+'
    buf << @attributes.join('+')
  end
  buf
end

#to_sObject



147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/csvhuman/tag.rb', line 147

def to_s
  ## cache/pre-built/memoize - why? why not?
  ##
  ##  builds
  ##     #population +affected +children +f

  buf = ''
  buf << '#' + @name
  if @attributes && @attributes.size > 0
    buf << ' +'
    buf << @attributes.join(' +')
  end
  buf
end

#typecast(value) ⇒ Object

todo/check: rename to/use convert or call - why? why not?



126
127
128
129
# File 'lib/csvhuman/tag.rb', line 126

def typecast( value )
  ## note: if conv is nil/null - pass value through as is (1:1); used for Strings (by default)
  @conv ?  @conv.call( value ) : value
end