Class: String

Inherits:
Object show all
Defined in:
lib/strokedb/core_ext/blank.rb,
lib/strokedb/util/inflect.rb,
lib/strokedb/core_ext/string.rb,
lib/strokedb/sync/diff/string.rb

Overview

extracted and adapted from ActiveRecord (rubyforge.org/projects/activesupport/)

Direct Known Subclasses

StrokeDB::DocumentReferenceValue

Instance Method Summary collapse

Instance Method Details

#/(o) ⇒ Object



43
44
45
# File 'lib/strokedb/core_ext/string.rb', line 43

def /(o)
  File.join(self, o.to_s)
end

#blank?Boolean

Returns:

  • (Boolean)


41
42
43
# File 'lib/strokedb/core_ext/blank.rb', line 41

def blank?
  self !~ /\S/
end

#camel_caseObject Also known as: camelize



9
10
11
# File 'lib/strokedb/core_ext/string.rb', line 9

def camel_case
  split('_').map{|e| e.capitalize}.join
end

#constantizeObject



33
34
35
36
37
38
39
40
41
# File 'lib/strokedb/core_ext/string.rb', line 33

def constantize
  if /^meta:/ =~ self
    return StrokeDB::META_CACHE[Meta.make_uuid_from_fullname(self)]
  end
  unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ self
    raise NameError, "#{self.inspect} is not a valid constant name!"
  end
  Object.module_eval("::#{$1}", __FILE__, __LINE__)
end

#demodulizeObject



24
25
26
# File 'lib/strokedb/core_ext/string.rb', line 24

def demodulize
  gsub(/^.*::/, '')
end

#ends_with?(suffix) ⇒ Boolean

Returns:

  • (Boolean)


4
5
6
7
# File 'lib/strokedb/core_ext/string.rb', line 4

def ends_with?(suffix)
  suffix = suffix.to_s
  self[-suffix.length, suffix.length] == suffix
end

#linesObject



59
60
61
# File 'lib/strokedb/core_ext/string.rb', line 59

def lines
  self.split("\n").size
end

#modulizeObject



28
29
30
31
# File 'lib/strokedb/core_ext/string.rb', line 28

def modulize
  return '' unless include?('::') && self[0,2] != '::'
  self.gsub(/^(.+)::(#{demodulize})$/,'\\1')
end

#pluralObject Also known as: pluralize



213
214
215
# File 'lib/strokedb/util/inflect.rb', line 213

def plural
  English::Inflect.plural(self)
end

#singularObject Also known as: singularize



208
209
210
# File 'lib/strokedb/util/inflect.rb', line 208

def singular
  English::Inflect.singular(self)
end

#snake_caseObject



14
15
16
# File 'lib/strokedb/core_ext/string.rb', line 14

def snake_case
  gsub(/\B[A-Z][^A-Z]/, '_\&').downcase.gsub(' ', '_')
end

#stroke_diff(to) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/strokedb/sync/diff/string.rb', line 3

def stroke_diff(to)
  return super(to) unless to.is_a?(String)
  return nil if self == to
  
  _f = self[0,2]
  _t = to[0,2]
  pfx = "@#"
  # both are refs
  return super(to) if _f == _t && _t == pfx
  # one of items is ref, another is not.
  return super(to) if _f == pfx || _t == pfx
        
  lcs_diff = ::Diff::LCS.diff(self, to)
  patchset = lcs_diff.map do |changes| 
    parts = []
    last_part = changes.inject(nil) do |part, change|
      if part && part[0] == change.action && part[3] == change.position - 1
        part[3] += 1
        part[2] << change.element
        part
      else
        parts << part if part
        # emit
        [change.action, change.position, change.element, change.position]
      end
    end
    parts << last_part if last_part
    parts.empty? ? nil : parts
  end.compact.inject([]) do |patches, ps|
    ps.map do |p|
      patches << if p[0] == '+'
        [PATCH_PLUS,  p[1], p[2]]      # [+  position_in_b  substr]
      else
        [PATCH_MINUS, p[1], p[2].size] # [-  position_in_a  length]
      end
    end
    patches
  end
  #p patchset
  patchset.empty? ? nil : patchset
end

#stroke_merge(patch1, patch2) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/strokedb/sync/diff/string.rb', line 81

def stroke_merge(patch1, patch2)
  # One patch is missing (i.e. no changes)
  unless patch1 && patch2
    return _stroke_automerged(stroke_patch(patch1 || patch2))
  end

  # Patch could be either PATCH_REPLACE or regular string diff.
  # Thus, 4 cases:
  #
  # [replace, replace] -> possible conflict
  # [replace, diff]    -> conflict
  # [diff,    replace] -> conflict
  # [diff,    diff]    -> possible conflict

  # Code is verbose to be fast and clear
  if patch1[0] == PATCH_REPLACE
    if patch2[0] == PATCH_REPLACE # [replace, replace]
      if patch1[1] != patch2[1]
        return _stroke_conflicted(stroke_patch(patch1), stroke_patch(patch2))
      else
        return _stroke_automerged(stroke_patch(patch1))
      end
    else # [replace, diff]
       return _stroke_conflicted(stroke_patch(patch1), stroke_patch(patch2))
    end
  else
    if patch1[0] == PATCH_REPLACE # [diff, replace]
      return _stroke_conflicted(stroke_patch(patch1), stroke_patch(patch2))
    else
      nil # [diff, diff] - see below
    end
  end
	  # TODO: ...
end

#stroke_patch(patch) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/strokedb/sync/diff/string.rb', line 45

def stroke_patch(patch)
  return self unless patch
  return patch[1] if patch[0] == PATCH_REPLACE
  
  # Patch is a list of insertions and deletions.
  # Deletion is indexed relative to base.
  # Insertion is indexed relative to new string.
  res = ""
  ai = bj = 0
  patch.each do |change|
    action, position, element = change
    case action
    when PATCH_MINUS
      d = position - ai
      if d > 0
        res << self[ai, d]
        ai += d
        bj += d
      end
      ai += element # element == length
    when PATCH_PLUS
      d = position - bj
      if d > 0
        res << self[ai, d]
        ai += d
        bj += d
      end
      bj += element.size
      res << element
    end
  end
  d = self.size - ai
  res << self[ai, d] if d > 0
  res
end

#tableizeObject



18
19
20
21
22
# File 'lib/strokedb/core_ext/string.rb', line 18

def tableize
  words = snake_case.split('_')
  words.last.replace words.last.plural
  words.join('_')
end

#underscoreObject



51
52
53
54
55
56
57
# File 'lib/strokedb/core_ext/string.rb', line 51

def underscore
  self.to_s.gsub(/::/, '/').
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    tr("-", "_").
    downcase
end

#unindent!Object



47
48
49
# File 'lib/strokedb/core_ext/string.rb', line 47

def unindent!
  self.gsub!(/^\n/, '').gsub!(/^#{self.match(/^\s*/)[0]}/, '')
end