opal-activesupport 0.3.1 → 0.3.2

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.
@@ -1,15 +1,77 @@
1
1
  require 'active_support/inflector'
2
2
 
3
3
  class String
4
- def pluralize
5
- ActiveSupport::Inflector.pluralize(self)
4
+ def pluralize(count = nil, locale = :en)
5
+ locale = count if count.is_a?(Symbol)
6
+ if count == 1
7
+ dup
8
+ else
9
+ ActiveSupport::Inflector.pluralize(self, locale)
10
+ end
6
11
  end
7
12
 
8
- def singularize
9
- ActiveSupport::Inflector.singularize(self)
13
+ def singularize(locale = :en)
14
+ ActiveSupport::Inflector.singularize(self, locale)
10
15
  end
11
16
 
12
17
  def constantize
13
18
  ActiveSupport::Inflector.constantize(self)
14
19
  end
20
+
21
+ def safe_constantize
22
+ ActiveSupport::Inflector.safe_constantize(self)
23
+ end
24
+
25
+ def camelize(first_letter = :upper)
26
+ case first_letter
27
+ when :upper
28
+ ActiveSupport::Inflector.camelize(self, true)
29
+ when :lower
30
+ ActiveSupport::Inflector.camelize(self, false)
31
+ else
32
+ raise ArgumentError, "Invalid option, use either :upper or :lower."
33
+ end
34
+ end
35
+ alias_method :camelcase, :camelize
36
+
37
+ def titleize(keep_id_suffix: false)
38
+ ActiveSupport::Inflector.titleize(self, keep_id_suffix: keep_id_suffix)
39
+ end
40
+ alias_method :titlecase, :titleize
41
+
42
+ def underscore
43
+ ActiveSupport::Inflector.underscore(self)
44
+ end
45
+
46
+ def dasherize
47
+ ActiveSupport::Inflector.dasherize(self)
48
+ end
49
+
50
+ def demodulize
51
+ ActiveSupport::Inflector.demodulize(self)
52
+ end
53
+
54
+ def deconstantize
55
+ ActiveSupport::Inflector.deconstantize(self)
56
+ end
57
+
58
+ def tableize
59
+ ActiveSupport::Inflector.tableize(self)
60
+ end
61
+
62
+ def classify
63
+ ActiveSupport::Inflector.classify(self)
64
+ end
65
+
66
+ def humanize(capitalize: true, keep_id_suffix: false)
67
+ ActiveSupport::Inflector.humanize(self, capitalize: capitalize, keep_id_suffix: keep_id_suffix)
68
+ end
69
+
70
+ def upcase_first
71
+ ActiveSupport::Inflector.upcase_first(self)
72
+ end
73
+
74
+ def foreign_key(separate_class_name_and_id_with_underscore = true)
75
+ ActiveSupport::Inflector.foreign_key(self, separate_class_name_and_id_with_underscore)
76
+ end
15
77
  end
@@ -1,3 +1,5 @@
1
+ require "active_support/inflector/inflections"
2
+
1
3
  module ActiveSupport
2
4
  Inflector.inflections(:en) do |inflect|
3
5
  inflect.plural(/$/, 's')
@@ -1,2 +1,5 @@
1
- require 'active_support/inflector/inflections'
2
- require 'active_support/inflections'
1
+ require "active_support/inflector/inflections"
2
+ require "active_support/inflector/methods"
3
+
4
+ require "active_support/inflections"
5
+ require "active_support/core_ext/string/inflections"
@@ -4,86 +4,67 @@ module ActiveSupport
4
4
  module Inflector
5
5
  extend self
6
6
 
7
- def inflections(lang = :en)
8
- if block_given?
9
- yield Inflections.instance
10
- else
11
- Inflections.instance
12
- end
13
- end
7
+ class Inflections
8
+ @__instance__ = {}
14
9
 
15
- def constantize(camel_cased_word)
16
- names = camel_cased_word.split('::')
10
+ class Uncountables < Array
11
+ def <<(*word)
12
+ add(word)
13
+ end
17
14
 
18
- # Trigger a built-in NameError exception including the ill-formed constant in the message.
19
- Object.const_get(camel_cased_word) if names.empty?
15
+ def add(words)
16
+ words = words.flatten.map(&:downcase)
17
+ concat(words)
18
+ self
19
+ end
20
20
 
21
- # Remove the first blank element in case of '::ClassName' notation.
22
- names.shift if names.size > 1 && names.first.empty?
21
+ def uncountable?(str)
22
+ include?(str.downcase)
23
+ end
23
24
 
24
- names.inject(Object) do |constant, name|
25
- if constant == Object
26
- constant.const_get(name)
27
- else
28
- candidate = constant.const_get(name)
29
- next candidate if constant.const_defined?(name, false)
30
- next candidate unless Object.const_defined?(name)
31
-
32
- # Go down the ancestors to check if it is owned directly. The check
33
- # stops when we reach Object or the end of ancestors tree.
34
- constant = constant.ancestors.inject do |const, ancestor|
35
- break const if ancestor == Object
36
- break ancestor if ancestor.const_defined?(name, false)
37
- const
38
- end
39
-
40
- # owner is in Object, so raise
41
- constant.const_get(name, false)
25
+ def dup
26
+ copy = Uncountables.new
27
+ copy.add(self)
28
+ copy
42
29
  end
43
30
  end
44
- end
45
31
 
46
- def pluralize(word)
47
- apply_inflections(word, inflections.plurals)
48
- end
49
32
 
50
- def singularize(word)
51
- apply_inflections(word, inflections.singulars)
52
- end
33
+ def self.instance(locale)
34
+ @__instance__[locale] ||= new
35
+ end
53
36
 
54
- def apply_inflections(word, rules)
55
- result = word.to_s
37
+ attr_reader :plurals, :singulars, :uncountables, :humans
56
38
 
57
- if inflections.uncountables.include?(result.downcase)
58
- result
59
- else
60
- rules.detect do |rule, replacement|
61
- break result.sub(rule, replacement) if result.index(rule)
62
- end
39
+ def initialize
40
+ @plurals, @singulars, @uncountables, @humans = [], [], Uncountables.new, []
63
41
  end
64
- end
65
42
 
66
- class Inflections
67
- def self.instance
68
- @__instance__ ||= new
43
+ def initialize_dup(orig) # :nodoc:
44
+ %w(plurals singulars uncountables humans).each do |scope|
45
+ instance_variable_set("@#{scope}", orig.send(scope).dup)
46
+ end
69
47
  end
70
48
 
71
- attr_reader :plurals, :singulars, :uncountables
72
-
73
- def initialize
74
- @plurals, @singulars, @uncountables = [], [], Set.new
75
- end
76
49
 
77
50
  def plural(rule, replacement)
51
+ @uncountables.delete(rule) if rule.is_a?(String)
52
+ @uncountables.delete(replacement)
78
53
  @plurals.unshift([rule, replacement])
79
54
  end
80
55
 
81
56
  def singular(rule, replacement)
57
+ @uncountables.delete(rule) if rule.is_a?(String)
58
+ @uncountables.delete(replacement)
82
59
  @singulars.unshift([rule, replacement])
83
60
  end
84
61
 
85
- def uncountable(words)
86
- words.each { |w| @uncountables << w.downcase }
62
+ def uncountable(*words)
63
+ @uncountables.add(words)
64
+ end
65
+
66
+ def human(rule, replacement)
67
+ @humans.unshift([rule, replacement])
87
68
  end
88
69
 
89
70
  def irregular(singular, plural)
@@ -103,17 +84,34 @@ module ActiveSupport
103
84
  singular(/(#{s0})#{srest}$/i, '\1' + srest)
104
85
  singular(/(#{p0})#{prest}$/i, '\1' + srest)
105
86
  else
106
- plural(/#{s0.upcase}(?i)#{srest}$/, p0.upcase + prest)
107
- plural(/#{s0.downcase}(?i)#{srest}$/, p0.downcase + prest)
108
- plural(/#{p0.upcase}(?i)#{prest}$/, p0.upcase + prest)
109
- plural(/#{p0.downcase}(?i)#{prest}$/, p0.downcase + prest)
110
-
111
- singular(/#{s0.upcase}(?i)#{srest}$/, s0.upcase + srest)
112
- singular(/#{s0.downcase}(?i)#{srest}$/, s0.downcase + srest)
113
- singular(/#{p0.upcase}(?i)#{prest}$/, s0.upcase + srest)
114
- singular(/#{p0.downcase}(?i)#{prest}$/, s0.downcase + srest)
87
+ plural(/#{s0.upcase}#{srest}$/i, p0.upcase + prest)
88
+ plural(/#{s0.downcase}#{srest}$/i, p0.downcase + prest)
89
+ plural(/#{p0.upcase}#{prest}$/i, p0.upcase + prest)
90
+ plural(/#{p0.downcase}#{prest}$/i, p0.downcase + prest)
91
+
92
+ singular(/#{s0.upcase}#{srest}$/i, s0.upcase + srest)
93
+ singular(/#{s0.downcase}#{srest}$/i, s0.downcase + srest)
94
+ singular(/#{p0.upcase}#{prest}$/i, s0.upcase + srest)
95
+ singular(/#{p0.downcase}#{prest}$/i, s0.downcase + srest)
96
+ end
97
+ end
98
+
99
+ def clear(scope = :all)
100
+ case scope
101
+ when :all
102
+ @plurals, @singulars, @uncountables, @humans = [], [], Uncountables.new, []
103
+ else
104
+ instance_variable_set "@#{scope}", []
115
105
  end
116
106
  end
117
107
  end
108
+
109
+ def inflections(locale = :en)
110
+ if block_given?
111
+ yield Inflections.instance(locale)
112
+ else
113
+ Inflections.instance(locale)
114
+ end
115
+ end
118
116
  end
119
117
  end
@@ -0,0 +1,198 @@
1
+ require "active_support/inflections"
2
+
3
+ module ActiveSupport
4
+ module Inflector
5
+ extend self
6
+
7
+ def pluralize(word, locale = :en)
8
+ apply_inflections(word, inflections(locale).plurals, locale)
9
+ end
10
+
11
+ def singularize(word, locale = :en)
12
+ apply_inflections(word, inflections(locale).singulars, locale)
13
+ end
14
+
15
+ def camelize(term, uppercase_first_letter = true)
16
+ string = term.to_s
17
+ if uppercase_first_letter
18
+ string = string.sub(/^[a-z\d]*/) { |match| match.capitalize }
19
+ else
20
+ string = string.downcase
21
+ end
22
+ string = string.gsub(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
23
+ string = string.gsub("/".freeze, "::".freeze)
24
+ string
25
+ end
26
+
27
+ def underscore(camel_cased_word)
28
+ return camel_cased_word unless /[A-Z-]|::/.match?(camel_cased_word)
29
+ word = camel_cased_word.to_s.gsub("::".freeze, "/".freeze)
30
+ word = word.gsub(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2'.freeze)
31
+ word = word.gsub(/([a-z\d])([A-Z])/, '\1_\2'.freeze)
32
+ word = word.tr("-".freeze, "_".freeze)
33
+ word = word.downcase
34
+ word
35
+ end
36
+
37
+ def humanize(lower_case_and_underscored_word, capitalize: true, keep_id_suffix: false)
38
+ result = lower_case_and_underscored_word.to_s.dup
39
+
40
+ inflections.humans.each do |(rule, replacement)|
41
+ if (rule.is_a?(Regexp) && result =~ rule) || (rule.is_a?(String) && result == rule)
42
+ result = result.sub(rule, replacement)
43
+ break
44
+ end
45
+ end
46
+
47
+ result = result.sub(/\A_+/, "".freeze)
48
+ unless keep_id_suffix
49
+ result = result.sub(/_id\z/, "".freeze)
50
+ end
51
+ result = result.tr("_".freeze, " ".freeze)
52
+
53
+ result = result.gsub(/([a-z\d]*)/i) do |match|
54
+ "#{match.downcase}"
55
+ end
56
+
57
+ if capitalize
58
+ result = result.sub(/\A\w/) { |match| match.upcase }
59
+ end
60
+
61
+ result
62
+ end
63
+
64
+ def upcase_first(string)
65
+ string.length > 0 ? string[0].upcase + string[1..-1] : ""
66
+ end
67
+
68
+ def titleize(word, keep_id_suffix: false)
69
+ humanize(underscore(word), keep_id_suffix: keep_id_suffix).gsub(/([a-zA-Z'’`])[a-z]*/) do |match|
70
+ match.capitalize
71
+ end
72
+ end
73
+
74
+ def tableize(class_name)
75
+ pluralize(underscore(class_name))
76
+ end
77
+
78
+ def classify(table_name)
79
+ # strip out any leading schema name
80
+ camelize(singularize(table_name.to_s.sub(/.*\./, "".freeze)))
81
+ end
82
+
83
+ def dasherize(underscored_word)
84
+ underscored_word.tr("_".freeze, "-".freeze)
85
+ end
86
+
87
+ def demodulize(path)
88
+ path = path.to_s
89
+ if i = path.rindex("::")
90
+ path[(i + 2)..-1]
91
+ else
92
+ path
93
+ end
94
+ end
95
+
96
+ def deconstantize(path)
97
+ path.to_s[0, path.rindex("::") || 0] # implementation based on the one in facets' Module#spacename
98
+ end
99
+
100
+ def foreign_key(class_name, separate_class_name_and_id_with_underscore = true)
101
+ underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id")
102
+ end
103
+
104
+ def constantize(camel_cased_word)
105
+ names = camel_cased_word.split('::')
106
+
107
+ # Trigger a built-in NameError exception including the ill-formed constant in the message.
108
+ # FIXME: initially was
109
+ # Object.const_get(camel_cased_word) if names.empty?
110
+ # Changed because Opal can't handles such case
111
+ # Instead it throws something like <NoMethodError: undefined method 'upcase' for nil>
112
+ raise NameError, 'wrong constant name ' if names.empty?
113
+
114
+ # Remove the first blank element in case of '::ClassName' notation.
115
+ names.shift if names.size > 1 && names.first.empty?
116
+
117
+ names.inject(Object) do |constant, name|
118
+ if constant == Object
119
+ constant.const_get(name)
120
+ else
121
+ candidate = constant.const_get(name)
122
+ next candidate if constant.const_defined?(name, false)
123
+ next candidate unless Object.const_defined?(name)
124
+
125
+ # Go down the ancestors to check if it is owned directly. The check
126
+ # stops when we reach Object or the end of ancestors tree.
127
+ constant = constant.ancestors.inject(constant) do |const, ancestor|
128
+ break const if ancestor == Object
129
+ break ancestor if ancestor.const_defined?(name, false)
130
+ const
131
+ end
132
+
133
+ # owner is in Object, so raise
134
+ constant.const_get(name, false)
135
+ end
136
+ end
137
+ end
138
+
139
+ def safe_constantize(camel_cased_word)
140
+ constantize(camel_cased_word)
141
+ rescue NameError => e
142
+ raise if e.name && !(camel_cased_word.to_s.split("::").include?(e.name.to_s) ||
143
+ e.name.to_s == camel_cased_word.to_s)
144
+ rescue ArgumentError => e
145
+ raise unless /not missing constant #{const_regexp(camel_cased_word)}!$/.match?(e.message)
146
+ end
147
+
148
+
149
+ def ordinal(number)
150
+ abs_number = number.to_i.abs
151
+
152
+ if (11..13).include?(abs_number % 100)
153
+ "th"
154
+ else
155
+ case abs_number % 10
156
+ when 1; "st"
157
+ when 2; "nd"
158
+ when 3; "rd"
159
+ else "th"
160
+ end
161
+ end
162
+ end
163
+
164
+ def ordinalize(number)
165
+ "#{number}#{ordinal(number)}"
166
+ end
167
+
168
+ private
169
+
170
+ def const_regexp(camel_cased_word)
171
+ parts = camel_cased_word.split("::".freeze)
172
+
173
+ return Regexp.escape(camel_cased_word) if parts.blank?
174
+
175
+ last = parts.pop
176
+
177
+ parts.reverse.inject(last) do |acc, part|
178
+ part.empty? ? acc : "#{part}(::#{acc})?"
179
+ end
180
+ end
181
+
182
+ def apply_inflections(word, rules, locale = :en)
183
+ result = word.to_s.dup
184
+
185
+ if word.empty? || inflections(locale).uncountables.uncountable?(result)
186
+ result
187
+ else
188
+ rules.each do |(rule, replacement)|
189
+ if (rule.is_a?(Regexp) && result =~ rule) || (rule.is_a?(String) && result == rule)
190
+ result = result.sub(rule, replacement)
191
+ break
192
+ end
193
+ end
194
+ result
195
+ end
196
+ end
197
+ end
198
+ end