Module: WebUtils

Extended by:
Rack::Utils
Defined in:
lib/web_utils.rb

Constant Summary collapse

VERSION =
'0.1.5'.freeze
EMPTY_STRING =

Global string constants

''.freeze
IES_STRING =
'ies'.freeze
E_STRING =
'e'.freeze
S_STRING =
's'.freeze
Y_STRING =
'y'.freeze
X_STRING =
'x'.freeze
XES_STRING =
'xes'.freeze
SPACE =
' '.freeze
DASH =
'-'.freeze
UNDERSCORE =
'_'.freeze
AMPERSAND =
'&'.freeze
PERCENT =
'%'.freeze
PIPE =
'|'
DOT =
'.'.freeze
COMMA =
','.freeze
CONST_SEP =
'::'.freeze
ELLIPSIS =
'...'
AND_STRING =
'and'.freeze
SPACE_PERCENT_STRING =
' percent'.freeze
TRUE_STRING =
'true'.freeze
FALSE_STRING =
'false'.freeze
BR_TAG =
'<br>'.freeze
ARG1_SUB =
'\1'.freeze
BLANK_RE =

From then on, constants preceed the methods they are used on.

/\A[[:space:]]*\z/.freeze
PLURAL_RE =
/([b-df-hj-np-tv-z])ys\z/.freeze
PLURAL_SUB =
'\1ies'.freeze
SINGULAR_RE =
/ies\z/.freeze
UPPER_OR_NUM_RE =
/([A-Z]|\d+)/.freeze
DASH_LOWER_OR_NUM_RE =
/\-([a-z0-9])/.freeze
START_UPPER_RE =
/^[A-Z]/.freeze
START_LOWER_RE =
/^[a-z]/.freeze
ACCENTS =
"ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšſŢţŤťŦŧÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž".freeze
WITHOUT_ACCENTS =
"AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSssTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz".freeze
DASHIFY_RE =
/(\-|[^0-9a-zA-Z])+/.freeze
EDGE_DASH_RE =
/(\A-|-\z)/.freeze
ALPHA_NUM_RE =
/[a-zA-Z0-9]+/.freeze
EACH_STUB_ERR_MSG =
'WebUtils.each_stub expects an object which respond to each_with_index.'
TYPECASTABLE =
[:bool, :boolean, :nil, :int, :integer, :float].freeze
INT_RE =
/\A-?\d+\z/.freeze
FLOAT_RE =
/\A-?\d*\.\d+\z/.freeze
ID_CHARS =
(('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a).freeze.map(&:freeze)
ID_SIZE =
16
DEPRECATED_RANDOM_ID_STRING =
'WebUtils::generate_random_id is deprecated. Use standard SecureRandom instead.'.freeze
RN_RE =
/\r?\n/.freeze
/^(\/|[a-z]*:)/.freeze
/\A[a-z]*:?\/\//.freeze
EMAIL_REGEX =
/([^\s]+@[^\s]*[a-zA-Z])/.freeze
/\b((https?:\/\/|ftps?:\/\/|www\.)([A-Za-z0-9\-_=%&@\?\.\/]+))\b/.freeze
TAG_REGEX =
/<[^>]*>/.freeze
NL_RE =
/\n/.freeze
QUERY_SPLITTER =
/[^a-zA-Z0-9\&]+/.freeze
PRICE_ERR_MSG =
'The price needs to be the price in cents/pence as an integer'.freeze
PRICE_FMT =
'%.2f'.freeze
NO_CENTS_RE =
/\.00/.freeze
THOUSANDS_RE =
/(\d{3})(?=\d)/.freeze
THOUSANDS_SUB =
'\1,'.freeze
PRICE_PARSE_ERR_MSG =
'The price needs to be parsed from a String'.freeze
SWITCH_DOT_COMMA_TR =
['.,'.freeze, ',.'.freeze].freeze
COMMA_BASED_PRICE_RE =
/(\.\d\d\d|,\d\d?)\z/.freeze
NON_PRICE_CHARS_RE =
/[^\d\.\-,]/.freeze
DEFAULT_BRAND =
self.name
START_DOT_SLASH_RE =
/\A\.\//.freeze
BOT_REGEX =
/bot|crawl|slurp|spider/i.freeze

Class Method Summary collapse

Class Method Details

.automatic_html(s, br = BR_TAG) ⇒ Object



267
268
269
270
271
272
273
274
275
276
277
# File 'lib/web_utils.rb', line 267

def automatic_html s, br=BR_TAG
  replaced = s.to_s.
  gsub(LINK_REGEX) do |str|
    url = complete_link $1
    "<a href='#{url}' target='_blank'>#{$1}</a>"
  end.
  gsub(EMAIL_REGEX) do |str|
    "<a href='mailto:#{$1.downcase}'>#{$1}</a>"
  end
  nl2br(replaced,br)
end

.automatic_typecast(str, casted = TYPECASTABLE) ⇒ Object



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

def automatic_typecast str, casted=TYPECASTABLE 
  return str unless str.is_a?(String)
  casted = casted.map do |sym|
    case sym
    when :int
      :integer
    when :bool
      :boolean
    else
      sym
    end
  end
  if casted.include?(:boolean) and str == TRUE_STRING
    true
  elsif casted.include?(:boolean) and str == FALSE_STRING
    false
  elsif casted.include?(:nil) and str == EMPTY_STRING
    nil
  elsif casted.include?(:integer) and str =~ INT_RE
    str.to_i
  elsif casted.include?(:float) and str =~ FLOAT_RE
    str.to_f
  else
    str
  end
end

.being_crawled?(request) ⇒ Boolean

Returns:

  • (Boolean)


361
362
363
# File 'lib/web_utils.rb', line 361

def being_crawled? request
  request.user_agent =~ BOT_REGEX
end

.blank?(s) ⇒ Boolean

Returns:

  • (Boolean)


47
48
49
50
51
52
53
54
55
# File 'lib/web_utils.rb', line 47

def blank? s
  return true if s.nil?
  # Not much difference with strip on benchmarks
  # return (s.empty? or BLANK_RE.match?(s)) if s.is_a?(String)
  return (s.strip.empty?) if s.is_a?(String)
  return s.empty? if s.respond_to?(:empty?)
  return true if s==false
  false
end

.branded_filename(path, brand = DEFAULT_BRAND) ⇒ Object



340
341
342
343
# File 'lib/web_utils.rb', line 340

def branded_filename path, brand=DEFAULT_BRAND
  "#{File.dirname(path)}/#{brand}-#{File.basename(path)}"
    .sub(START_DOT_SLASH_RE, EMPTY_STRING)
end


248
249
250
251
252
253
254
# File 'lib/web_utils.rb', line 248

def complete_link link
  if blank?(link) or link =~ COMPLETE_LINK_RE
    link
  else
    "//#{link}"
  end
end

.dasherize_class_name(s) ⇒ Object



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

def dasherize_class_name s
  s.gsub(UPPER_OR_NUM_RE) {|str| "-#{str.downcase}" }[1..-1].gsub(CONST_SEP, DASH)
end

.deep_copy(original) ⇒ Object



141
142
143
# File 'lib/web_utils.rb', line 141

def deep_copy original
  Marshal.load(Marshal.dump(original))
end

.display_price(int) ⇒ Object



307
308
309
310
311
312
313
314
315
316
# File 'lib/web_utils.rb', line 307

def display_price int
  unless int.is_a?(Integer)
    raise(TypeError, PRICE_ERR_MSG)
  end
  (PRICE_FMT % (int/100.0))
    .sub(NO_CENTS_RE, EMPTY_STRING)
    .reverse
    .gsub(THOUSANDS_RE, THOUSANDS_SUB)
    .reverse
end

.each_stub(obj, &block) ⇒ Object

Raises:

  • (TypeError)


182
183
184
185
186
187
188
189
190
191
192
# File 'lib/web_utils.rb', line 182

def each_stub obj, &block 
  raise TypeError, EACH_STUB_ERR_MSG unless obj.respond_to?(:each_with_index)
  obj.each_with_index do |(k,v),i|
    value = v || k
    if value.is_a?(Hash) || value.is_a?(Array)
      each_stub(value,&block)
    else
      block.call(obj, (v.nil? ? i : k), value)
    end
  end
end

.ensure_key(h, k, v) ⇒ Object



151
152
153
# File 'lib/web_utils.rb', line 151

def ensure_key h, k, v
  {k=>v}.merge h
end

.ensure_key!(h, k, v) ⇒ Object



146
147
148
# File 'lib/web_utils.rb', line 146

def ensure_key! h, k, v
  h.fetch(k) {|k| h.store(k, v) }
end

.external_link?(link) ⇒ Boolean

Returns:

  • (Boolean)


259
260
261
# File 'lib/web_utils.rb', line 259

def external_link? link
  !!(link =~ EXTERNAL_LINK_RE)
end

.filename_variation(path, variation, ext) ⇒ Object



346
347
348
349
# File 'lib/web_utils.rb', line 346

def filename_variation path, variation, ext
  old_ext = File.extname(path) 
  path.sub(/#{Regexp.escape old_ext}$/, ".#{variation}.#{ext}")
end

.generate_random_id(size = ID_SIZE) ⇒ Object



231
232
233
234
235
236
# File 'lib/web_utils.rb', line 231

def generate_random_id size=ID_SIZE
  warn DEPRECATED_RANDOM_ID_STRING
  id = String.new
  size.times{id << ID_CHARS[rand(ID_CHARS.size)]} 
  id
end

.get_value(raw, context = Kernel) ⇒ Object



130
131
132
133
134
135
136
137
138
# File 'lib/web_utils.rb', line 130

def get_value raw, context=Kernel
  if raw.is_a? Proc
    raw.call
  elsif raw.is_a? Symbol
    context.__send__ raw
  else
    raw
  end
end


376
377
378
# File 'lib/web_utils.rb', line 376

def google_maps_link address
  "https://www.google.com/maps/search/?api=1&query=#{u address}"
end


118
119
120
121
122
123
124
125
126
127
# File 'lib/web_utils.rb', line 118

def guess_related_class_name context, clue
  context.respond_to?(:name) ? context.name : context.to_s
  clue = clue.to_s
  return clue if clue =~ START_UPPER_RE
  if clue =~ START_LOWER_RE
    clue = undasherize_class_name singularize(clue).gsub(UNDERSCORE, DASH)
    clue = "::#{clue}"
  end
  "#{context}#{clue}"
end

.h(text) ⇒ Object



366
367
368
# File 'lib/web_utils.rb', line 366

def h text
  escape_html text
end

.initial_request?(request) ⇒ Boolean

Returns:

  • (Boolean)


352
353
354
355
356
# File 'lib/web_utils.rb', line 352

def initial_request? request
  URI.parse(request.referer).host!=request.host
rescue URI::InvalidURIError
  return true
end

.label_for_field(field_name) ⇒ Object



175
176
177
# File 'lib/web_utils.rb', line 175

def label_for_field field_name
  field_name.to_s.scan(ALPHA_NUM_RE).map(&:capitalize).join(SPACE)
end

.nl2br(s, br = BR_TAG) ⇒ Object



241
242
243
# File 'lib/web_utils.rb', line 241

def nl2br s, br=BR_TAG
  s.to_s.gsub(RN_RE, br)
end

.parse_price(string) ⇒ Object



324
325
326
327
328
329
330
331
332
333
334
# File 'lib/web_utils.rb', line 324

def parse_price string
  unless string.is_a?(String)
    raise(TypeError, PRICE_PARSE_ERR_MSG) 
  end
  string = string.gsub(NON_PRICE_CHARS_RE, EMPTY_STRING)
  if string[COMMA_BASED_PRICE_RE]
    # comma-based price 
    string = string.tr(*SWITCH_DOT_COMMA_TR)
  end
  (PRICE_FMT % string.gsub(COMMA, EMPTY_STRING)).gsub(DOT, EMPTY_STRING).to_i
end

.pluralize(s) ⇒ Object



61
62
63
64
65
66
# File 'lib/web_utils.rb', line 61

def pluralize s
  s = s.dup
  s<<E_STRING if s[-1,1]==X_STRING
  s<<S_STRING
  s.sub PLURAL_RE, PLURAL_SUB
end

.regex_for_query(query, exhaustive = true) ⇒ Object



293
294
295
296
297
298
# File 'lib/web_utils.rb', line 293

def regex_for_query query, exhaustive=true
  atoms = query.split(QUERY_SPLITTER)
  atom_patterns = atoms.map{|a| "(?=.*\\b#{a})" }
  sep = exhaustive ? EMPTY_STRING : PIPE
  /#{atom_patterns.join(sep)}/i.freeze
end

.resolve_class_name(s, context = Kernel) ⇒ Object

Raises:

  • (NameError)


98
99
100
101
102
103
104
105
106
107
# File 'lib/web_utils.rb', line 98

def resolve_class_name s, context=Kernel
  current, *payload = s.to_s.split(CONST_SEP)
  raise(NameError) if current.nil?
  const = context.const_get(current)
  if payload.empty?
    const
  else
    resolve_class_name(payload.join(CONST_SEP),const)
  end
end

.resolve_dasherized_class_name(s) ⇒ Object



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

def resolve_dasherized_class_name s
  resolve_class_name(undasherize_class_name(s.to_s)) 
end

.singularize(s) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
# File 'lib/web_utils.rb', line 71

def singularize s
  if s.end_with? XES_STRING
    s[0..-3]
  elsif s.end_with? IES_STRING
    s.sub(SINGULAR_RE, Y_STRING)
  elsif s.end_with? S_STRING
    s[0..-2]
  else
    s.dup
  end
end

.slugify(s, force_lower = true) ⇒ Object



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

def slugify s, force_lower=true
  s = s.to_s
    .tr(ACCENTS, WITHOUT_ACCENTS)
    .gsub(AMPERSAND, AND_STRING)
    .gsub(PERCENT, SPACE_PERCENT_STRING)
    .gsub(DASHIFY_RE, DASH)
    .gsub(EDGE_DASH_RE, EMPTY_STRING)
  s = s.downcase if force_lower
  escape(s)
end

.truncate(s, c = 320, ellipsis = ELLIPSIS) ⇒ Object



283
284
285
286
287
288
# File 'lib/web_utils.rb', line 283

def truncate s, c=320, ellipsis=ELLIPSIS
  s.to_s
    .gsub(TAG_REGEX, EMPTY_STRING)
    .gsub(NL_RE, SPACE)
    .sub(/^(.{#{c}}\w*).*$/m, ARG1_SUB+ellipsis)
end

.u(text) ⇒ Object



371
372
373
# File 'lib/web_utils.rb', line 371

def u text
  escape text
end

.undasherize_class_name(s) ⇒ Object



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

def undasherize_class_name s
  s.capitalize.gsub(DASH_LOWER_OR_NUM_RE) {|str| $1.upcase }.gsub(DASH, CONST_SEP)
end