activesupport 1.3.1 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- data/CHANGELOG +232 -2
- data/README +43 -0
- data/lib/active_support.rb +4 -1
- data/lib/active_support/breakpoint.rb +5 -0
- data/lib/active_support/core_ext/array.rb +2 -16
- data/lib/active_support/core_ext/array/conversions.rb +30 -4
- data/lib/active_support/core_ext/array/grouping.rb +55 -0
- data/lib/active_support/core_ext/bigdecimal.rb +3 -0
- data/lib/active_support/core_ext/bigdecimal/formatting.rb +7 -0
- data/lib/active_support/core_ext/class/inheritable_attributes.rb +6 -1
- data/lib/active_support/core_ext/date/conversions.rb +13 -7
- data/lib/active_support/core_ext/enumerable.rb +41 -10
- data/lib/active_support/core_ext/exception.rb +2 -2
- data/lib/active_support/core_ext/hash/conversions.rb +123 -12
- data/lib/active_support/core_ext/hash/indifferent_access.rb +18 -9
- data/lib/active_support/core_ext/integer/inflections.rb +10 -4
- data/lib/active_support/core_ext/load_error.rb +3 -3
- data/lib/active_support/core_ext/module.rb +2 -0
- data/lib/active_support/core_ext/module/aliasing.rb +58 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +31 -0
- data/lib/active_support/core_ext/module/delegation.rb +27 -2
- data/lib/active_support/core_ext/name_error.rb +20 -0
- data/lib/active_support/core_ext/string.rb +2 -0
- data/lib/active_support/core_ext/string/access.rb +5 -5
- data/lib/active_support/core_ext/string/inflections.rb +93 -4
- data/lib/active_support/core_ext/string/unicode.rb +42 -0
- data/lib/active_support/core_ext/symbol.rb +1 -1
- data/lib/active_support/core_ext/time/calculations.rb +7 -5
- data/lib/active_support/core_ext/time/conversions.rb +1 -2
- data/lib/active_support/dependencies.rb +417 -50
- data/lib/active_support/deprecation.rb +201 -0
- data/lib/active_support/inflections.rb +1 -2
- data/lib/active_support/inflector.rb +117 -19
- data/lib/active_support/json.rb +14 -3
- data/lib/active_support/json/encoders/core.rb +21 -18
- data/lib/active_support/multibyte.rb +7 -0
- data/lib/active_support/multibyte/chars.rb +129 -0
- data/lib/active_support/multibyte/generators/generate_tables.rb +149 -0
- data/lib/active_support/multibyte/handlers/passthru_handler.rb +9 -0
- data/lib/active_support/multibyte/handlers/utf8_handler.rb +453 -0
- data/lib/active_support/multibyte/handlers/utf8_handler_proc.rb +44 -0
- data/lib/active_support/option_merger.rb +3 -3
- data/lib/active_support/ordered_options.rb +24 -23
- data/lib/active_support/reloadable.rb +39 -5
- data/lib/active_support/values/time_zone.rb +1 -1
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/vendor/builder/blankslate.rb +16 -6
- data/lib/active_support/vendor/builder/xchar.rb +112 -0
- data/lib/active_support/vendor/builder/xmlbase.rb +12 -10
- data/lib/active_support/vendor/builder/xmlmarkup.rb +26 -7
- data/lib/active_support/vendor/xml_simple.rb +1021 -0
- data/lib/active_support/version.rb +2 -2
- data/lib/active_support/whiny_nil.rb +1 -1
- metadata +26 -4
- data/lib/active_support/core_ext/hash/conversions.rb.rej +0 -28
@@ -0,0 +1,201 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module Deprecation
|
5
|
+
mattr_accessor :debug
|
6
|
+
self.debug = false
|
7
|
+
|
8
|
+
# Choose the default warn behavior according to RAILS_ENV.
|
9
|
+
# Ignore deprecation warnings in production.
|
10
|
+
DEFAULT_BEHAVIORS = {
|
11
|
+
'test' => Proc.new { |message, callstack|
|
12
|
+
$stderr.puts(message)
|
13
|
+
$stderr.puts callstack.join("\n ") if debug
|
14
|
+
},
|
15
|
+
'development' => Proc.new { |message, callstack|
|
16
|
+
RAILS_DEFAULT_LOGGER.warn message
|
17
|
+
RAILS_DEFAULT_LOGGER.debug callstack.join("\n ") if debug
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
class << self
|
22
|
+
def warn(message = nil, callstack = caller)
|
23
|
+
behavior.call(deprecation_message(callstack, message), callstack) if behavior && !silenced?
|
24
|
+
end
|
25
|
+
|
26
|
+
def default_behavior
|
27
|
+
if defined?(RAILS_ENV)
|
28
|
+
DEFAULT_BEHAVIORS[RAILS_ENV.to_s]
|
29
|
+
else
|
30
|
+
DEFAULT_BEHAVIORS['test']
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Have deprecations been silenced?
|
35
|
+
def silenced?
|
36
|
+
@silenced = false unless defined?(@silenced)
|
37
|
+
@silenced
|
38
|
+
end
|
39
|
+
|
40
|
+
# Silence deprecation warnings within the block.
|
41
|
+
def silence
|
42
|
+
old_silenced, @silenced = @silenced, true
|
43
|
+
yield
|
44
|
+
ensure
|
45
|
+
@silenced = old_silenced
|
46
|
+
end
|
47
|
+
|
48
|
+
attr_writer :silenced
|
49
|
+
|
50
|
+
|
51
|
+
private
|
52
|
+
def deprecation_message(callstack, message = nil)
|
53
|
+
message ||= "You are using deprecated behavior which will be removed from Rails 2.0."
|
54
|
+
"DEPRECATION WARNING: #{message} See http://www.rubyonrails.org/deprecation for details. #{deprecation_caller_message(callstack)}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def deprecation_caller_message(callstack)
|
58
|
+
file, line, method = extract_callstack(callstack)
|
59
|
+
if file
|
60
|
+
if line && method
|
61
|
+
"(called from #{method} at #{file}:#{line})"
|
62
|
+
else
|
63
|
+
"(called from #{file}:#{line})"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def extract_callstack(callstack)
|
69
|
+
if md = callstack.first.match(/^(.+?):(\d+)(?::in `(.*?)')?/)
|
70
|
+
md.captures
|
71
|
+
else
|
72
|
+
callstack.first
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Behavior is a block that takes a message argument.
|
78
|
+
mattr_accessor :behavior
|
79
|
+
self.behavior = default_behavior
|
80
|
+
|
81
|
+
# Warnings are not silenced by default.
|
82
|
+
self.silenced = false
|
83
|
+
|
84
|
+
module ClassMethods
|
85
|
+
# Declare that a method has been deprecated.
|
86
|
+
def deprecate(*method_names)
|
87
|
+
options = method_names.last.is_a?(Hash) ? method_names.pop : {}
|
88
|
+
method_names = method_names + options.keys
|
89
|
+
method_names.each do |method_name|
|
90
|
+
alias_method_chain(method_name, :deprecation) do |target, punctuation|
|
91
|
+
class_eval(<<-EOS, __FILE__, __LINE__)
|
92
|
+
def #{target}_with_deprecation#{punctuation}(*args, &block)
|
93
|
+
::ActiveSupport::Deprecation.warn(self.class.deprecated_method_warning(:#{method_name}, #{options[method_name].inspect}), caller)
|
94
|
+
#{target}_without_deprecation#{punctuation}(*args, &block)
|
95
|
+
end
|
96
|
+
EOS
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def deprecated_method_warning(method_name, message=nil)
|
102
|
+
warning = "#{method_name} is deprecated and will be removed from Rails #{deprecation_horizon}"
|
103
|
+
case message
|
104
|
+
when Symbol then "#{warning} (use #{message} instead)"
|
105
|
+
when String then "#{warning} (#{message})"
|
106
|
+
else warning
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def deprecation_horizon
|
111
|
+
'2.0'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
module Assertions
|
116
|
+
def assert_deprecated(match = nil, &block)
|
117
|
+
result, warnings = collect_deprecations(&block)
|
118
|
+
assert !warnings.empty?, "Expected a deprecation warning within the block but received none"
|
119
|
+
if match
|
120
|
+
match = Regexp.new(Regexp.escape(match)) unless match.is_a?(Regexp)
|
121
|
+
assert warnings.any? { |w| w =~ match }, "No deprecation warning matched #{match}: #{warnings.join(', ')}"
|
122
|
+
end
|
123
|
+
result
|
124
|
+
end
|
125
|
+
|
126
|
+
def assert_not_deprecated(&block)
|
127
|
+
result, deprecations = collect_deprecations(&block)
|
128
|
+
assert deprecations.empty?, "Expected no deprecation warning within the block but received #{deprecations.size}: \n #{deprecations * "\n "}"
|
129
|
+
result
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
def collect_deprecations
|
134
|
+
old_behavior = ActiveSupport::Deprecation.behavior
|
135
|
+
deprecations = []
|
136
|
+
ActiveSupport::Deprecation.behavior = Proc.new do |message, callstack|
|
137
|
+
deprecations << message
|
138
|
+
end
|
139
|
+
result = yield
|
140
|
+
[result, deprecations]
|
141
|
+
ensure
|
142
|
+
ActiveSupport::Deprecation.behavior = old_behavior
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Stand-in for @request, @attributes, @params, etc which emits deprecation
|
147
|
+
# warnings on any method call (except #inspect).
|
148
|
+
class DeprecatedInstanceVariableProxy
|
149
|
+
instance_methods.each { |m| undef_method m unless m =~ /^__/ }
|
150
|
+
|
151
|
+
def initialize(instance, method, var = "@#{method}")
|
152
|
+
@instance, @method, @var = instance, method, var
|
153
|
+
end
|
154
|
+
|
155
|
+
# Don't give a deprecation warning on inspect since test/unit and error
|
156
|
+
# logs rely on it for diagnostics.
|
157
|
+
def inspect
|
158
|
+
target.inspect
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
def method_missing(called, *args, &block)
|
163
|
+
warn caller, called, args
|
164
|
+
target.__send__(called, *args, &block)
|
165
|
+
end
|
166
|
+
|
167
|
+
def target
|
168
|
+
@instance.__send__(@method)
|
169
|
+
end
|
170
|
+
|
171
|
+
def warn(callstack, called, args)
|
172
|
+
ActiveSupport::Deprecation.warn("#{@var} is deprecated! Call #{@method}.#{called} instead of #{@var}.#{called}. Args: #{args.inspect}", callstack)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
class Module
|
179
|
+
include ActiveSupport::Deprecation::ClassMethods
|
180
|
+
end
|
181
|
+
|
182
|
+
require 'test/unit/error'
|
183
|
+
|
184
|
+
module Test
|
185
|
+
module Unit
|
186
|
+
class TestCase
|
187
|
+
include ActiveSupport::Deprecation::Assertions
|
188
|
+
end
|
189
|
+
|
190
|
+
class Error # :nodoc:
|
191
|
+
# Silence warnings when reporting test errors.
|
192
|
+
def message_with_silenced_deprecation
|
193
|
+
ActiveSupport::Deprecation.silence do
|
194
|
+
message_without_silenced_deprecation
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
alias_method_chain :message, :silenced_deprecation
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
@@ -11,7 +11,6 @@ Inflector.inflections do |inflect|
|
|
11
11
|
inflect.plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
|
12
12
|
inflect.plural(/(hive)$/i, '\1s')
|
13
13
|
inflect.plural(/([^aeiouy]|qu)y$/i, '\1ies')
|
14
|
-
inflect.plural(/([^aeiouy]|qu)ies$/i, '\1y')
|
15
14
|
inflect.plural(/(x|ch|ss|sh)$/i, '\1es')
|
16
15
|
inflect.plural(/(matr|vert|ind)ix|ex$/i, '\1ices')
|
17
16
|
inflect.plural(/([m|l])ouse$/i, '\1ice')
|
@@ -36,7 +35,7 @@ Inflector.inflections do |inflect|
|
|
36
35
|
inflect.singular(/(o)es$/i, '\1')
|
37
36
|
inflect.singular(/(shoe)s$/i, '\1')
|
38
37
|
inflect.singular(/(cris|ax|test)es$/i, '\1is')
|
39
|
-
inflect.singular(/(
|
38
|
+
inflect.singular(/(octop|vir)i$/i, '\1us')
|
40
39
|
inflect.singular(/(alias|status)es$/i, '\1')
|
41
40
|
inflect.singular(/^(ox)en/i, '\1')
|
42
41
|
inflect.singular(/(vert|ind)ices$/i, '\1ex')
|
@@ -1,9 +1,9 @@
|
|
1
|
-
require 'singleton'
|
1
|
+
require 'singleton'
|
2
2
|
|
3
3
|
# The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without,
|
4
4
|
# and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept
|
5
5
|
# in inflections.rb.
|
6
|
-
module Inflector
|
6
|
+
module Inflector
|
7
7
|
# A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional
|
8
8
|
# inflection rules. Examples:
|
9
9
|
#
|
@@ -21,20 +21,20 @@ module Inflector
|
|
21
21
|
# already have been loaded.
|
22
22
|
class Inflections
|
23
23
|
include Singleton
|
24
|
-
|
24
|
+
|
25
25
|
attr_reader :plurals, :singulars, :uncountables
|
26
|
-
|
26
|
+
|
27
27
|
def initialize
|
28
28
|
@plurals, @singulars, @uncountables = [], [], []
|
29
29
|
end
|
30
|
-
|
31
|
-
# Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
|
30
|
+
|
31
|
+
# Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
|
32
32
|
# The replacement should always be a string that may include references to the matched data from the rule.
|
33
33
|
def plural(rule, replacement)
|
34
34
|
@plurals.insert(0, [rule, replacement])
|
35
35
|
end
|
36
|
-
|
37
|
-
# Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression.
|
36
|
+
|
37
|
+
# Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression.
|
38
38
|
# The replacement should always be a string that may include references to the matched data from the rule.
|
39
39
|
def singular(rule, replacement)
|
40
40
|
@singulars.insert(0, [rule, replacement])
|
@@ -42,7 +42,7 @@ module Inflector
|
|
42
42
|
|
43
43
|
# Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
|
44
44
|
# for strings, not regular expressions. You simply pass the irregular in singular and plural form.
|
45
|
-
#
|
45
|
+
#
|
46
46
|
# Examples:
|
47
47
|
# irregular 'octopus', 'octopi'
|
48
48
|
# irregular 'person', 'people'
|
@@ -50,9 +50,9 @@ module Inflector
|
|
50
50
|
plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1])
|
51
51
|
singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1])
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
# Add uncountable words that shouldn't be attempted inflected.
|
55
|
-
#
|
55
|
+
#
|
56
56
|
# Examples:
|
57
57
|
# uncountable "money"
|
58
58
|
# uncountable "money", "information"
|
@@ -60,7 +60,7 @@ module Inflector
|
|
60
60
|
def uncountable(*words)
|
61
61
|
(@uncountables << words).flatten!
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
# Clears the loaded inflections within a given scope (default is :all). Give the scope as a symbol of the inflection type,
|
65
65
|
# the options are: :plurals, :singulars, :uncountables
|
66
66
|
#
|
@@ -87,6 +87,15 @@ module Inflector
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
+
# Returns the plural form of the word in the string.
|
91
|
+
#
|
92
|
+
# Examples
|
93
|
+
# "post".pluralize #=> "posts"
|
94
|
+
# "octopus".pluralize #=> "octopi"
|
95
|
+
# "sheep".pluralize #=> "sheep"
|
96
|
+
# "words".pluralize #=> "words"
|
97
|
+
# "the blue mailman".pluralize #=> "the blue mailmen"
|
98
|
+
# "CamelOctopus".pluralize #=> "CamelOctopi"
|
90
99
|
def pluralize(word)
|
91
100
|
result = word.to_s.dup
|
92
101
|
|
@@ -98,6 +107,15 @@ module Inflector
|
|
98
107
|
end
|
99
108
|
end
|
100
109
|
|
110
|
+
# The reverse of pluralize, returns the singular form of a word in a string.
|
111
|
+
#
|
112
|
+
# Examples
|
113
|
+
# "posts".singularize #=> "post"
|
114
|
+
# "octopi".singularize #=> "octopus"
|
115
|
+
# "sheep".singluarize #=> "sheep"
|
116
|
+
# "word".singluarize #=> "word"
|
117
|
+
# "the blue mailmen".singularize #=> "the blue mailman"
|
118
|
+
# "CamelOctopi".singularize #=> "CamelOctopus"
|
101
119
|
def singularize(word)
|
102
120
|
result = word.to_s.dup
|
103
121
|
|
@@ -109,6 +127,16 @@ module Inflector
|
|
109
127
|
end
|
110
128
|
end
|
111
129
|
|
130
|
+
# By default, camelize converts strings to UpperCamelCase. If the argument to camelize
|
131
|
+
# is set to ":lower" then camelize produces lowerCamelCase.
|
132
|
+
#
|
133
|
+
# camelize will also convert '/' to '::' which is useful for converting paths to namespaces
|
134
|
+
#
|
135
|
+
# Examples
|
136
|
+
# "active_record".camelize #=> "ActiveRecord"
|
137
|
+
# "active_record".camelize(:lower) #=> "activeRecord"
|
138
|
+
# "active_record/errors".camelize #=> "ActiveRecord::Errors"
|
139
|
+
# "active_record/errors".camelize(:lower) #=> "activeRecord::Errors"
|
112
140
|
def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
|
113
141
|
if first_letter_in_uppercase
|
114
142
|
lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
@@ -117,10 +145,26 @@ module Inflector
|
|
117
145
|
end
|
118
146
|
end
|
119
147
|
|
148
|
+
# Capitalizes all the words and replaces some characters in the string to create
|
149
|
+
# a nicer looking title. Titleize is meant for creating pretty output. It is not
|
150
|
+
# used in the Rails internals.
|
151
|
+
#
|
152
|
+
# titleize is also aliased as as titlecase
|
153
|
+
#
|
154
|
+
# Examples
|
155
|
+
# "man from the boondocks".titleize #=> "Man From The Boondocks"
|
156
|
+
# "x-men: the last stand".titleize #=> "X Men: The Last Stand"
|
120
157
|
def titleize(word)
|
121
158
|
humanize(underscore(word)).gsub(/\b([a-z])/) { $1.capitalize }
|
122
159
|
end
|
123
|
-
|
160
|
+
|
161
|
+
# The reverse of +camelize+. Makes an underscored form from the expression in the string.
|
162
|
+
#
|
163
|
+
# Changes '::' to '/' to convert namespaces to paths.
|
164
|
+
#
|
165
|
+
# Examples
|
166
|
+
# "ActiveRecord".underscore #=> "active_record"
|
167
|
+
# "ActiveRecord::Errors".underscore #=> active_record/errors
|
124
168
|
def underscore(camel_cased_word)
|
125
169
|
camel_cased_word.to_s.gsub(/::/, '/').
|
126
170
|
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
@@ -128,39 +172,93 @@ module Inflector
|
|
128
172
|
tr("-", "_").
|
129
173
|
downcase
|
130
174
|
end
|
131
|
-
|
175
|
+
|
176
|
+
# Replaces underscores with dashes in the string.
|
177
|
+
#
|
178
|
+
# Example
|
179
|
+
# "puni_puni" #=> "puni-puni"
|
132
180
|
def dasherize(underscored_word)
|
133
181
|
underscored_word.gsub(/_/, '-')
|
134
182
|
end
|
135
183
|
|
184
|
+
# Capitalizes the first word and turns underscores into spaces and strips _id.
|
185
|
+
# Like titleize, this is meant for creating pretty output.
|
186
|
+
#
|
187
|
+
# Examples
|
188
|
+
# "employee_salary" #=> "Employee salary"
|
189
|
+
# "author_id" #=> "Author"
|
136
190
|
def humanize(lower_case_and_underscored_word)
|
137
191
|
lower_case_and_underscored_word.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize
|
138
192
|
end
|
139
193
|
|
194
|
+
# Removes the module part from the expression in the string
|
195
|
+
#
|
196
|
+
# Examples
|
197
|
+
# "ActiveRecord::CoreExtensions::String::Inflections".demodulize #=> "Inflections"
|
198
|
+
# "Inflections".demodulize #=> "Inflections"
|
140
199
|
def demodulize(class_name_in_module)
|
141
200
|
class_name_in_module.to_s.gsub(/^.*::/, '')
|
142
201
|
end
|
143
202
|
|
203
|
+
# Create the name of a table like Rails does for models to table names. This method
|
204
|
+
# uses the pluralize method on the last word in the string.
|
205
|
+
#
|
206
|
+
# Examples
|
207
|
+
# "RawScaledScorer".tableize #=> "raw_scaled_scorers"
|
208
|
+
# "egg_and_ham".tableize #=> "egg_and_hams"
|
209
|
+
# "fancyCategory".tableize #=> "fancy_categories"
|
144
210
|
def tableize(class_name)
|
145
211
|
pluralize(underscore(class_name))
|
146
212
|
end
|
147
|
-
|
213
|
+
|
214
|
+
# Create a class name from a table name like Rails does for table names to models.
|
215
|
+
# Note that this returns a string and not a Class. (To convert to an actual class
|
216
|
+
# follow classify with constantize.)
|
217
|
+
#
|
218
|
+
# Examples
|
219
|
+
# "egg_and_hams".classify #=> "EggAndHam"
|
220
|
+
# "post".classify #=> "Post"
|
148
221
|
def classify(table_name)
|
149
|
-
|
222
|
+
# strip out any leading schema name
|
223
|
+
camelize(singularize(table_name.to_s.sub(/.*\./, '')))
|
150
224
|
end
|
151
225
|
|
226
|
+
# Creates a foreign key name from a class name.
|
227
|
+
# +separate_class_name_and_id_with_underscore+ sets whether
|
228
|
+
# the method should put '_' between the name and 'id'.
|
229
|
+
#
|
230
|
+
# Examples
|
231
|
+
# "Message".foreign_key #=> "message_id"
|
232
|
+
# "Message".foreign_key(false) #=> "messageid"
|
233
|
+
# "Admin::Post".foreign_key #=> "post_id"
|
152
234
|
def foreign_key(class_name, separate_class_name_and_id_with_underscore = true)
|
153
235
|
underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id")
|
154
236
|
end
|
155
237
|
|
238
|
+
# Constantize tries to find a declared constant with the name specified
|
239
|
+
# in the string. It raises a NameError when the name is not in CamelCase
|
240
|
+
# or is not initialized.
|
241
|
+
#
|
242
|
+
# Examples
|
243
|
+
# "Module".constantize #=> Module
|
244
|
+
# "Class".constantize #=> Class
|
156
245
|
def constantize(camel_cased_word)
|
157
|
-
|
158
|
-
|
159
|
-
|
246
|
+
unless /^(::)?([A-Z]\w*)(::[A-Z]\w*)*$/ =~ camel_cased_word
|
247
|
+
raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
|
248
|
+
end
|
249
|
+
|
160
250
|
camel_cased_word = "::#{camel_cased_word}" unless $1
|
161
251
|
Object.module_eval(camel_cased_word, __FILE__, __LINE__)
|
162
252
|
end
|
163
253
|
|
254
|
+
# Ordinalize turns a number into an ordinal string used to denote the
|
255
|
+
# position in an ordered sequence such as 1st, 2nd, 3rd, 4th.
|
256
|
+
#
|
257
|
+
# Examples
|
258
|
+
# ordinalize(1) # => "1st"
|
259
|
+
# ordinalize(2) # => "2nd"
|
260
|
+
# ordinalize(1002) # => "1002nd"
|
261
|
+
# ordinalize(1003) # => "1003rd"
|
164
262
|
def ordinalize(number)
|
165
263
|
if (11..13).include?(number.to_i % 100)
|
166
264
|
"#{number}th"
|