activesupport 1.2.5 → 1.3.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 +163 -4
- data/lib/active_support.rb +8 -3
- data/lib/active_support/breakpoint.rb +1 -1
- data/lib/active_support/caching_tools.rb +62 -0
- data/lib/active_support/clean_logger.rb +3 -1
- data/lib/active_support/core_ext/array.rb +16 -0
- data/lib/active_support/core_ext/array/conversions.rb +18 -2
- data/lib/active_support/core_ext/blank.rb +14 -2
- data/lib/active_support/core_ext/class.rb +3 -0
- data/lib/active_support/core_ext/class/attribute_accessors.rb +44 -0
- data/lib/active_support/{class_inheritable_attributes.rb → core_ext/class/inheritable_attributes.rb} +2 -4
- data/lib/active_support/core_ext/class/removal.rb +24 -0
- data/lib/active_support/core_ext/date/conversions.rb +2 -0
- data/lib/active_support/core_ext/enumerable.rb +23 -1
- data/lib/active_support/core_ext/exception.rb +0 -1
- data/lib/active_support/core_ext/hash.rb +4 -0
- data/lib/active_support/core_ext/hash/conversions.rb +44 -0
- data/lib/active_support/core_ext/hash/diff.rb +11 -0
- data/lib/active_support/core_ext/hash/indifferent_access.rb +23 -4
- data/lib/active_support/core_ext/integer/inflections.rb +1 -1
- data/lib/active_support/core_ext/kernel.rb +4 -79
- data/lib/active_support/core_ext/kernel/agnostics.rb +11 -0
- data/lib/active_support/core_ext/kernel/daemonizing.rb +15 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +51 -0
- data/lib/active_support/core_ext/kernel/requires.rb +24 -0
- data/lib/active_support/core_ext/logger.rb +16 -0
- data/lib/active_support/core_ext/module.rb +5 -0
- data/lib/active_support/core_ext/module/attribute_accessors.rb +44 -0
- data/lib/active_support/core_ext/module/delegation.rb +16 -0
- data/lib/active_support/core_ext/module/inclusion.rb +11 -0
- data/lib/active_support/core_ext/module/introspection.rb +21 -0
- data/lib/active_support/core_ext/module/loading.rb +13 -0
- data/lib/active_support/core_ext/numeric/time.rb +14 -1
- data/lib/active_support/core_ext/object.rb +2 -0
- data/lib/active_support/core_ext/object/extending.rb +47 -0
- data/lib/active_support/core_ext/object/misc.rb +34 -0
- data/lib/active_support/core_ext/proc.rb +12 -0
- data/lib/active_support/core_ext/string.rb +2 -0
- data/lib/active_support/core_ext/string/access.rb +2 -2
- data/lib/active_support/core_ext/string/inflections.rb +10 -3
- data/lib/active_support/core_ext/string/iterators.rb +17 -0
- data/lib/active_support/core_ext/symbol.rb +5 -0
- data/lib/active_support/core_ext/time/calculations.rb +15 -0
- data/lib/active_support/core_ext/time/conversions.rb +1 -0
- data/lib/active_support/dependencies.rb +81 -159
- data/lib/active_support/inflections.rb +48 -48
- data/lib/active_support/inflector.rb +17 -5
- data/lib/active_support/json.rb +37 -0
- data/lib/active_support/json/encoders.rb +25 -0
- data/lib/active_support/json/encoders/core.rb +65 -0
- data/lib/active_support/option_merger.rb +25 -0
- data/lib/active_support/ordered_options.rb +23 -11
- data/lib/active_support/reloadable.rb +30 -0
- data/lib/active_support/vendor/builder.rb +13 -0
- data/lib/active_support/vendor/builder/blankslate.rb +53 -0
- data/lib/active_support/vendor/builder/xmlbase.rb +143 -0
- data/lib/active_support/vendor/builder/xmlevents.rb +63 -0
- data/lib/active_support/vendor/builder/xmlmarkup.rb +308 -0
- data/lib/active_support/version.rb +2 -2
- metadata +113 -69
- data/lib/active_support/class_attribute_accessors.rb +0 -57
- data/lib/active_support/core_ext/object_and_class.rb +0 -44
- data/lib/active_support/module_attribute_accessors.rb +0 -57
@@ -0,0 +1,11 @@
|
|
1
|
+
class Module
|
2
|
+
def included_in_classes
|
3
|
+
classes = []
|
4
|
+
ObjectSpace.each_object(Class) { |k| classes << k if k.included_modules.include?(self) }
|
5
|
+
|
6
|
+
classes.reverse.inject([]) do |unique_classes, klass|
|
7
|
+
unique_classes << klass unless unique_classes.collect { |k| k.to_s }.include?(klass.to_s)
|
8
|
+
unique_classes
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class Module
|
2
|
+
# Return the module which contains this one; if this is a root module, such as
|
3
|
+
# +::MyModule+, then Object is returned.
|
4
|
+
def parent
|
5
|
+
parent_name = name.split('::')[0..-2] * '::'
|
6
|
+
parent_name.empty? ? Object : parent_name.constantize
|
7
|
+
end
|
8
|
+
|
9
|
+
# Return all the parents of this module, ordered from nested outwards. The
|
10
|
+
# receiver is not contained within the result.
|
11
|
+
def parents
|
12
|
+
parents = []
|
13
|
+
parts = name.split('::')[0..-2]
|
14
|
+
until parts.empty?
|
15
|
+
parents << (parts * '::').constantize
|
16
|
+
parts.pop
|
17
|
+
end
|
18
|
+
parents << Object unless parents.include? Object
|
19
|
+
parents
|
20
|
+
end
|
21
|
+
end
|
@@ -1,8 +1,21 @@
|
|
1
1
|
module ActiveSupport #:nodoc:
|
2
2
|
module CoreExtensions #:nodoc:
|
3
3
|
module Numeric #:nodoc:
|
4
|
-
# Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years
|
4
|
+
# Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years.
|
5
|
+
#
|
6
|
+
# If you need precise date calculations that doesn't just treat months as 30 days, then have
|
7
|
+
# a look at Time#advance.
|
8
|
+
#
|
9
|
+
# Some of these methods are approximations, Ruby's core
|
10
|
+
# Date[http://stdlib.rubyonrails.org/libdoc/date/rdoc/index.html] and
|
11
|
+
# Time[http://stdlib.rubyonrails.org/libdoc/time/rdoc/index.html] should be used for precision
|
12
|
+
# date and time arithmetic
|
5
13
|
module Time
|
14
|
+
def seconds
|
15
|
+
self
|
16
|
+
end
|
17
|
+
alias :second :seconds
|
18
|
+
|
6
19
|
def minutes
|
7
20
|
self * 60
|
8
21
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class Object #:nodoc:
|
2
|
+
def remove_subclasses_of(*superclasses)
|
3
|
+
Class.remove_class(*subclasses_of(*superclasses))
|
4
|
+
end
|
5
|
+
|
6
|
+
def subclasses_of(*superclasses)
|
7
|
+
subclasses = []
|
8
|
+
ObjectSpace.each_object(Class) do |k|
|
9
|
+
next if # Exclude this class if
|
10
|
+
(k.ancestors & superclasses).empty? || # It's not a subclass of our supers
|
11
|
+
superclasses.include?(k) || # It *is* one of the supers
|
12
|
+
eval("! defined?(::#{k})") || # It's not defined.
|
13
|
+
eval("::#{k}").object_id != k.object_id
|
14
|
+
subclasses << k
|
15
|
+
end
|
16
|
+
subclasses
|
17
|
+
end
|
18
|
+
|
19
|
+
def extended_by
|
20
|
+
ancestors = class << self; ancestors end
|
21
|
+
ancestors.select { |mod| mod.class == Module } - [ Object, Kernel ]
|
22
|
+
end
|
23
|
+
|
24
|
+
def copy_instance_variables_from(object, exclude = [])
|
25
|
+
exclude += object.protected_instance_variables if object.respond_to? :protected_instance_variables
|
26
|
+
|
27
|
+
instance_variables = object.instance_variables - exclude.map { |name| name.to_s }
|
28
|
+
instance_variables.each { |name| instance_variable_set(name, object.instance_variable_get(name)) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def extend_with_included_modules_from(object)
|
32
|
+
object.extended_by.each { |mod| extend mod }
|
33
|
+
end
|
34
|
+
|
35
|
+
def instance_values
|
36
|
+
instance_variables.inject({}) do |values, name|
|
37
|
+
values[name[1..-1]] = instance_variable_get(name)
|
38
|
+
values
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
unless defined? instance_exec # 1.9
|
43
|
+
def instance_exec(*arguments, &block)
|
44
|
+
block.bind(self)[*arguments]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Object #:nodoc:
|
2
|
+
# A Ruby-ized realization of the K combinator, courtesy of Mikael Brockman.
|
3
|
+
#
|
4
|
+
# def foo
|
5
|
+
# returning values = [] do
|
6
|
+
# values << 'bar'
|
7
|
+
# values << 'baz'
|
8
|
+
# end
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# foo # => ['bar', 'baz']
|
12
|
+
#
|
13
|
+
# def foo
|
14
|
+
# returning [] do |values|
|
15
|
+
# values << 'bar'
|
16
|
+
# values << 'baz'
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# foo # => ['bar', 'baz']
|
21
|
+
#
|
22
|
+
def returning(value)
|
23
|
+
yield(value)
|
24
|
+
value
|
25
|
+
end
|
26
|
+
|
27
|
+
def with_options(options)
|
28
|
+
yield ActiveSupport::OptionMerger.new(self, options)
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_json
|
32
|
+
ActiveSupport::JSON.encode(self)
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Proc #:nodoc:
|
2
|
+
def bind(object)
|
3
|
+
block, time = self, Time.now
|
4
|
+
(class << object; self end).class_eval do
|
5
|
+
method_name = "__bind_#{time.to_i}_#{time.usec}"
|
6
|
+
define_method(method_name, &block)
|
7
|
+
method = instance_method(method_name)
|
8
|
+
remove_method(method_name)
|
9
|
+
method
|
10
|
+
end.bind(object)
|
11
|
+
end
|
12
|
+
end
|
@@ -2,10 +2,12 @@ require File.dirname(__FILE__) + '/string/inflections'
|
|
2
2
|
require File.dirname(__FILE__) + '/string/conversions'
|
3
3
|
require File.dirname(__FILE__) + '/string/access'
|
4
4
|
require File.dirname(__FILE__) + '/string/starts_ends_with'
|
5
|
+
require File.dirname(__FILE__) + '/string/iterators'
|
5
6
|
|
6
7
|
class String #:nodoc:
|
7
8
|
include ActiveSupport::CoreExtensions::String::Access
|
8
9
|
include ActiveSupport::CoreExtensions::String::Conversions
|
9
10
|
include ActiveSupport::CoreExtensions::String::Inflections
|
10
11
|
include ActiveSupport::CoreExtensions::String::StartsEndsWith
|
12
|
+
include ActiveSupport::CoreExtensions::String::Iterators
|
11
13
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/../../inflector'
|
1
|
+
require File.dirname(__FILE__) + '/../../inflector' unless defined? Inflector
|
2
2
|
module ActiveSupport #:nodoc:
|
3
3
|
module CoreExtensions #:nodoc:
|
4
4
|
module String #:nodoc:
|
@@ -12,8 +12,11 @@ module ActiveSupport #:nodoc:
|
|
12
12
|
Inflector.singularize(self)
|
13
13
|
end
|
14
14
|
|
15
|
-
def camelize
|
16
|
-
|
15
|
+
def camelize(first_letter = :upper)
|
16
|
+
case first_letter
|
17
|
+
when :upper then Inflector.camelize(self, true)
|
18
|
+
when :lower then Inflector.camelize(self, false)
|
19
|
+
end
|
17
20
|
end
|
18
21
|
alias_method :camelcase, :camelize
|
19
22
|
|
@@ -26,6 +29,10 @@ module ActiveSupport #:nodoc:
|
|
26
29
|
Inflector.underscore(self)
|
27
30
|
end
|
28
31
|
|
32
|
+
def dasherize
|
33
|
+
Inflector.dasherize(self)
|
34
|
+
end
|
35
|
+
|
29
36
|
def demodulize
|
30
37
|
Inflector.demodulize(self)
|
31
38
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'strscan'
|
2
|
+
|
3
|
+
module ActiveSupport #:nodoc:
|
4
|
+
module CoreExtensions #:nodoc:
|
5
|
+
module String #:nodoc:
|
6
|
+
# Custom string iterators
|
7
|
+
module Iterators
|
8
|
+
# Yields a single-character string for each character in the string.
|
9
|
+
# When $KCODE = 'UTF8', multi-byte characters are yielded appropriately.
|
10
|
+
def each_char
|
11
|
+
scanner, char = StringScanner.new(self), /./mu
|
12
|
+
loop { yield(scanner.scan(char) || break) }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -44,6 +44,15 @@ module ActiveSupport #:nodoc:
|
|
44
44
|
options[:usec] || ((options[:hour] || options[:min] || options[:sec]) ? 0 : self.usec)
|
45
45
|
)
|
46
46
|
end
|
47
|
+
|
48
|
+
# Uses Date to provide precise Time calculations for years, months, and days. The +options+ parameter takes a hash with
|
49
|
+
# any of these keys: :months, :days, :years.
|
50
|
+
def advance(options)
|
51
|
+
d = ::Date.new(year + (options.delete(:years) || 0), month, day)
|
52
|
+
d = d >> options.delete(:months) if options[:months]
|
53
|
+
d = d + options.delete(:days) if options[:days]
|
54
|
+
change(options.merge(:year => d.year, :month => d.month, :mday => d.day))
|
55
|
+
end
|
47
56
|
|
48
57
|
# Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension
|
49
58
|
# Do not use this method in combination with x.months, use months_ago instead!
|
@@ -152,6 +161,12 @@ module ActiveSupport #:nodoc:
|
|
152
161
|
change(:mday => last_day,:hour => 0, :min => 0, :sec => 0, :usec => 0)
|
153
162
|
end
|
154
163
|
alias :at_end_of_month :end_of_month
|
164
|
+
|
165
|
+
# Returns a new Time representing the start of the quarter (1st of january, april, july, october, 0:00)
|
166
|
+
def beginning_of_quarter
|
167
|
+
beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= self.month })
|
168
|
+
end
|
169
|
+
alias :at_beginning_of_quarter :beginning_of_quarter
|
155
170
|
|
156
171
|
# Returns a new Time representing the start of the year (1st of january, 0:00)
|
157
172
|
def beginning_of_year
|
@@ -1,176 +1,72 @@
|
|
1
|
-
require
|
1
|
+
require 'set'
|
2
|
+
require File.dirname(__FILE__) + '/core_ext/module/attribute_accessors'
|
2
3
|
require File.dirname(__FILE__) + '/core_ext/load_error'
|
4
|
+
require File.dirname(__FILE__) + '/core_ext/kernel'
|
3
5
|
|
4
6
|
module Dependencies #:nodoc:
|
5
7
|
extend self
|
6
8
|
|
7
|
-
|
9
|
+
# Should we turn on Ruby warnings on the first load of dependent files?
|
10
|
+
mattr_accessor :warnings_on_first_load
|
11
|
+
self.warnings_on_first_load = false
|
12
|
+
|
13
|
+
# All files ever loaded.
|
14
|
+
mattr_accessor :history
|
15
|
+
self.history = Set.new
|
16
|
+
|
17
|
+
# All files currently loaded.
|
8
18
|
mattr_accessor :loaded
|
19
|
+
self.loaded = Set.new
|
9
20
|
|
10
|
-
|
21
|
+
# Should we load files or require them?
|
11
22
|
mattr_accessor :mechanism
|
12
|
-
|
23
|
+
self.mechanism = :load
|
24
|
+
|
13
25
|
def load?
|
14
26
|
mechanism == :load
|
15
27
|
end
|
16
|
-
|
17
|
-
def depend_on(file_name, swallow_load_errors = false)
|
18
|
-
unless loaded.include?(file_name)
|
19
|
-
loaded << file_name
|
20
28
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
end
|
29
|
+
def depend_on(file_name, swallow_load_errors = false)
|
30
|
+
require_or_load(file_name)
|
31
|
+
rescue LoadError
|
32
|
+
raise unless swallow_load_errors
|
27
33
|
end
|
28
34
|
|
29
35
|
def associate_with(file_name)
|
30
36
|
depend_on(file_name, true)
|
31
37
|
end
|
32
|
-
|
38
|
+
|
33
39
|
def clear
|
34
|
-
|
40
|
+
loaded.clear
|
35
41
|
end
|
36
|
-
|
37
|
-
def require_or_load(file_name)
|
38
|
-
file_name = "#{file_name}.rb" unless ! load? || file_name[-3..-1] == '.rb'
|
39
|
-
load? ? load(file_name) : require(file_name)
|
40
|
-
end
|
41
|
-
|
42
|
-
def remove_subclasses_for(*classes)
|
43
|
-
Object.remove_subclasses_of(*classes)
|
44
|
-
end
|
45
|
-
|
46
|
-
# LoadingModules implement namespace-safe dynamic loading.
|
47
|
-
# They support automatic loading via const_missing, allowing contained items to be automatically
|
48
|
-
# loaded when required. No extra syntax is required, as expressions such as Controller::Admin::UserController
|
49
|
-
# load the relavent files automatically.
|
50
|
-
#
|
51
|
-
# Ruby-style modules are supported, as a folder named 'submodule' will load 'submodule.rb' when available.
|
52
|
-
class LoadingModule < Module #:nodoc:
|
53
|
-
attr_reader :path
|
54
|
-
attr_reader :root
|
55
|
-
|
56
|
-
class << self
|
57
|
-
def root(*load_paths)
|
58
|
-
RootLoadingModule.new(*load_paths)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def initialize(root, path=[])
|
63
|
-
@path = path.clone.freeze
|
64
|
-
@root = root
|
65
|
-
end
|
66
|
-
|
67
|
-
def root?() self.root == self end
|
68
|
-
def load_paths() self.root.load_paths end
|
69
|
-
|
70
|
-
# Load missing constants if possible.
|
71
|
-
def const_missing(name)
|
72
|
-
const_load!(name) ? const_get(name) : super(name)
|
73
|
-
end
|
74
|
-
|
75
|
-
# Load the controller class or a parent module.
|
76
|
-
def const_load!(name, file_name = nil)
|
77
|
-
file_name ||= 'application' if root? && name.to_s == 'ApplicationController'
|
78
|
-
path = self.path + [file_name || name]
|
79
|
-
|
80
|
-
load_paths.each do |load_path|
|
81
|
-
fs_path = load_path.filesystem_path(path)
|
82
|
-
next unless fs_path
|
83
|
-
|
84
|
-
case
|
85
|
-
when File.directory?(fs_path)
|
86
|
-
new_module = LoadingModule.new(self.root, self.path + [name])
|
87
|
-
self.const_set name, new_module
|
88
|
-
if self.root?
|
89
|
-
if Object.const_defined?(name)
|
90
|
-
msg = "Cannot load module #{name}: Object::#{name} is set to #{Object.const_get(name).inspect}"
|
91
|
-
raise NameError, msg
|
92
|
-
end
|
93
|
-
Object.const_set(name, new_module)
|
94
|
-
end
|
95
|
-
break
|
96
|
-
when File.file?(fs_path)
|
97
|
-
loaded_file = self.root.load_file!(fs_path)
|
98
|
-
|
99
|
-
# Import the loaded constant from Object provided we are the root node.
|
100
|
-
self.const_set(name, Object.const_get(name)) if self.root? && Object.const_defined?(name)
|
101
|
-
|
102
|
-
# Throw an error if we load the file but we don't find the Object we expect
|
103
|
-
if loaded_file and not self.const_defined?(name)
|
104
|
-
msg = "Already loaded file '#{fs_path}' but '#{name.to_s}' was not set, perhaps you need to rename '#{fs_path}'?"
|
105
|
-
raise LoadError, msg
|
106
|
-
end
|
107
|
-
break
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
self.const_defined?(name)
|
112
|
-
end
|
113
|
-
|
114
|
-
# Is this name present or loadable?
|
115
|
-
# This method is used by Routes to find valid controllers.
|
116
|
-
def const_available?(name)
|
117
|
-
self.const_defined?(name) || load_paths.any? {|lp| lp.filesystem_path(path + [name])}
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
class RootLoadingModule < LoadingModule #:nodoc:
|
122
|
-
attr_reader :load_paths
|
123
42
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
def root() self end
|
43
|
+
def require_or_load(file_name)
|
44
|
+
file_name = $1 if file_name =~ /^(.*)\.rb$/
|
45
|
+
return if loaded.include?(file_name)
|
129
46
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
def load_file!(file_path)
|
134
|
-
require_dependency(file_path)
|
135
|
-
end
|
47
|
+
# Record that we've seen this file *before* loading it to avoid an
|
48
|
+
# infinite loop with mutual dependencies.
|
49
|
+
loaded << file_name
|
136
50
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
def initialize(root) @root = root end
|
150
|
-
|
151
|
-
# Return nil if the path does not exist, or the path to a directory
|
152
|
-
# if the path leads to a module, or the path to a file if it leads to an object.
|
153
|
-
def filesystem_path(path, allow_module=true)
|
154
|
-
fs_path = [@root]
|
155
|
-
fs_path += path[0..-2].map {|name| const_name_to_module_name name}
|
156
|
-
|
157
|
-
if allow_module
|
158
|
-
result = File.join(fs_path, const_name_to_module_name(path.last))
|
159
|
-
return result if File.directory? result # Return the module path if one exists
|
51
|
+
if load?
|
52
|
+
begin
|
53
|
+
# Enable warnings iff this file has not been loaded before and
|
54
|
+
# warnings_on_first_load is set.
|
55
|
+
if !warnings_on_first_load or history.include?(file_name)
|
56
|
+
load "#{file_name}.rb"
|
57
|
+
else
|
58
|
+
enable_warnings { load "#{file_name}.rb" }
|
59
|
+
end
|
60
|
+
rescue
|
61
|
+
loaded.delete file_name
|
62
|
+
raise
|
160
63
|
end
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
File.file?(result) ? result : nil
|
165
|
-
end
|
166
|
-
|
167
|
-
def const_name_to_file_name(name)
|
168
|
-
name.to_s.underscore + '.rb'
|
64
|
+
else
|
65
|
+
require file_name
|
169
66
|
end
|
170
67
|
|
171
|
-
|
172
|
-
|
173
|
-
end
|
68
|
+
# Record history *after* loading so first load gets warnings.
|
69
|
+
history << file_name
|
174
70
|
end
|
175
71
|
end
|
176
72
|
|
@@ -181,27 +77,53 @@ Object.send(:define_method, :require_association) { |file_name| Dependencies.ass
|
|
181
77
|
class Module #:nodoc:
|
182
78
|
# Rename the original handler so we can chain it to the new one
|
183
79
|
alias :rails_original_const_missing :const_missing
|
184
|
-
|
80
|
+
|
185
81
|
# Use const_missing to autoload associations so we don't have to
|
186
82
|
# require_association when using single-table inheritance.
|
187
83
|
def const_missing(class_id)
|
188
|
-
if Object.const_defined?(:Controllers) and Object::Controllers.const_available?(class_id)
|
189
|
-
return Object::Controllers.const_get(class_id)
|
190
|
-
end
|
191
|
-
|
192
84
|
file_name = class_id.to_s.demodulize.underscore
|
85
|
+
file_path = as_load_path.empty? ? file_name : "#{as_load_path}/#{file_name}"
|
193
86
|
begin
|
194
|
-
require_dependency(
|
195
|
-
|
196
|
-
|
87
|
+
require_dependency(file_path)
|
88
|
+
brief_name = self == Object ? '' : "#{name}::"
|
89
|
+
raise NameError.new("uninitialized constant #{brief_name}#{class_id}") unless const_defined?(class_id)
|
90
|
+
return const_get(class_id)
|
197
91
|
rescue MissingSourceFile => e
|
198
|
-
#
|
199
|
-
raise unless e.is_missing?
|
92
|
+
# Re-raise the error if it does not concern the file we were trying to load.
|
93
|
+
raise unless e.is_missing? file_path
|
94
|
+
|
95
|
+
# Look for a directory in the load path that we ought to load.
|
96
|
+
if $LOAD_PATH.any? { |base| File.directory? "#{base}/#{file_path}" }
|
97
|
+
mod = Module.new
|
98
|
+
const_set class_id, mod # Create the new module
|
99
|
+
return mod
|
100
|
+
end
|
101
|
+
|
102
|
+
# Attempt to access the name from the parent, unless we don't have a valid
|
103
|
+
# parent, or the constant is already defined in the parent. If the latter
|
104
|
+
# is the case, then we are being queried via self::class_id, and we should
|
105
|
+
# avoid returning the constant from the parent if possible.
|
106
|
+
if parent && parent != self && ! parents.any? { |p| p.const_defined?(class_id) }
|
107
|
+
suppress(NameError) do
|
108
|
+
return parent.send(:const_missing, class_id)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
200
112
|
raise NameError.new("uninitialized constant #{class_id}").copy_blame!(e)
|
201
113
|
end
|
202
114
|
end
|
203
115
|
end
|
204
116
|
|
117
|
+
class Class
|
118
|
+
def const_missing(class_id)
|
119
|
+
if [Object, Kernel].include?(self) || parent == self
|
120
|
+
super
|
121
|
+
else
|
122
|
+
parent.send :const_missing, class_id
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
205
127
|
class Object #:nodoc:
|
206
128
|
def load(file, *extras)
|
207
129
|
super(file, *extras)
|
@@ -237,4 +159,4 @@ class Exception #:nodoc:
|
|
237
159
|
@blamed_files = exc.blamed_files.clone
|
238
160
|
self
|
239
161
|
end
|
240
|
-
end
|
162
|
+
end
|