cardname 0.15.0 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '09f8f18762c861c7f86ba80f9b3f880c4eed7b44b469d01db78433fbe50db63f'
4
- data.tar.gz: 32b9b34f0b2bf444ce301876703f7cb0a45822e64cbf7142731828b09d282f98
3
+ metadata.gz: 31233d7951221846f2898d40721963a9fe71614d08e5c395faae832546066b61
4
+ data.tar.gz: b3bbaf9b81dac6212c3434604204d700eb99dfa684dcb13bd6503892ac6219a9
5
5
  SHA512:
6
- metadata.gz: e9dbdb672ab542bdbf618cd72ed6819f72d469a0a1a0f0ba1d1799977dd66ef21b46e0034b9846948585696ecdca7abbe94811ad18cd9e9d69fe106840c6e6ea
7
- data.tar.gz: 840efe97c1f02b061445c9ed8b82b01f04be25c95fe3cdd90da46d3acf5d111be9090ba24d8cc499808d17f762c87a5c3100ee4440e4bb94e7f2f3fb7f094184
6
+ metadata.gz: 1c30f90fb867e3fb83279c46b55976fdcd96301b744517a56e9aee4427e3562e45ff3fda00b28c416913312e9a1b02008299b6958aaad09bcdc5fa1dcea2e8ee
7
+ data.tar.gz: 8482990c4776c0fa2529309d5116fefd28f03a3f32561335c09c3581b8dac5355240c72507a788903cec46eb4884285d790696abd3775136fac54c863acd316c
@@ -0,0 +1,60 @@
1
+ class Cardname
2
+ # methods for the Cardname class.
3
+ module ClassMethods
4
+ # #new skips installation and returns a cached Cardname object when possible
5
+ # @return [Cardname]
6
+ def new obj
7
+ return obj if obj.is_a? self.class
8
+
9
+ str = stringify(obj)
10
+ cache[str] ||= super(str)
11
+ end
12
+
13
+ # Cardname cache. keys are strings, values are corresponding Cardname objects
14
+ # Note that unlike most decko/card caches, the cardname cache is process-specific
15
+ # and should not need to be reset even with data changes, because Cardname objects
16
+ # are not data-aware.
17
+ #
18
+ # @return [Hash]
19
+ def cache
20
+ @cache ||= {}
21
+ end
22
+
23
+ # reset Cardname cache
24
+ # @see #cache
25
+ # @return [Hash]
26
+ def reset
27
+ @cache = {}
28
+ end
29
+
30
+ # true if there are no banned characters
31
+ # @return [Boolean]
32
+ def nothing_banned?
33
+ return @nothing_banned unless @nothing_banned.nil?
34
+
35
+ @nothing_banned = banned_array.empty?
36
+ end
37
+
38
+ # regular expression for detecting banned characters
39
+ # @return [Regexp]
40
+ def banned_re
41
+ @banned_re ||= /[#{Regexp.escape((banned_array + [joint])).join}]/
42
+ end
43
+
44
+ # split string on joint into parts
45
+ # @return [Array]
46
+ def split_parts str
47
+ str.split(/\s*#{JOINT_RE}\s*/, -1)
48
+ end
49
+
50
+ private
51
+
52
+ def stringify obj
53
+ if obj.is_a?(Array)
54
+ obj.map(&:to_s) * joint
55
+ else
56
+ obj.to_s
57
+ end
58
+ end
59
+ end
60
+ end
@@ -1,8 +1,9 @@
1
1
  class Cardname
2
+ # contextual (or relative) names are names that vary by context
2
3
  module Contextual
3
4
  RELATIVE_REGEXP = /\b_(left|right|whole|self|user|main|\d+|L*R?)\b/
4
5
 
5
- # @return true if name is left or right of context
6
+ # @return [Boolean] true if name is left or right of context
6
7
  def child_of? context
7
8
  return false unless compound?
8
9
 
@@ -10,22 +11,31 @@ class Cardname
10
11
  absolute_name(context).parent_keys.include? context_key
11
12
  end
12
13
 
14
+ # @return [Boolean]
13
15
  def relative?
14
16
  starts_with_joint? || (s =~ RELATIVE_REGEXP).present?
15
17
  end
16
18
 
19
+ # starts with joint, no other contextual element
20
+ # @return [Boolean]
17
21
  def simple_relative?
18
22
  starts_with_joint? && (s =~ RELATIVE_REGEXP).nil?
19
23
  end
20
24
 
25
+ # not relative
26
+ # @return [Boolean]
21
27
  def absolute?
22
28
  !relative?
23
29
  end
24
30
 
31
+ # contextual elements removed
32
+ # @return [String]
25
33
  def stripped
26
34
  s.gsub RELATIVE_REGEXP, ""
27
35
  end
28
36
 
37
+ # +X
38
+ # @return [Boolean]
29
39
  def starts_with_joint?
30
40
  compound? && parts.first.empty?
31
41
  end
@@ -44,22 +54,46 @@ class Cardname
44
54
  key == compressed.absolute_name(from).key ? compressed : self
45
55
  end
46
56
 
47
- def remove_context *from
48
- return false unless from.compact.present?
57
+ # @return [String]
58
+ def absolute context
59
+ context = (context || "").to_name
60
+ new_parts = absolutize_contextual_parts context
61
+ return "" if new_parts.empty?
49
62
 
50
- remaining = parts_excluding(*from)
51
- return false if remaining.compact.empty? || # all name parts in context
52
- remaining == parts # no name parts in context
63
+ absolutize_extremes new_parts, context.s
64
+ new_parts.join self.class.joint
65
+ end
53
66
 
54
- remaining
67
+ # @return [Cardname]
68
+ def absolute_name *args
69
+ absolute(*args).to_name
70
+ end
71
+
72
+ # 1 = left; 2= left of left; 3 = left of left of left....
73
+ # @return [Cardname]
74
+ def nth_left_name n
75
+ (n >= length ? parts[0] : parts[0..-n - 1]).to_name
55
76
  end
56
77
 
78
+ private
79
+
57
80
  def parts_excluding *string
58
81
  exclude_name = string.to_name
59
82
  exclude_keys = exclude_name ? exclude_name.part_names.map(&:key) : []
60
83
  parts_minus exclude_keys
61
84
  end
62
85
 
86
+ def remove_context *from
87
+ return false unless from.compact.present?
88
+
89
+ remaining = parts_excluding(*from)
90
+ return false if remaining.compact.empty? || # all name parts in context
91
+ remaining == parts # no name parts in context
92
+
93
+ remaining
94
+ end
95
+
96
+ # @return [Array <String>]
63
97
  def parts_minus keys_to_ignore
64
98
  parts.map do |part|
65
99
  next if part.empty?
@@ -70,26 +104,6 @@ class Cardname
70
104
  end
71
105
  end
72
106
 
73
- def absolute context
74
- context = (context || "").to_name
75
- new_parts = absolutize_contextual_parts context
76
- return "" if new_parts.empty?
77
-
78
- absolutize_extremes new_parts, context.s
79
- new_parts.join self.class.joint
80
- end
81
-
82
- def absolute_name *args
83
- absolute(*args).to_name
84
- end
85
-
86
- def nth_left n
87
- # 1 = left; 2= left of left; 3 = left of left of left....
88
- (n >= length ? parts[0] : parts[0..-n - 1]).to_name
89
- end
90
-
91
- private
92
-
93
107
  def absolutize_contextual_parts context
94
108
  parts.map do |part|
95
109
  case part
@@ -118,7 +132,7 @@ class Cardname
118
132
  def partmap_part match, context
119
133
  l_s = match[1].size
120
134
  r_s = !match[2].empty?
121
- l_part = context.nth_left l_s
135
+ l_part = context.nth_left_name l_s
122
136
  r_s ? l_part.tag : l_part.s
123
137
  end
124
138
 
@@ -1,52 +1,47 @@
1
1
  class Cardname
2
+ # methods for altering name
2
3
  module Manipulate
3
- # swap a subname
4
- # keys are used for comparison
5
- def swap old, new
6
- old_name = old.to_name
7
- new_name = new.to_name
8
- return self if old_name.num_parts > num_parts
9
- return swap_part(old_name, new_name) if old_name.simple?
10
- return self unless include? old_name
11
-
12
- swap_all_subsequences(old_name, new_name).to_name
4
+ # alter cardname based on card index
5
+ # @return [Cardname]
6
+ def []= index, val
7
+ p = parts
8
+ p[index] = val
9
+ replace self.class.new(p)
13
10
  end
14
11
 
15
- def swap_part oldpart, newpart
16
- ensure_simpleness oldpart, "Use 'swap' to swap junctions"
17
-
18
- oldpart = oldpart.to_name
19
- newpart = newpart.to_name
20
-
21
- parts.map do |p|
22
- oldpart == p ? newpart : p
23
- end.to_name
12
+ # append part to cardname
13
+ # @return [Cardname]
14
+ def << val
15
+ replace self.class.new(parts << val)
24
16
  end
25
17
 
26
- def swap_piece oldpiece, newpiece
27
- oldpiece = oldpiece.to_name
28
- newpiece = newpiece.to_name
29
-
30
- return swap_part oldpiece, newpiece if oldpiece.simple?
31
- return self unless starts_with_parts?(oldpiece)
32
- return newpiece if oldpiece.num_parts == num_parts
33
-
34
- self.class.new [newpiece, self[oldpiece.num_parts..-1]].flatten
35
- end
36
-
37
- def num_parts
38
- parts.length
39
- end
18
+ # swap one name for another (keys are used for comparison)
19
+ # @return [Cardname]
20
+ def swap old, new
21
+ old_name = old.to_name
22
+ new_name = new.to_name
40
23
 
41
- def [] *args
42
- self.class.new part_names[*args]
24
+ if old_name.num_parts > num_parts
25
+ self
26
+ elsif old_name.simple?
27
+ swap_part old_name, new_name
28
+ elsif include? old_name
29
+ swap_all_subsequences(old_name, new_name).to_name
30
+ else
31
+ self
32
+ end
43
33
  end
44
34
 
35
+ # add a joint to name's beginning (if it doesn't already start with one)
36
+ # @return [String]
45
37
  def prepend_joint
46
38
  joint = self.class.joint
47
39
  self =~ /^#{Regexp.escape joint}/ ? self : (joint + self)
48
40
  end
41
+ alias_method :to_field, :prepend_joint
49
42
 
43
+ # substitute name, where it appears in str, with new string
44
+ # @return [String]
50
45
  def sub_in str, with:
51
46
  %i[capitalize downcase].product(%i[pluralize singularize])
52
47
  .inject(str) do |s, (m1, m2)|
@@ -54,10 +49,12 @@ class Cardname
54
49
  end
55
50
  end
56
51
 
57
- alias_method :to_field, :prepend_joint
58
-
59
52
  private
60
53
 
54
+ def swap_part oldpart, newpart
55
+ parts.map { |p| oldpart == p ? newpart : p }.to_name
56
+ end
57
+
61
58
  def swap_all_subsequences oldseq, newseq
62
59
  res = []
63
60
  i = 0
@@ -75,11 +72,5 @@ class Cardname
75
72
  res += parts[i..-1] if i < num_parts
76
73
  res
77
74
  end
78
-
79
- def ensure_simpleness part, msg=nil
80
- return if part.to_name.simple?
81
-
82
- raise StandardError, "'#{part}' has to be simple. #{msg}"
83
- end
84
75
  end
85
76
  end
@@ -1,82 +1,156 @@
1
1
  class Cardname
2
2
  # naming conventions:
3
- # methods that end with _name return name objects
4
- # the same methods without _name return strings
3
+ #
4
+ # - methods that end with _name return {Cardname} objects
5
+ # - methods that end with _key return {Cardname#key case/space keys}
6
+ # - methods without _name or _key return Strings
7
+ #
5
8
  module Parts
6
- # PARTS
7
- def part_names
8
- @part_names ||= generate_part_names
9
+ # the part of a compound name to the left of the rightmost joint.
10
+ # @example
11
+ # "A".cardname.left -> nil
12
+ # "A+B".cardname.left -> "A"
13
+ # "A+B+C".cardname.left -> "A+B"
14
+ # "A+B+C+D".cardname.left -> "A+B+C"
15
+ # @see #trunk
16
+ # @return [String]
17
+ def left
18
+ left_name&.s
19
+ end
20
+
21
+ # @see #left
22
+ # @return [String]
23
+ def left_key
24
+ left_name&.key
25
+ end
26
+
27
+ # @see #left
28
+ # @return [Cardname]
29
+ def left_name
30
+ simple? ? nil : self.class.new(part_names[0..-2])
31
+ end
32
+
33
+ # for compound cards, an array of the left and right
34
+ # @example
35
+ # "A".cardname.parents -> []
36
+ # "A+B".cardname.parents -> ["A", "B"]
37
+ # "A+B+C".cardname.parents -> ["A+B", "C"]
38
+ # "A+B+C+D".cardname.parents -> ["A+B+C", "D"]
39
+ # @see #parts
40
+ # @return [Array <String>]
41
+ def parents
42
+ parent_names.map(&:s)
9
43
  end
10
44
 
45
+ # @see #parents
46
+ # @return [Array <String>]
47
+ def parent_keys
48
+ parent_names.map(&:key)
49
+ end
50
+
51
+ # @see #parents
52
+ # @return [Array <Cardname>]
53
+ def parent_names
54
+ simple? ? [] : [left_name, right_name]
55
+ end
56
+
57
+ # for compound cards, each joint separated part
58
+ # @example
59
+ # "A".cardname.parts -> []
60
+ # "A+B".cardname.parts -> ["A", "B"]
61
+ # "A+B+C".cardname.parts -> ["A", "B", "C"]
62
+ # "A+B+C+D".cardname.parts -> ["A", "B", C", "D"]
63
+ # @see #parents
64
+ # @return [Array <String>]
11
65
  def parts
12
66
  part_names.map(&:s)
13
67
  end
14
68
  alias_method :to_a, :parts
15
69
 
70
+ # @see #parts
71
+ # @return [Array <String>]
16
72
  def part_keys
17
73
  part_names.map(&:key)
18
74
  end
19
75
 
20
- def trunk_name
21
- simple? ? self : left_name
76
+ # @see #parts
77
+ # @return [Array <Cardname>]
78
+ def part_names
79
+ @part_names ||= generate_part_names
22
80
  end
23
81
 
82
+ # like #left, but returns self for simple cards
83
+ # @example
84
+ # "A".cardname.trunk -> "A"
85
+ # "A+B".cardname.trunk -> "A"
86
+ # "A+B+C".cardname.trunk -> "A+B"
87
+ # "A+B+C+D".cardname.trunk -> "A+B+C"
88
+ # @see #left
89
+ # @return [String]
24
90
  def trunk
25
91
  trunk_name.s
26
92
  end
27
93
 
94
+ # @see #trunk
95
+ # @return [String]
28
96
  def trunk_key
29
97
  trunk_name.key
30
98
  end
31
99
 
32
- def tag_name
33
- simple? ? self : right_name
100
+ # @see #trunk
101
+ # @return [Cardname]
102
+ def trunk_name
103
+ simple? ? self : left_name
34
104
  end
35
105
 
106
+ # like #right, but returns self for simple cards
107
+ # @see #right
108
+ # @example
109
+ # "A".cardname.tag -> "A"
110
+ # "A+B".cardname.tag -> "B"
111
+ # "A+B+C".cardname.tag -> "C"
112
+ # "A+B+C+D".cardname.tag -> "D"
113
+ # @return [String]
36
114
  def tag
37
115
  tag_name.s
38
116
  end
39
117
 
118
+ # @see #tag
119
+ # @return [String]
40
120
  def tag_key
41
121
  tag_name.key
42
122
  end
43
123
 
44
- def parent_names
45
- simple? ? [] : [left_name, right_name]
46
- end
47
-
48
- def parents
49
- parent_names.map(&:s)
50
- end
51
-
52
- def parent_keys
53
- parent_names.map(&:key)
54
- end
55
-
56
- def left_name
57
- simple? ? nil : self.class.new(part_names[0..-2])
58
- end
59
-
60
- def left
61
- left_name&.s
62
- end
63
-
64
- def left_key
65
- left_name&.key
66
- end
67
-
68
- def right_name
69
- simple? ? nil : part_names[-1]
124
+ # @see #tag
125
+ # @return [Cardname]
126
+ def tag_name
127
+ simple? ? self : right_name
70
128
  end
71
129
 
130
+ # the part of a compound name to the left of the rightmost joint.
131
+ #
132
+ # "A".cardname.right -> nil
133
+ # "A+B".cardname.right -> "B"
134
+ # "A+B+C".cardname.right -> "C"
135
+ # "A+B+C+D".cardname.right -> "D"
136
+ # @see #tag
137
+ # @return [String]
72
138
  def right
73
139
  right_name&.s
74
140
  end
75
141
 
142
+ # @see #right
143
+ # @return [String]
76
144
  def right_key
77
145
  right_name&.key
78
146
  end
79
147
 
148
+ # @see #right
149
+ # @return [Cardname]
150
+ def right_name
151
+ simple? ? nil : part_names[-1]
152
+ end
153
+
80
154
  private
81
155
 
82
156
  def generate_part_names
@@ -5,23 +5,35 @@ class Cardname
5
5
  module Pieces
6
6
  # self and all ancestors (= parts and recursive lefts)
7
7
  # @example
8
- # "A+B+C+D".to_name.pieces
9
- # # => ["A", "B", "C", "D", "A+B", "A+B+C", "A+B+C+D"]
8
+ # "A+B+C+D".to_name.pieces => ["A", "B", "C", "D", "A+B", "A+B+C", "A+B+C+D"]
9
+ # @return [Array <String>]
10
10
  def pieces
11
- simple? ? [self] : (parts + junction_pieces)
11
+ simple? ? [self] : (parts + compound_pieces)
12
12
  end
13
13
 
14
+ # @see #pieces
15
+ # @return [Array <Cardname>]
14
16
  def piece_names
15
17
  pieces.map(&:to_name)
16
18
  end
17
19
 
20
+ # parents, parents' parents, etc
21
+ # @example
22
+ # "A+B+C+D".to_name.ancestors => ["A", "B", "C", "D", "A+B", "A+B+C"]
23
+ # @return [Array <String>]
18
24
  def ancestors
19
25
  pieces.reject { |p| p == self }
20
26
  end
21
27
 
28
+ # @see #ancestors
29
+ # @return [Array <Cardname>]
30
+ def ancestor_pieces
31
+ ancestors.map(&:to_name)
32
+ end
33
+
22
34
  private
23
35
 
24
- def junction_pieces
36
+ def compound_pieces
25
37
  [].tap do |pieces|
26
38
  parts[1..-1].inject parts[0] do |left, right|
27
39
  piece = [left, right] * self.class.joint
@@ -1,16 +1,18 @@
1
1
  class Cardname
2
+ # name methods returning true/false
2
3
  module Predicates
3
- # @return true if name has only one part
4
+ # @return [Boolean] true if name has only one part
4
5
  def simple?
5
6
  part_names if @simple.nil?
6
7
  @simple
7
8
  end
8
9
 
9
- # @return true if name has more than one part
10
+ # @return [Boolean] true if name has more than one part
10
11
  def compound?
11
12
  !simple?
12
13
  end
13
14
 
15
+ # @return [Boolean] true unless name contains banned characters
14
16
  def valid?
15
17
  return true if self.class.nothing_banned?
16
18
 
@@ -19,21 +21,21 @@ class Cardname
19
21
  end
20
22
  end
21
23
 
22
- # @return true if name starts with the same parts as `prefix`
24
+ # @return [Boolean] true if name starts with the same parts as `prefix`
23
25
  def starts_with_parts? *prefix
24
26
  start_name = prefix.to_name
25
27
  start_name == self[0, start_name.num_parts]
26
28
  end
27
29
  alias_method :start_with_parts?, :starts_with_parts?
28
30
 
29
- # @return true if name ends with the same parts as `prefix`
31
+ # @return [Boolean] true if name ends with the same parts as `prefix`
30
32
  def ends_with_parts? *suffix
31
33
  end_name = suffix.to_name
32
34
  end_name == self[-end_name.num_parts..-1]
33
35
  end
34
36
  alias_method :end_with_parts?, :ends_with_parts?
35
37
 
36
- # @return true if name has a chain of parts that equals `subname`
38
+ # @return [Boolean] true if name has a chain of parts that equals `subname`
37
39
  def include? subname
38
40
  subkey = subname.to_name.key
39
41
  key =~ /(^|#{JOINT_RE})#{Regexp.quote subkey}($|#{JOINT_RE})/
@@ -2,6 +2,7 @@ require "htmlentities"
2
2
 
3
3
  class Cardname
4
4
  module Variants
5
+ # @return [String]
5
6
  def simple_key
6
7
  return "" if empty?
7
8
 
@@ -14,6 +15,8 @@ class Cardname
14
15
  .join("_")
15
16
  end
16
17
 
18
+ # URI-friendly version of name. retains case, underscores for space
19
+ # @return [String]
17
20
  def url_key
18
21
  part_names.map do |part_name|
19
22
  stripped = part_name.decoded.gsub(/[^#{OK4KEY_RE}]+/, " ").strip
@@ -24,18 +27,16 @@ class Cardname
24
27
  # safe to be used in HTML as id ('*' and '+' are not allowed),
25
28
  # but the key is no longer unique.
26
29
  # For example "A-XB" and "A+*B" have the same safe_key
30
+ # @return [String]
27
31
  def safe_key
28
32
  key.tr("*", "X").tr self.class.joint, "-"
29
33
  end
30
34
 
35
+ # @return [String]
31
36
  def decoded
32
37
  @decoded ||= s.index("&") ? HTMLEntities.new.decode(s) : s
33
38
  end
34
39
 
35
- def to_sym
36
- s.to_sym
37
- end
38
-
39
40
  private
40
41
 
41
42
  def uninflect_method
data/lib/cardname.rb CHANGED
@@ -3,6 +3,10 @@
3
3
  require "active_support/inflector"
4
4
  require "htmlentities"
5
5
 
6
+ # The Cardname class generalizes the core naming concepts of Decko/Card. The most central
7
+ # of these is the idea that compound names can be formed by combining simple names.
8
+ #
9
+ #
6
10
  class Cardname < String
7
11
  require "cardname/parts"
8
12
  require "cardname/pieces"
@@ -11,6 +15,7 @@ class Cardname < String
11
15
  require "cardname/predicates"
12
16
  require "cardname/manipulate"
13
17
  require "cardname/fields"
18
+ require "cardname/class_methods"
14
19
 
15
20
  include Parts
16
21
  include Pieces
@@ -19,8 +24,7 @@ class Cardname < String
19
24
  include Predicates
20
25
  include Manipulate
21
26
  include Fields
22
-
23
- OK4KEY_RE = '\p{Word}\*'
27
+ extend ClassMethods
24
28
 
25
29
  cattr_accessor :joint, :banned_array, :var_re, :uninflect, :params, :session, :stabilize
26
30
 
@@ -30,49 +34,9 @@ class Cardname < String
30
34
  self.uninflect = :singularize
31
35
  self.stabilize = false
32
36
 
37
+ OK4KEY_RE = '\p{Word}\*'
33
38
  JOINT_RE = Regexp.escape joint
34
39
 
35
- class << self
36
- def new obj
37
- return obj if obj.is_a? self.class
38
-
39
- str = stringify(obj)
40
- cache[str] ||= super(str)
41
- end
42
-
43
- def reset
44
- @cache = {}
45
- end
46
-
47
- def nothing_banned?
48
- return @nothing_banned unless @nothing_banned.nil?
49
-
50
- @nothing_banned = banned_array.empty?
51
- end
52
-
53
- def banned_re
54
- @banned_re ||= /[#{Regexp.escape((banned_array + [joint])).join}]/
55
- end
56
-
57
- def split_parts str
58
- str.split(/\s*#{JOINT_RE}\s*/, -1)
59
- end
60
-
61
- def cache
62
- @cache ||= {}
63
- end
64
-
65
- private
66
-
67
- def stringify obj
68
- if obj.is_a?(Array)
69
- obj.map(&:to_s) * joint
70
- else
71
- obj.to_s
72
- end
73
- end
74
- end
75
-
76
40
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
77
41
  # ~~~~~~~~~~~~~~~~~~~~~~ INSTANCE ~~~~~~~~~~~~~~~~~~~~~~~~~
78
42
  attr_reader :key
@@ -87,31 +51,32 @@ class Cardname < String
87
51
  freeze
88
52
  end
89
53
 
54
+ # simple string version of name
55
+ # @return [String]
90
56
  def s
91
57
  String.new self
92
58
  end
93
59
  alias_method :to_s, :s
94
60
  alias_method :to_str, :s
95
- # alias_method :dup, :clone
96
61
 
62
+ # @return [Cardname]
97
63
  def to_name
98
64
  self
99
65
  end
100
66
 
101
- def []= index, val
102
- p = parts
103
- p[index] = val
104
- replace self.class.new(p)
105
- end
106
-
107
- def << val
108
- replace self.class.new(parts << val)
67
+ # @return [Symbol]
68
+ def to_sym
69
+ s.to_sym
109
70
  end
110
71
 
72
+ # the key defines the namespace
73
+ # @return [String]
111
74
  def key
112
75
  @key ||= generate_key.freeze
113
76
  end
114
77
 
78
+ # test for same key
79
+ # @return [Boolean]
115
80
  def == other
116
81
  key ==
117
82
  case
@@ -121,6 +86,18 @@ class Cardname < String
121
86
  end
122
87
  end
123
88
 
89
+ # cardname based on part index
90
+ # @return [Cardname]
91
+ def [] *args
92
+ self.class.new part_names[*args]
93
+ end
94
+
95
+ # @see #parts
96
+ # @return [Integer]
97
+ def num_parts
98
+ parts.length
99
+ end
100
+
124
101
  private
125
102
 
126
103
  def generate_key
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cardname
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.0
4
+ version: 0.15.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ethan McCutchen
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-01-04 00:00:00.000000000 Z
13
+ date: 2023-03-29 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -50,6 +50,7 @@ files:
50
50
  - README.md
51
51
  - Rakefile
52
52
  - lib/cardname.rb
53
+ - lib/cardname/class_methods.rb
53
54
  - lib/cardname/contextual.rb
54
55
  - lib/cardname/fields.rb
55
56
  - lib/cardname/manipulate.rb