Class: CheckPlease::Path

Inherits:
Object
  • Object
show all
Includes:
Reification
Defined in:
lib/check_please/path.rb

Overview

TODO: this class is getting a bit large; maybe split out some of the stuff that uses flags?

Constant Summary collapse

SEPARATOR =
"/"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Reification

included

Constructor Details

#initialize(name_or_segments = []) ⇒ Path

Returns a new instance of Path.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/check_please/path.rb', line 17

def initialize(name_or_segments = [])
  case name_or_segments
  when String, Symbol, Numeric, nil
    string = name_or_segments.to_s
    if string =~ %r(//)
      raise InvalidPath, "paths cannot have empty segments"
    end

    names = string.split(SEPARATOR)
    names.shift until names.empty? || names.first =~ /\S/
    segments = PathSegment.reify(names)
  when Array
    segments = PathSegment.reify(name_or_segments)
  else
    raise InvalidPath, "not sure what to do with #{name_or_segments.inspect}"
  end

  @segments = Array(segments)

  @to_s = SEPARATOR + @segments.join(SEPARATOR)
  freeze
rescue InvalidPathSegment => e
  raise InvalidPath, e.message
end

Instance Attribute Details

#segmentsObject (readonly)

Returns the value of attribute segments.



16
17
18
# File 'lib/check_please/path.rb', line 16

def segments
  @segments
end

#to_sObject (readonly)

Returns the value of attribute to_s.



16
17
18
# File 'lib/check_please/path.rb', line 16

def to_s
  @to_s
end

Class Method Details

.rootObject



10
11
12
# File 'lib/check_please/path.rb', line 10

def self.root
  new('/')
end

Instance Method Details

#+(new_basename) ⇒ Object



42
43
44
45
46
# File 'lib/check_please/path.rb', line 42

def +(new_basename)
  new_segments = self.segments.dup
  new_segments << new_basename # don't reify here; it'll get done on Path#initialize
  self.class.new(new_segments)
end

#==(other) ⇒ Object



48
49
50
# File 'lib/check_please/path.rb', line 48

def ==(other)
  self.to_s == other.to_s
end

#ancestorsObject



52
53
54
55
56
57
58
59
60
61
# File 'lib/check_please/path.rb', line 52

def ancestors
  list = []
  p = self
  loop do
    break if p.root?
    p = p.parent
    list.unshift p
  end
  list.reverse
end

#basenameObject



63
64
65
# File 'lib/check_please/path.rb', line 63

def basename
  segments.last.to_s
end

#depthObject



67
68
69
# File 'lib/check_please/path.rb', line 67

def depth
  1 + segments.length
end

#excluded?(flags) ⇒ Boolean

Returns:

  • (Boolean)


71
72
73
74
75
76
77
78
79
# File 'lib/check_please/path.rb', line 71

def excluded?(flags)
  return false if root? # that would just be silly

  return true if too_deep?(flags)
  return true if explicitly_excluded?(flags)
  return true if implicitly_excluded?(flags)

  false
end

#inspectObject



81
82
83
# File 'lib/check_please/path.rb', line 81

def inspect
  "<#{self.class.name} '#{to_s}'>"
end

#key_to_match_by(flags) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
# File 'lib/check_please/path.rb', line 85

def key_to_match_by(flags)
  key_exprs = unpack_key_exprs(flags.match_by_key)
  # NOTE: match on parent because if self.to_s == '/foo', MBK '/foo/:id' should return 'id'
  matches = key_exprs.select { |e| e.parent.match?(self) }

  case matches.length
  when 0 ; nil
  when 1 ; matches.first.segments.last.key
  else   ; raise "More than one match_by_key expression for path '#{self}': #{matches.map(&:to_s).inspect}"
  end
end

#match?(path_or_string) ⇒ Boolean

Returns:

  • (Boolean)


101
102
103
104
105
106
107
108
109
110
111
# File 'lib/check_please/path.rb', line 101

def match?(path_or_string)
  # If the strings are literally equal, we're good..
  return true if self == path_or_string

  # Otherwise, compare segments: do we have the same number, and do they all #match?
  other = reify(path_or_string)
  return false if other.depth != self.depth

  seg_pairs = self.segments.zip(other.segments)
  seg_pairs.all? { |a, b| a.match?(b) }
end

#match_by_value?(flags) ⇒ Boolean

Returns:

  • (Boolean)


97
98
99
# File 'lib/check_please/path.rb', line 97

def match_by_value?(flags)
  flags.match_by_value.any? { |e| e.match?(self) }
end

#parentObject



113
114
115
116
# File 'lib/check_please/path.rb', line 113

def parent
  return nil if root? # TODO: consider the Null Object pattern
  self.class.new(segments[0..-2])
end

#root?Boolean

Returns:

  • (Boolean)


118
119
120
# File 'lib/check_please/path.rb', line 118

def root?
  @segments.empty?
end