Class: SmartName

Inherits:
Object show all
Includes:
ActiveSupport::Configurable
Defined in:
lib/smart_name.rb

Constant Summary collapse

RUBY19 =
RUBY_VERSION =~ /^1\.9/
WORD_RE =
RUBY19 ? '\p{Word}' : '\w'
JOINT =

Wagny defaults:

'+'
@@name2nameobject =
{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(str) ⇒ SmartName

Returns a new instance of SmartName.



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/smart_name.rb', line 61

def initialize str
  @s = str.to_s.strip
  @s = @s.encode('UTF-8') if RUBY19
  @key = if @s.index(SmartName.joint)
      @parts = @s.split(/\s*#{Regexp.escape(SmartName.joint)}\s*/)
      @parts << '' if @s[-1] == SmartName.joint
      @simple = false
      @parts.map { |p| p.to_name.key } * SmartName.joint
    else
      @parts = [str]
      @simple = true
      str.empty? ? '' : simple_key
    end
  @@name2nameobject[str] = self
end

Instance Attribute Details

#keyObject (readonly)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~ INSTANCE ~~~~~~~~~~~~~~~~~~~~~~~~~



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

def key
  @key
end

#partsObject (readonly)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~ INSTANCE ~~~~~~~~~~~~~~~~~~~~~~~~~



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

def parts
  @parts
end

#sObject (readonly) Also known as: to_s

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~ INSTANCE ~~~~~~~~~~~~~~~~~~~~~~~~~



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

def s
  @s
end

#simpleObject (readonly) Also known as: simple?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~ INSTANCE ~~~~~~~~~~~~~~~~~~~~~~~~~



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

def simple
  @simple
end

Class Method Details

.banned_reObject



49
50
51
# File 'lib/smart_name.rb', line 49

def banned_re
  %r{#{ (['['] + SmartName.banned_array << SmartName.joint )*'\\' + ']' }}
end

.new(obj) ⇒ Object



32
33
34
35
36
37
38
39
40
# File 'lib/smart_name.rb', line 32

def new obj
  return obj if SmartName===obj
  str = Array===obj ? obj*SmartName.joint : obj.to_s
  if known_name = @@name2nameobject[str]
    known_name
  else
    super str.strip
  end
end

.substitute!(str, hash) ⇒ Object



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

def self.substitute! str, hash
  hash.keys.each do |var|
    str.gsub!(SmartName.var_re) { |x| (v=hash[var.to_sym]).nil? ? x : v }
  end
  str
end

.unescape(uri) ⇒ Object



42
43
44
45
46
47
# File 'lib/smart_name.rb', line 42

def unescape uri
  # can't instantiate because key doesn't resolve correctly in unescaped form
  # issue is peculiar to plus sign (+), which are interpreted as a space.
  # if we could make that not happen, we could avoid this (and handle spaces in urls)
  uri.gsub(' ','+').gsub '_',' '
end

Instance Method Details

#==(obj) ⇒ Object



90
91
92
93
94
95
96
97
# File 'lib/smart_name.rb', line 90

def == obj
  object_key = case
    when obj.respond_to?(:key)      ; obj.key
    when obj.respond_to?(:to_name) ; obj.to_name.key
    else                               ; obj.to_s
    end
  object_key == key
end

#blank?Boolean Also known as: empty?

Returns:

  • (Boolean)


83
# File 'lib/smart_name.rb', line 83

def blank?()     s.blank?     end

#decodedObject



114
115
116
# File 'lib/smart_name.rb', line 114

def decoded
  @decoded ||= (s.index('&') ?  HTMLEntities.new.decode(s) : s)
end

#inspectObject



86
87
88
# File 'lib/smart_name.rb', line 86

def inspect
  "<SmartName key=#{key}[#{self}]>"
end

#junction?Boolean

Returns:

  • (Boolean)


132
# File 'lib/smart_name.rb', line 132

def junction?()  not simple?                                             end

#leftObject



134
# File 'lib/smart_name.rb', line 134

def left()       @left  ||= simple? ? nil : parts[0..-2]*SmartName.joint end

#left_nameObject



137
# File 'lib/smart_name.rb', line 137

def left_name()  @left_name  ||= left  && SmartName.new( left  )         end

#lengthObject



81
# File 'lib/smart_name.rb', line 81

def length()     parts.length end

#nth_left(n) ⇒ Object



233
234
235
236
# File 'lib/smart_name.rb', line 233

def nth_left n
  # 1 = left; 2= left of left; 3 = left of left of left....
  ( n >= length ? parts[0] : parts[0..-n-1] ).to_name
end

#piecesObject



148
149
150
151
152
153
154
# File 'lib/smart_name.rb', line 148

def pieces
  @pieces ||= if simple?
    [ self ]
  else
    trunk_name.pieces + [ tag_name ]
  end
end

#post_cgiObject



124
125
126
127
# File 'lib/smart_name.rb', line 124

def post_cgi
  #hmm.  this could resolve to the key of some other card.  move to class method?
  @post_cgi ||= s.gsub '~plus~', SmartName.joint
end

#pre_cgiObject



118
119
120
121
122
# File 'lib/smart_name.rb', line 118

def pre_cgi
  #why is this necessary?? doesn't real CGI escaping handle this??
  # hmmm.  is this to prevent absolutizing
  @pre_cgi ||= parts.join '~plus~'
end

#replace_part(oldpart, newpart) ⇒ Object

~~~~~~~~~~~~~~~~~~~~ MISC ~~~~~~~~~~~~~~~~~~~~



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/smart_name.rb', line 241

def replace_part oldpart, newpart
  oldpart = oldpart.to_name
  newpart = newpart.to_name
  if oldpart.simple?
    if simple?
      self == oldpart ? newpart : self
    else
      parts.map do |p|
        oldpart == p ? newpart.to_s : p
      end.to_name
    end
  elsif simple?
    self
  else
    if oldpart == parts[0, oldpart.length]
      if self.length == oldpart.length
        newpart
      else
        (newpart.parts+(parts[oldpart.length,].lines.to_a)).to_name
      end
    else
      self
    end
  end
end

#rightObject



135
# File 'lib/smart_name.rb', line 135

def right()      @right ||= simple? ? nil : parts[-1]                    end

#right_nameObject



138
# File 'lib/smart_name.rb', line 138

def right_name() @right_name ||= right && SmartName.new( right )         end

#rstar?Boolean

Returns:

  • (Boolean)


160
# File 'lib/smart_name.rb', line 160

def rstar?()        right     and '*' == right[0]           end

#safe_keyObject



110
111
112
# File 'lib/smart_name.rb', line 110

def safe_key
  @safe_key ||= key.gsub('*','X').gsub SmartName.joint, '-'
end

#simple_keyObject

~~~~~~~~~~~~~~~~~~~ VARIANTS ~~~~~~~~~~~~~~~~~~~



102
103
104
# File 'lib/smart_name.rb', line 102

def simple_key
  decoded.underscore.gsub(/[^#{WORD_RE}\*]+/,'_').split(/_+/).reject(&:empty?).map(&(SmartName.uninflect))*'_'
end

#sizeObject



82
# File 'lib/smart_name.rb', line 82

def size()       to_s.size    end

#star?Boolean

~~~~~~~~~~~~~~~~~~~ TRAITS / STARS ~~~~~~~~~~~~~~~~~~~

Returns:

  • (Boolean)


159
# File 'lib/smart_name.rb', line 159

def star?()         simple?   and '*' == s[0]               end

#tagObject



143
# File 'lib/smart_name.rb', line 143

def tag()        @tag   ||= simple? ? s : right                          end

#tag_nameObject



146
# File 'lib/smart_name.rb', line 146

def tag_name()   @tag_name   ||= simple? ? self : right_name             end

#to_absolute(context, args = {}) ⇒ Object



202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/smart_name.rb', line 202

def to_absolute context, args={}
  context = context.to_name
  parts.map do |part|
    new_part = case part
      when /^_user$/i;            (user=Session.user_card) ? user.name : part
      when /^_main$/i;            SmartName.params[:main_name]
      when /^(_self|_whole|_)$/i; context.s
      when /^_left$/i;            context.trunk #note - inconsistent use of left v. trunk
      when /^_right$/i;           context.tag
      when /^_(\d+)$/i
        pos = $~[1].to_i
        pos = context.length if pos > context.length
        context.parts[pos-1]
      when /^_(L*)(R?)$/i
        l_s, r_s = $~[1].size, !$~[2].empty?
        l_part = context.nth_left l_s
        r_s ? l_part.tag : l_part.s
      when /^_/
        custom = args[:params] ? args[:params][part] : nil
        custom ? CGI.escapeHTML(custom) : part #why are we escaping HTML here?
      else
        part
      end.to_s.strip
    new_part.empty? ? context.to_s : new_part
  end * SmartName.joint
end

#to_absolute_name(*args) ⇒ Object



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

def to_absolute_name *args
  SmartName.new to_absolute(*args)
end

#to_nameObject



80
# File 'lib/smart_name.rb', line 80

def to_name()    self         end

#to_show(context, args = {}) ⇒ Object

~~~~~~~~~~~~~~~~~~~~ SHOW / ABSOLUTE ~~~~~~~~~~~~~~~~~~~~



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/smart_name.rb', line 185

def to_show context, args={}
#      ignore = [ args[:ignore], context.to_name.parts ].flatten.compact.map &:to_name
  ignore = [ args[:ignore] ].flatten.map &:to_name
  fullname = parts.to_name.to_absolute_name context, args

  show_parts = fullname.parts.map do |part|
    reject = ( part.empty? or part =~ /^_/ or ignore.member? part.to_name )
    reject ? nil : part
  end

  initial_blank = show_parts[0].nil?
  show_name = show_parts.compact.to_name.s

  initial_blank ? SmartName.joint + show_name : show_name
end

#trait(tag_code) ⇒ Object



177
178
179
# File 'lib/smart_name.rb', line 177

def trait tag_code
  trait_name( tag_code ).s
end

#trait_name(tag_code) ⇒ Object



172
173
174
175
# File 'lib/smart_name.rb', line 172

def trait_name tag_code
  codecard = SmartName.codes[ tag_code ] and codecard = SmartName.lookup[ codecard ] and
    [ self, codecard.send(SmartName.name_attribute) ].to_name
end

#trait_name?(*traitlist) ⇒ Boolean

Returns:

  • (Boolean)


162
163
164
165
166
167
168
169
170
# File 'lib/smart_name.rb', line 162

def trait_name? *traitlist
  junction? && begin
    right_key = right_name.key
    !!traitlist.find do |codename|
      codecard = SmartName.codes[ codename ] and codecard = SmartName.lookup[ codecard ] and
        codecard.send(SmartName.name_attribute).key == right_key
    end
  end
end

#trunkObject

Note that all names have a trunk and tag, but only junctions have left and right



142
# File 'lib/smart_name.rb', line 142

def trunk()      @trunk ||= simple? ? s : left                           end

#trunk_nameObject



145
# File 'lib/smart_name.rb', line 145

def trunk_name() @trunk_name ||= simple? ? self : left_name              end

#url_keyObject



106
107
108
# File 'lib/smart_name.rb', line 106

def url_key
  @url_key ||= decoded.gsub(/[^\*#{WORD_RE}\s\+]/,' ').strip.gsub(/[\s\_]+/,'_')
end

#valid?Boolean

Returns:

  • (Boolean)


77
78
79
# File 'lib/smart_name.rb', line 77

def valid?()
  not parts.find { |pt| pt.match SmartName.banned_re }
end