activesupport 1.0.4 → 1.1.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 CHANGED
@@ -1,3 +1,40 @@
1
+ *SVN*
2
+
3
+ * Fixed conflict with Glue gem #1606 [Rick Olson]
4
+
5
+ * Added new rules to the Inflector to deal with more unusual plurals mouse/louse => mice/lice, information => information, ox => oxen, virus => viri, archive => archives #1571, #1583, #1490, #1599, #1608 [foamdino@gmail.com/others]
6
+
7
+ * Fixed memory leak with Object#remove_subclasses_of, which inflicted a Rails application running in development mode with a ~20KB leak per request #1289 [c.r.mcgrath@gmail.com]
8
+
9
+ * Made 1.year == 365.25.days to account for leap years. This allows you to do User.find(:all, :conditions => ['birthday > ?', 50.years.ago]) without losing a lot of days. #1488 [tuxie@dekadance.se]
10
+
11
+ * Added an exception if calling id on nil to WhinyNil #584 [kevin-temp@writesoon.com]
12
+
13
+ * Added Fix/Bignum#multiple_of? which returns true on 14.multiple_of?(7) and false on 16.multiple_of?(7) #1464 [Thomas Fuchs]
14
+
15
+ * Added even? and odd? to work with Bignums in addition to Fixnums #1464 [Thomas Fuchs]
16
+
17
+ * Fixed Time#at_beginning_of_week returned the next Monday instead of the previous one when called on a Sunday #1403 [jean.helou@gmail.com]
18
+
19
+ * Increased the speed of indifferent hash access by using Hash#default. #1436 [Nicholas Seckar]
20
+
21
+ * Added that " " is now also blank? (using strip if available)
22
+
23
+ * Fixed Dependencies so all modules are able to load missing constants #1173 [Nicholas Seckar]
24
+
25
+ * Fixed the Inflector to underscore strings containing numbers, so Area51Controller becomes area51_controller #1176 [Nicholas Seckar]
26
+
27
+ * Fixed that HashWithIndifferentAccess stringified all keys including symbols, ints, objects, and arrays #1162 [Nicholas Seckar]
28
+
29
+ * Fixed Time#last_year to go back in time, not forward #1278 [fabien@odilat.com]
30
+
31
+ * Fixed the pluralization of analysis to analyses #1295 [seattle@rootimage.msu.edu]
32
+
33
+ * Fixed that Time.local(2005,12).months_since(1) would raise "ArgumentError: argument out of range" #1311 [jhahn@niveon.com]
34
+
35
+ * Added silencing to the default Logger class
36
+
37
+
1
38
  *1.0.4* (19th April, 2005)
2
39
 
3
40
  * Fixed that in some circumstances controllers outside of modules may have hidden ones inside modules. For example, admin/content might have been hidden by /content. #1075 [Nicholas Seckar]
@@ -11,7 +48,7 @@
11
48
 
12
49
  *1.0.3* (27th March, 2005)
13
50
 
14
- * Fixed Inflector.pluralize to handle capitalized words #932 [bitsweat]
51
+ * Fixed Inflector.pluralize to handle capitalized words #932 [Jeremy Kemper]
15
52
 
16
53
  * Added Object#suppress which allows you to make a saner choice around with exceptions to swallow #980. Example:
17
54
 
@@ -90,7 +127,7 @@
90
127
 
91
128
  * Added Inflector.humanize to turn attribute names like employee_salary into "Employee salary". Used by automated error reporting in AR.
92
129
 
93
- * Added availability of class inheritable attributes to the masses #477 [bitsweat]
130
+ * Added availability of class inheritable attributes to the masses #477 [Jeremy Kemper]
94
131
 
95
132
  class Foo
96
133
  class_inheritable_reader :read_me
@@ -108,14 +145,14 @@
108
145
  Bar.read_and_write_me = 'bar'
109
146
  Bar.read_and_write_me != Foo.read_and_write_me
110
147
 
111
- * Added Inflections as an extension on String, so Inflector.pluralize(Inflector.classify(name)) becomes name.classify.pluralize #476 [bitsweat]
148
+ * Added Inflections as an extension on String, so Inflector.pluralize(Inflector.classify(name)) becomes name.classify.pluralize #476 [Jeremy Kemper]
112
149
 
113
150
  * Added Byte operations to Numeric, so 5.5.megabytes + 200.kilobytes #461 [Marcel Molina]
114
151
 
115
152
  * Fixed that Dependencies.reload can't load the same file twice #420 [Kent Sibilev]
116
153
 
117
- * Added Fixnum#ago/until, Fixnum#since/from_now #450 [bitsweat]
154
+ * Added Fixnum#ago/until, Fixnum#since/from_now #450 [Jeremy Kemper]
118
155
 
119
156
  * Added that Inflector now accepts Symbols and Classes by calling .to_s on the word supplied
120
157
 
121
- * Added time unit extensions to Fixnum that'll return the period in seconds, like 2.days + 4.hours.
158
+ * Added time unit extensions to Fixnum that'll return the period in seconds, like 2.days + 4.hours.
@@ -2,7 +2,7 @@
2
2
  # just like the native attr* accessors for instance attributes.
3
3
  class Class # :nodoc:
4
4
  def cattr_reader(*syms)
5
- syms.each do |sym|
5
+ syms.select { |sym| sym.respond_to?(:id2name) }.each do |sym|
6
6
  class_eval <<-EOS
7
7
  if ! defined? @@#{sym.id2name}
8
8
  @@#{sym.id2name} = nil
@@ -29,7 +29,7 @@ class Class # :nodoc:
29
29
  end
30
30
 
31
31
  def cattr_writer(*syms)
32
- syms.each do |sym|
32
+ syms.select { |sym| sym.respond_to?(:id2name) }.each do |sym|
33
33
  class_eval <<-EOS
34
34
  if ! defined? @@#{sym.id2name}
35
35
  @@#{sym.id2name} = nil
@@ -54,4 +54,4 @@ class Class # :nodoc:
54
54
  cattr_reader(*syms)
55
55
  cattr_writer(*syms)
56
56
  end
57
- end
57
+ end
@@ -1,6 +1,14 @@
1
1
  require 'logger'
2
2
 
3
3
  class Logger #:nodoc:
4
+ # Silences the logger for the duration of the block.
5
+ def silence(temporary_level = Logger::ERROR)
6
+ old_logger_level, self.level = level, temporary_level
7
+ yield
8
+ ensure
9
+ self.level = old_logger_level
10
+ end
11
+
4
12
  private
5
13
  remove_const "Format"
6
14
  Format = "%s\n"
@@ -0,0 +1,5 @@
1
+ require File.dirname(__FILE__) + '/array/to_param'
2
+
3
+ class Array #:nodoc:
4
+ include ActiveSupport::CoreExtensions::Array::ToParam
5
+ end
@@ -0,0 +1,12 @@
1
+ module ActiveSupport #:nodoc:
2
+ module CoreExtensions #:nodoc:
3
+ module Array #:nodoc:
4
+ module ToParam #:nodoc:
5
+ # When an array is given to url_for, it is converted to a slash separated string.
6
+ def to_param
7
+ join '/'
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ require File.dirname(__FILE__) + '/cgi/escape_skipping_slashes'
2
+
3
+ class CGI #:nodoc:
4
+ extend(ActiveSupport::CoreExtensions::CGI::EscapeSkippingSlashes)
5
+ end
@@ -0,0 +1,14 @@
1
+ module ActiveSupport #:nodoc:
2
+ module CoreExtensions #:nodoc:
3
+ module CGI #:nodoc:
4
+ module EscapeSkippingSlashes #:nodoc:
5
+ def escape_skipping_slashes(str)
6
+ str = str.join('/') if str.respond_to? :join
7
+ str.gsub(/([^ \/a-zA-Z0-9_.-])/n) do
8
+ "%#{$1.unpack('H2').first.upcase}"
9
+ end.tr(' ', '+')
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -3,6 +3,11 @@ module ActiveSupport #:nodoc:
3
3
  module Date #:nodoc:
4
4
  # Getting dates in different convenient string representations and other objects
5
5
  module Conversions
6
+ DATE_FORMATS = {
7
+ :short => "%e %b",
8
+ :long => "%B %e, %Y"
9
+ }
10
+
6
11
  def self.append_features(klass) #:nodoc:
7
12
  super
8
13
  klass.send(:alias_method, :to_default_s, :to_s)
@@ -10,11 +15,7 @@ module ActiveSupport #:nodoc:
10
15
  end
11
16
 
12
17
  def to_formatted_s(format = :default)
13
- case format
14
- when :default then to_default_s
15
- when :short then strftime("%e %b").strip
16
- when :long then strftime("%B %e, %Y").strip
17
- end
18
+ DATE_FORMATS[format] ? strftime(DATE_FORMATS[format]).strip : to_default_s
18
19
  end
19
20
 
20
21
  # To be able to keep Dates and Times interchangeable on conversions
@@ -3,3 +3,7 @@ require File.dirname(__FILE__) + '/fixnum/even_odd'
3
3
  class Fixnum #:nodoc:
4
4
  include ActiveSupport::CoreExtensions::Fixnum::EvenOdd
5
5
  end
6
+
7
+ class Bignum #:nodoc:
8
+ include ActiveSupport::CoreExtensions::Fixnum::EvenOdd
9
+ end
@@ -7,8 +7,12 @@ module ActiveSupport #:nodoc:
7
7
  # * 2.even? # => true
8
8
  # * 2.odd? # => false
9
9
  module EvenOdd
10
+ def multiple_of?(number)
11
+ self % number == 0
12
+ end
13
+
10
14
  def even?
11
- self % 2 == 0
15
+ multiple_of? 2
12
16
  end
13
17
 
14
18
  def odd?
@@ -3,21 +3,15 @@ class HashWithIndifferentAccess < Hash
3
3
  def initialize(constructor = {})
4
4
  if constructor.is_a?(Hash)
5
5
  super()
6
- update(constructor.stringify_keys)
6
+ update(constructor)
7
7
  else
8
8
  super(constructor)
9
9
  end
10
10
  end
11
-
12
- alias_method :regular_reader, :[] unless method_defined?(:regular_reader)
13
-
14
- def [](key)
15
- case key
16
- when Symbol: regular_reader(key.to_s) || regular_reader(key)
17
- when String: regular_reader(key) || regular_reader(key.to_sym)
18
- else regular_reader(key)
19
- end
20
- end
11
+
12
+ def default(key)
13
+ self[key.to_s] if key.is_a?(Symbol)
14
+ end
21
15
 
22
16
  alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
23
17
 
@@ -56,7 +50,7 @@ end
56
50
  module ActiveSupport #:nodoc:
57
51
  module CoreExtensions #:nodoc:
58
52
  module Hash #:nodoc:
59
- module IndifferentAccess
53
+ module IndifferentAccess #:nodoc:
60
54
  def with_indifferent_access
61
55
  HashWithIndifferentAccess.new(self)
62
56
  end
@@ -1,4 +1,4 @@
1
- class MissingSourceFile < LoadError
1
+ class MissingSourceFile < LoadError #:nodoc:
2
2
  attr_reader :path
3
3
  def initialize(message, path)
4
4
  super(message)
@@ -24,10 +24,10 @@ class MissingSourceFile < LoadError
24
24
  ]
25
25
  end
26
26
 
27
- module ActiveSupport
28
- module CoreExtensions
29
- module LoadErrorExtensions
30
- module LoadErrorClassMethods
27
+ module ActiveSupport #:nodoc:
28
+ module CoreExtensions #:nodoc:
29
+ module LoadErrorExtensions #:nodoc:
30
+ module LoadErrorClassMethods #:nodoc:
31
31
  def new(*args)
32
32
  (self == LoadError && MissingSourceFile.from_message(args.first)) || super
33
33
  end
@@ -32,9 +32,9 @@ module ActiveSupport #:nodoc:
32
32
  self * 30.days
33
33
  end
34
34
  alias :month :months
35
-
35
+
36
36
  def years
37
- self * 365.days
37
+ (self * 365.25.days).to_i
38
38
  end
39
39
  alias :year :years
40
40
 
@@ -1,6 +1,13 @@
1
1
  class Object #:nodoc:
2
2
  def remove_subclasses_of(superclass)
3
- subclasses_of(superclass).each { |subclass| Object.send(:remove_const, subclass) rescue nil }
3
+ subclasses_of(superclass).each do |subclass|
4
+ ObjectSpace.each_object(Class) do |k|
5
+ if k.to_s == subclass
6
+ k.instance_variables.each { |v| k.send(:remove_instance_variable, v) }
7
+ end
8
+ end
9
+ Object.send(:remove_const, subclass) rescue nil
10
+ end
4
11
  end
5
12
 
6
13
  def subclasses_of(superclass)
@@ -12,8 +19,11 @@ class Object #:nodoc:
12
19
  subclasses
13
20
  end
14
21
 
22
+ # "", " ", nil, and 0 are all blank
15
23
  def blank?
16
- if respond_to? :empty?
24
+ if respond_to?(:empty?) && respond_to?(:strip)
25
+ strip.empty?
26
+ elsif respond_to? :empty?
17
27
  empty?
18
28
  elsif respond_to? :zero?
19
29
  zero?
@@ -48,7 +48,8 @@ module ActiveSupport #:nodoc:
48
48
 
49
49
  def months_since(months)
50
50
  if months + self.month > 12
51
- change(:year => self.year + 1, :month => 1).months_since(months - (self.month == 1 ? 12 : (self.month + 1)))
51
+ old_time = self
52
+ change(:year => self.year + 1, :month => 1).months_since(months + old_time.month - 12 - 1)
52
53
  else
53
54
  change(:year => self.year, :month => self.month + months)
54
55
  end
@@ -63,12 +64,12 @@ module ActiveSupport #:nodoc:
63
64
  change(:year => self.year + years)
64
65
  end
65
66
 
66
- # Short-hand for months_ago(1)
67
+ # Short-hand for years_ago(1)
67
68
  def last_year
68
- years_since(1)
69
+ years_ago(1)
69
70
  end
70
71
 
71
- # Short-hand for months_since(1)
72
+ # Short-hand for years_since(1)
72
73
  def next_year
73
74
  years_since(1)
74
75
  end
@@ -86,7 +87,8 @@ module ActiveSupport #:nodoc:
86
87
 
87
88
  # Returns a new Time representing the "start" of this week (Monday, 0:00)
88
89
  def beginning_of_week
89
- (self - self.wday.days).midnight + 1.day
90
+ days_to_monday = self.wday!=0 ? self.wday-1 : 6
91
+ (self - days_to_monday.days).midnight
90
92
  end
91
93
  alias :monday :beginning_of_week
92
94
  alias :at_beginning_of_week :beginning_of_week
@@ -5,6 +5,12 @@ module ActiveSupport #:nodoc:
5
5
  module Time #:nodoc:
6
6
  # Getting times in different convenient string representations and other objects
7
7
  module Conversions
8
+ DATE_FORMATS = {
9
+ :db => "%Y-%m-%d %H:%M:%S",
10
+ :short => "%e %b %H:%M",
11
+ :long => "%B %e, %Y %H:%M"
12
+ }
13
+
8
14
  def self.append_features(klass)
9
15
  super
10
16
  klass.send(:alias_method, :to_default_s, :to_s)
@@ -12,12 +18,7 @@ module ActiveSupport #:nodoc:
12
18
  end
13
19
 
14
20
  def to_formatted_s(format = :default)
15
- case format
16
- when :default then to_default_s
17
- when :db then strftime("%Y-%m-%d %H:%M:%S")
18
- when :short then strftime("%e %b %H:%M").strip
19
- when :long then strftime("%B %e, %Y %H:%M").strip
20
- end
21
+ DATE_FORMATS[format] ? strftime(DATE_FORMATS[format]).strip : to_default_s
21
22
  end
22
23
 
23
24
  def to_date
@@ -1,6 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/module_attribute_accessors'
2
2
 
3
- module Dependencies
3
+ module Dependencies #:nodoc:
4
4
  extend self
5
5
 
6
6
  @@loaded = [ ]
@@ -14,7 +14,7 @@ module Dependencies
14
14
  end
15
15
 
16
16
  def depend_on(file_name, swallow_load_errors = false)
17
- if !loaded.include?(file_name)
17
+ unless loaded.include?(file_name)
18
18
  loaded << file_name
19
19
 
20
20
  begin
@@ -34,7 +34,7 @@ module Dependencies
34
34
  end
35
35
 
36
36
  def require_or_load(file_name)
37
- file_name = "#{file_name}.rb" unless ! load? || /\.rb$/ =~ file_name
37
+ file_name = "#{file_name}.rb" unless ! load? || file_name[-3..-1] == '.rb'
38
38
  load? ? load(file_name) : require(file_name)
39
39
  end
40
40
 
@@ -48,12 +48,14 @@ module Dependencies
48
48
  # load the relavent files automatically.
49
49
  #
50
50
  # Ruby-style modules are supported, as a folder named 'submodule' will load 'submodule.rb' when available.
51
- class LoadingModule < Module
51
+ class LoadingModule < Module #:nodoc:
52
52
  attr_reader :path
53
53
  attr_reader :root
54
54
 
55
- def self.root(*load_paths)
56
- RootLoadingModule.new(*load_paths)
55
+ class << self
56
+ def root(*load_paths)
57
+ RootLoadingModule.new(*load_paths)
58
+ end
57
59
  end
58
60
 
59
61
  def initialize(root, path=[])
@@ -61,7 +63,7 @@ module Dependencies
61
63
  @root = root
62
64
  end
63
65
 
64
- def root?() self.root == self end
66
+ def root?() self.root == self end
65
67
  def load_paths() self.root.load_paths end
66
68
 
67
69
  # Load missing constants if possible.
@@ -71,13 +73,15 @@ module Dependencies
71
73
 
72
74
  # Load the controller class or a parent module.
73
75
  def const_load!(name, file_name = nil)
76
+ file_name ||= 'application' if root? && name.to_s == 'ApplicationController'
74
77
  path = self.path + [file_name || name]
75
78
 
76
79
  load_paths.each do |load_path|
77
80
  fs_path = load_path.filesystem_path(path)
78
81
  next unless fs_path
79
82
 
80
- if File.directory?(fs_path)
83
+ case
84
+ when File.directory?(fs_path)
81
85
  new_module = LoadingModule.new(self.root, self.path + [name])
82
86
  self.const_set name, new_module
83
87
  if self.root?
@@ -88,7 +92,7 @@ module Dependencies
88
92
  Object.const_set(name, new_module)
89
93
  end
90
94
  break
91
- elsif File.file?(fs_path)
95
+ when File.file?(fs_path)
92
96
  self.root.load_file!(fs_path)
93
97
 
94
98
  # Import the loaded constant from Object provided we are the root node.
@@ -97,7 +101,7 @@ module Dependencies
97
101
  end
98
102
  end
99
103
 
100
- return self.const_defined?(name)
104
+ self.const_defined?(name)
101
105
  end
102
106
 
103
107
  # Is this name present or loadable?
@@ -107,7 +111,7 @@ module Dependencies
107
111
  end
108
112
  end
109
113
 
110
- class RootLoadingModule < LoadingModule
114
+ class RootLoadingModule < LoadingModule #:nodoc:
111
115
  attr_reader :load_paths
112
116
 
113
117
  def initialize(*paths)
@@ -133,7 +137,7 @@ module Dependencies
133
137
  end
134
138
 
135
139
  # This object defines a path from which Constants can be loaded.
136
- class ConstantLoadPath
140
+ class ConstantLoadPath #:nodoc:
137
141
  # Create a new load path with the filesystem path
138
142
  def initialize(root) @root = root end
139
143
 
@@ -141,7 +145,7 @@ module Dependencies
141
145
  # if the path leads to a module, or the path to a file if it leads to an object.
142
146
  def filesystem_path(path, allow_module=true)
143
147
  fs_path = [@root]
144
- fs_path += path[0..-2].collect {|name| const_name_to_module_name name}
148
+ fs_path += path[0..-2].map {|name| const_name_to_module_name name}
145
149
 
146
150
  if allow_module
147
151
  result = File.join(fs_path, const_name_to_module_name(path.last))
@@ -150,7 +154,7 @@ module Dependencies
150
154
 
151
155
  result = File.join(fs_path, const_name_to_file_name(path.last))
152
156
 
153
- return File.file?(result) ? result : nil
157
+ File.file?(result) ? result : nil
154
158
  end
155
159
 
156
160
  def const_name_to_file_name(name)
@@ -164,46 +168,44 @@ module Dependencies
164
168
  end
165
169
 
166
170
  Object.send(:define_method, :require_or_load) { |file_name| Dependencies.require_or_load(file_name) } unless Object.respond_to?(:require_or_load)
167
- Object.send(:define_method, :require_dependency) { |file_name| Dependencies.depend_on(file_name) } unless Object.respond_to?(:require_dependency)
168
- Object.send(:define_method, :require_association) { |file_name| Dependencies.associate_with(file_name) } unless Object.respond_to?(:require_association)
169
-
170
- class Object #:nodoc:
171
- class << self
172
- # Use const_missing to autoload associations so we don't have to
173
- # require_association when using single-table inheritance.
174
- def const_missing(class_id)
175
- if Object.const_defined?(:Controllers) and Object::Controllers.const_available?(class_id)
176
- return Object::Controllers.const_get(class_id)
177
- end
178
-
179
- begin
180
- require_dependency(class_id.to_s.demodulize.underscore)
181
- if Object.const_defined?(class_id) then return Object.const_get(class_id) else raise LoadError end
182
- rescue LoadError => e
183
- raise NameError.new("uninitialized constant #{class_id}").copy_blame!(e)
184
- end
171
+ Object.send(:define_method, :require_dependency) { |file_name| Dependencies.depend_on(file_name) } unless Object.respond_to?(:require_dependency)
172
+ Object.send(:define_method, :require_association) { |file_name| Dependencies.associate_with(file_name) } unless Object.respond_to?(:require_association)
173
+
174
+ class Module #:nodoc:
175
+ # Use const_missing to autoload associations so we don't have to
176
+ # require_association when using single-table inheritance.
177
+ def const_missing(class_id)
178
+ if Object.const_defined?(:Controllers) and Object::Controllers.const_available?(class_id)
179
+ return Object::Controllers.const_get(class_id)
180
+ end
181
+
182
+ begin
183
+ require_dependency(class_id.to_s.demodulize.underscore)
184
+ if Object.const_defined?(class_id) then return Object.const_get(class_id) else raise LoadError end
185
+ rescue LoadError => e
186
+ raise NameError.new("uninitialized constant #{class_id}").copy_blame!(e)
185
187
  end
186
188
  end
189
+ end
187
190
 
191
+ class Object #:nodoc:
188
192
  def load(file, *extras)
189
- begin super(file, *extras)
190
- rescue Object => exception
191
- exception.blame_file! file
192
- raise
193
- end
193
+ super(file, *extras)
194
+ rescue Object => exception
195
+ exception.blame_file! file
196
+ raise
194
197
  end
195
198
 
196
199
  def require(file, *extras)
197
- begin super(file, *extras)
198
- rescue Object => exception
199
- exception.blame_file! file
200
- raise
201
- end
200
+ super(file, *extras)
201
+ rescue Object => exception
202
+ exception.blame_file! file
203
+ raise
202
204
  end
203
205
  end
204
206
 
205
207
  # Add file-blaming to exceptions
206
- class Exception
208
+ class Exception #:nodoc:
207
209
  def blame_file!(file)
208
210
  (@blamed_files ||= []).unshift file
209
211
  end
@@ -5,18 +5,24 @@ module Inflector
5
5
 
6
6
  def pluralize(word)
7
7
  result = word.to_s.dup
8
- plural_rules.each do |(rule, replacement)|
9
- break if result.gsub!(rule, replacement)
8
+
9
+ if uncountable_words.include?(result.downcase)
10
+ result
11
+ else
12
+ plural_rules.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
13
+ result
10
14
  end
11
- return result
12
15
  end
13
16
 
14
17
  def singularize(word)
15
18
  result = word.to_s.dup
16
- singular_rules.each do |(rule, replacement)|
17
- break if result.gsub!(rule, replacement)
19
+
20
+ if uncountable_words.include?(result.downcase)
21
+ result
22
+ else
23
+ singular_rules.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
24
+ result
18
25
  end
19
- return result
20
26
  end
21
27
 
22
28
  def camelize(lower_case_and_underscored_word)
@@ -24,7 +30,7 @@ module Inflector
24
30
  end
25
31
 
26
32
  def underscore(camel_cased_word)
27
- camel_cased_word.to_s.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z])/,'\1_\2').gsub(/([a-z])([A-Z])/,'\1_\2').downcase
33
+ camel_cased_word.to_s.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').downcase
28
34
  end
29
35
 
30
36
  def humanize(lower_case_and_underscored_word)
@@ -55,42 +61,64 @@ module Inflector
55
61
  end
56
62
 
57
63
  private
64
+ def uncountable_words #:doc
65
+ %w( equipment information rice money species series fish )
66
+ end
67
+
58
68
  def plural_rules #:doc:
59
69
  [
60
- [/(fish)$/i, '\1\2'], # fish
61
- [/(x|ch|ss|sh)$/i, '\1es'], # search, switch, fix, box, process, address
62
- [/(series)$/i, '\1\2'],
70
+ [/^(ox)$/i, '\1\2en'], # ox
71
+ [/([m|l])ouse$/i, '\1ice'], # mouse, louse
72
+ [/(matr|vert)ix|ex$/i, '\1ices'], # matrix, vertex, index
73
+ [/(x|ch|ss|sh)$/i, '\1es'], # search, switch, fix, box, process, address
63
74
  [/([^aeiouy]|qu)ies$/i, '\1y'],
64
- [/([^aeiouy]|qu)y$/i, '\1ies'], # query, ability, agency
75
+ [/([^aeiouy]|qu)y$/i, '\1ies'], # query, ability, agency
76
+ [/(hive)$/i, '\1s'], # archive, hive
65
77
  [/(?:([^f])fe|([lr])f)$/i, '\1\2ves'], # half, safe, wife
66
- [/sis$/i, 'ses'], # basis, diagnosis
67
- [/([ti])um$/i, '\1a'], # datum, medium
68
- [/(p)erson$/i, '\1\2eople'], # person, salesperson
69
- [/(m)an$/i, '\1\2en'], # man, woman, spokesman
70
- [/(c)hild$/i, '\1\2hildren'], # child
71
- [/s$/i, 's'], # no change (compatibility)
78
+ [/sis$/i, 'ses'], # basis, diagnosis
79
+ [/([ti])um$/i, '\1a'], # datum, medium
80
+ [/(p)erson$/i, '\1eople'], # person, salesperson
81
+ [/(m)an$/i, '\1en'], # man, woman, spokesman
82
+ [/(c)hild$/i, '\1hildren'], # child
83
+ [/(buffal|tomat)o$/i, '\1\2oes'], # buffalo, tomato
84
+ [/(bu)s$/i, '\1\2ses'], # bus
85
+ [/(alias)/i, '\1es'], # alias
86
+ [/(octop|vir)us$/i, '\1i'], # octopus, virus - virus has no defined plural (according to Latin/dictionary.com), but viri is better than viruses/viruss
87
+ [/(ax|cri|test)is$/i, '\1es'], # axis, crisis
88
+ [/s$/i, 's'], # no change (compatibility)
72
89
  [/$/, 's']
73
90
  ]
74
91
  end
75
92
 
76
93
  def singular_rules #:doc:
77
94
  [
78
- [/(f)ish$/i, '\1\2ish'],
95
+ [/(matr)ices$/i, '\1ix'],
96
+ [/(vert)ices$/i, '\1ex'],
97
+ [/^(ox)en/i, '\1'],
98
+ [/(alias)es$/i, '\1'],
99
+ [/([octop|vir])i$/i, '\1us'],
100
+ [/(cris|ax|test)es$/i, '\1is'],
101
+ [/(shoe)s$/i, '\1'],
102
+ [/(o)es$/i, '\1'],
103
+ [/(bus)es$/i, '\1'],
104
+ [/([m|l])ice$/i, '\1ouse'],
79
105
  [/(x|ch|ss|sh)es$/i, '\1'],
80
106
  [/(m)ovies$/i, '\1\2ovie'],
81
107
  [/(s)eries$/i, '\1\2eries'],
82
108
  [/([^aeiouy]|qu)ies$/i, '\1y'],
83
109
  [/([lr])ves$/i, '\1f'],
84
110
  [/(tive)s$/i, '\1'],
111
+ [/(hive)s$/i, '\1'],
85
112
  [/([^f])ves$/i, '\1fe'],
113
+ [/(^analy)ses$/i, '\1sis'],
86
114
  [/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '\1\2sis'],
87
115
  [/([ti])a$/i, '\1um'],
88
116
  [/(p)eople$/i, '\1\2erson'],
89
- [/(m)en$/i, '\1\2an'],
117
+ [/(m)en$/i, '\1an'],
90
118
  [/(s)tatus$/i, '\1\2tatus'],
91
119
  [/(c)hildren$/i, '\1\2hild'],
92
120
  [/(n)ews$/i, '\1\2ews'],
93
121
  [/s$/i, '']
94
122
  ]
95
123
  end
96
- end
124
+ end
@@ -0,0 +1,46 @@
1
+ # Extensions to nil which allow for more helpful error messages for
2
+ # people who are new to rails.
3
+ #
4
+ # The aim is to ensure that when users pass nil to methods where that isn't
5
+ # appropriate, instead of NoMethodError and the name of some method used
6
+ # by the framework users will see a message explaining what type of object
7
+ # was expected.
8
+
9
+ class NilClass
10
+ WHINERS = [ ::ActiveRecord::Base, ::Array ]
11
+
12
+ @@method_class_map = Hash.new
13
+
14
+ WHINERS.each do |klass|
15
+ methods = klass.public_instance_methods - public_instance_methods
16
+ methods.each do |method|
17
+ @@method_class_map[method.to_sym] = klass
18
+ end
19
+ end
20
+
21
+ def id
22
+ raise RuntimeError, "Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id", caller
23
+ end
24
+
25
+ private
26
+ def method_missing(method, *args, &block)
27
+ if @@method_class_map.include?(method)
28
+ raise_nil_warning_for @@method_class_map[method], caller
29
+ else
30
+ super
31
+ end
32
+ end
33
+
34
+ def raise_nil_warning_for(klass, with_caller = nil)
35
+ raise NoMethodError, NIL_WARNING_MESSAGE % klass, with_caller || caller
36
+ end
37
+
38
+ NIL_WARNING_MESSAGE = <<-end_message unless const_defined?(:NIL_WARNING_MESSAGE)
39
+ WARNING: You have a nil object when you probably didn't expect it! Odds are you
40
+ want an instance of %s instead.
41
+
42
+ Look in the callstack to see where you're working with an object that could be nil.
43
+ Investigate your methods and make sure the object is what you expect!
44
+ end_message
45
+ end
46
+
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.8.8
2
+ rubygems_version: 0.8.10
3
3
  specification_version: 1
4
4
  name: activesupport
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.0.4
7
- date: 2005-04-19
6
+ version: 1.1.0
7
+ date: 2005-07-06
8
8
  summary: Support and utility classes used by the Rails framework.
9
9
  require_paths:
10
10
  - lib
@@ -42,6 +42,11 @@ files:
42
42
  - lib/active_support/misc.rb
43
43
  - lib/active_support/module_attribute_accessors.rb
44
44
  - lib/active_support/values
45
+ - lib/active_support/whiny_nil.rb
46
+ - lib/active_support/core_ext/array
47
+ - lib/active_support/core_ext/array.rb
48
+ - lib/active_support/core_ext/cgi
49
+ - lib/active_support/core_ext/cgi.rb
45
50
  - lib/active_support/core_ext/date
46
51
  - lib/active_support/core_ext/date.rb
47
52
  - lib/active_support/core_ext/fixnum
@@ -57,6 +62,8 @@ files:
57
62
  - lib/active_support/core_ext/string.rb
58
63
  - lib/active_support/core_ext/time
59
64
  - lib/active_support/core_ext/time.rb
65
+ - lib/active_support/core_ext/array/to_param.rb
66
+ - lib/active_support/core_ext/cgi/escape_skipping_slashes.rb
60
67
  - lib/active_support/core_ext/date/conversions.rb
61
68
  - lib/active_support/core_ext/fixnum/even_odd.rb
62
69
  - lib/active_support/core_ext/hash/indifferent_access.rb