monetra-ruby 0.0.6
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.
- data/Rakefile +35 -0
- data/lib/monetra.rb +239 -0
- data/lib/monetra/active_support.rb +42 -0
- data/lib/monetra/active_support/binding_of_caller.rb +84 -0
- data/lib/monetra/active_support/breakpoint.rb +523 -0
- data/lib/monetra/active_support/caching_tools.rb +62 -0
- data/lib/monetra/active_support/clean_logger.rb +38 -0
- data/lib/monetra/active_support/core_ext.rb +1 -0
- data/lib/monetra/active_support/core_ext/array.rb +7 -0
- data/lib/monetra/active_support/core_ext/array/conversions.rb +72 -0
- data/lib/monetra/active_support/core_ext/array/grouping.rb +46 -0
- data/lib/monetra/active_support/core_ext/bigdecimal.rb +3 -0
- data/lib/monetra/active_support/core_ext/bigdecimal/formatting.rb +7 -0
- data/lib/monetra/active_support/core_ext/blank.rb +50 -0
- data/lib/monetra/active_support/core_ext/cgi.rb +5 -0
- data/lib/monetra/active_support/core_ext/cgi/escape_skipping_slashes.rb +14 -0
- data/lib/monetra/active_support/core_ext/class.rb +3 -0
- data/lib/monetra/active_support/core_ext/class/attribute_accessors.rb +44 -0
- data/lib/monetra/active_support/core_ext/class/inheritable_attributes.rb +115 -0
- data/lib/monetra/active_support/core_ext/class/removal.rb +24 -0
- data/lib/monetra/active_support/core_ext/date.rb +6 -0
- data/lib/monetra/active_support/core_ext/date/conversions.rb +39 -0
- data/lib/monetra/active_support/core_ext/enumerable.rb +62 -0
- data/lib/monetra/active_support/core_ext/exception.rb +33 -0
- data/lib/monetra/active_support/core_ext/hash.rb +13 -0
- data/lib/monetra/active_support/core_ext/hash/conversions.rb +148 -0
- data/lib/monetra/active_support/core_ext/hash/diff.rb +11 -0
- data/lib/monetra/active_support/core_ext/hash/indifferent_access.rb +88 -0
- data/lib/monetra/active_support/core_ext/hash/keys.rb +53 -0
- data/lib/monetra/active_support/core_ext/hash/reverse_merge.rb +25 -0
- data/lib/monetra/active_support/core_ext/integer.rb +7 -0
- data/lib/monetra/active_support/core_ext/integer/even_odd.rb +24 -0
- data/lib/monetra/active_support/core_ext/integer/inflections.rb +15 -0
- data/lib/monetra/active_support/core_ext/kernel.rb +4 -0
- data/lib/monetra/active_support/core_ext/kernel/agnostics.rb +11 -0
- data/lib/monetra/active_support/core_ext/kernel/daemonizing.rb +15 -0
- data/lib/monetra/active_support/core_ext/kernel/reporting.rb +51 -0
- data/lib/monetra/active_support/core_ext/kernel/requires.rb +24 -0
- data/lib/monetra/active_support/core_ext/load_error.rb +38 -0
- data/lib/monetra/active_support/core_ext/logger.rb +16 -0
- data/lib/monetra/active_support/core_ext/module.rb +7 -0
- data/lib/monetra/active_support/core_ext/module/aliasing.rb +57 -0
- data/lib/monetra/active_support/core_ext/module/attr_internal.rb +31 -0
- data/lib/monetra/active_support/core_ext/module/attribute_accessors.rb +44 -0
- data/lib/monetra/active_support/core_ext/module/delegation.rb +41 -0
- data/lib/monetra/active_support/core_ext/module/inclusion.rb +11 -0
- data/lib/monetra/active_support/core_ext/module/introspection.rb +21 -0
- data/lib/monetra/active_support/core_ext/module/loading.rb +13 -0
- data/lib/monetra/active_support/core_ext/name_error.rb +20 -0
- data/lib/monetra/active_support/core_ext/numeric.rb +7 -0
- data/lib/monetra/active_support/core_ext/numeric/bytes.rb +44 -0
- data/lib/monetra/active_support/core_ext/numeric/time.rb +72 -0
- data/lib/monetra/active_support/core_ext/object.rb +2 -0
- data/lib/monetra/active_support/core_ext/object/extending.rb +47 -0
- data/lib/monetra/active_support/core_ext/object/misc.rb +34 -0
- data/lib/monetra/active_support/core_ext/pathname.rb +7 -0
- data/lib/monetra/active_support/core_ext/pathname/clean_within.rb +14 -0
- data/lib/monetra/active_support/core_ext/proc.rb +12 -0
- data/lib/monetra/active_support/core_ext/range.rb +5 -0
- data/lib/monetra/active_support/core_ext/range/conversions.rb +21 -0
- data/lib/monetra/active_support/core_ext/string.rb +13 -0
- data/lib/monetra/active_support/core_ext/string/access.rb +58 -0
- data/lib/monetra/active_support/core_ext/string/conversions.rb +19 -0
- data/lib/monetra/active_support/core_ext/string/inflections.rb +153 -0
- data/lib/monetra/active_support/core_ext/string/iterators.rb +17 -0
- data/lib/monetra/active_support/core_ext/string/starts_ends_with.rb +20 -0
- data/lib/monetra/active_support/core_ext/symbol.rb +12 -0
- data/lib/monetra/active_support/core_ext/time.rb +7 -0
- data/lib/monetra/active_support/core_ext/time/calculations.rb +188 -0
- data/lib/monetra/active_support/core_ext/time/conversions.rb +36 -0
- data/lib/monetra/active_support/dependencies.rb +187 -0
- data/lib/monetra/active_support/deprecation.rb +106 -0
- data/lib/monetra/active_support/inflections.rb +53 -0
- data/lib/monetra/active_support/inflector.rb +179 -0
- data/lib/monetra/active_support/json.rb +37 -0
- data/lib/monetra/active_support/json/encoders.rb +25 -0
- data/lib/monetra/active_support/json/encoders/core.rb +65 -0
- data/lib/monetra/active_support/option_merger.rb +25 -0
- data/lib/monetra/active_support/ordered_options.rb +50 -0
- data/lib/monetra/active_support/reloadable.rb +30 -0
- data/lib/monetra/active_support/values/time_zone.rb +180 -0
- data/lib/monetra/active_support/vendor/builder.rb +13 -0
- data/lib/monetra/active_support/vendor/builder/blankslate.rb +63 -0
- data/lib/monetra/active_support/vendor/builder/xchar.rb +112 -0
- data/lib/monetra/active_support/vendor/builder/xmlbase.rb +145 -0
- data/lib/monetra/active_support/vendor/builder/xmlevents.rb +63 -0
- data/lib/monetra/active_support/vendor/builder/xmlmarkup.rb +328 -0
- data/lib/monetra/active_support/vendor/flexmock.rb +84 -0
- data/lib/monetra/active_support/vendor/xml_simple.rb +1019 -0
- data/lib/monetra/active_support/version.rb +9 -0
- data/lib/monetra/active_support/whiny_nil.rb +38 -0
- data/test/test.rb +21 -0
- metadata +167 -0
|
@@ -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
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module ActiveSupport #:nodoc:
|
|
2
|
+
module CoreExtensions #:nodoc:
|
|
3
|
+
module String #:nodoc:
|
|
4
|
+
# Additional string tests.
|
|
5
|
+
module StartsEndsWith
|
|
6
|
+
# Does the string start with the specified +prefix+?
|
|
7
|
+
def starts_with?(prefix)
|
|
8
|
+
prefix = prefix.to_s
|
|
9
|
+
self[0, prefix.length] == prefix
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Does the string end with the specified +suffix+?
|
|
13
|
+
def ends_with?(suffix)
|
|
14
|
+
suffix = suffix.to_s
|
|
15
|
+
self[-suffix.length, suffix.length] == suffix
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class Symbol
|
|
2
|
+
# Turns the symbol into a simple proc, which is especially useful for enumerations. Examples:
|
|
3
|
+
#
|
|
4
|
+
# # The same as people.collect { |p| p.name }
|
|
5
|
+
# people.collect(&:name)
|
|
6
|
+
#
|
|
7
|
+
# # The same as people.select { |p| p.manager? }.collect { |p| p.salary }
|
|
8
|
+
# people.select(&:manager?).collect(&:salary)
|
|
9
|
+
def to_proc
|
|
10
|
+
Proc.new { |*args| args.shift.__send__(self, *args) }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
module ActiveSupport #:nodoc:
|
|
2
|
+
module CoreExtensions #:nodoc:
|
|
3
|
+
module Time #:nodoc:
|
|
4
|
+
# Enables the use of time calculations within Time itself
|
|
5
|
+
module Calculations
|
|
6
|
+
def self.included(base) #:nodoc:
|
|
7
|
+
base.extend(ClassMethods)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module ClassMethods
|
|
11
|
+
# Return the number of days in the given month. If a year is given,
|
|
12
|
+
# February will return the correct number of days for leap years.
|
|
13
|
+
# Otherwise, this method will always report February as having 28
|
|
14
|
+
# days.
|
|
15
|
+
def days_in_month(month, year=nil)
|
|
16
|
+
if month == 2
|
|
17
|
+
!year.nil? && (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)) ? 29 : 28
|
|
18
|
+
elsif month <= 7
|
|
19
|
+
month % 2 == 0 ? 30 : 31
|
|
20
|
+
else
|
|
21
|
+
month % 2 == 0 ? 31 : 30
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Seconds since midnight: Time.now.seconds_since_midnight
|
|
27
|
+
def seconds_since_midnight
|
|
28
|
+
self.hour.hours + self.min.minutes + self.sec + (self.usec/1.0e+6)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Returns a new Time where one or more of the elements have been changed according to the +options+ parameter. The time options
|
|
32
|
+
# (hour, minute, sec, usec) reset cascadingly, so if only the hour is passed, then minute, sec, and usec is set to 0. If the hour and
|
|
33
|
+
# minute is passed, then sec and usec is set to 0.
|
|
34
|
+
def change(options)
|
|
35
|
+
::Time.send(
|
|
36
|
+
self.utc? ? :utc : :local,
|
|
37
|
+
options[:year] || self.year,
|
|
38
|
+
options[:month] || self.month,
|
|
39
|
+
options[:mday] || self.mday,
|
|
40
|
+
options[:hour] || self.hour,
|
|
41
|
+
options[:min] || (options[:hour] ? 0 : self.min),
|
|
42
|
+
options[:sec] || ((options[:hour] || options[:min]) ? 0 : self.sec),
|
|
43
|
+
options[:usec] || ((options[:hour] || options[:min] || options[:sec]) ? 0 : self.usec)
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Uses Date to provide precise Time calculations for years, months, and days. The +options+ parameter takes a hash with
|
|
48
|
+
# any of these keys: :months, :days, :years.
|
|
49
|
+
def advance(options)
|
|
50
|
+
d = ::Date.new(year + (options.delete(:years) || 0), month, day)
|
|
51
|
+
d = d >> options.delete(:months) if options[:months]
|
|
52
|
+
d = d + options.delete(:days) if options[:days]
|
|
53
|
+
change(options.merge(:year => d.year, :month => d.month, :mday => d.day))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension
|
|
57
|
+
# Do not use this method in combination with x.months, use months_ago instead!
|
|
58
|
+
def ago(seconds)
|
|
59
|
+
seconds.until(self)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Returns a new Time representing the time a number of seconds since the instance time, this is basically a wrapper around
|
|
63
|
+
#the Numeric extension. Do not use this method in combination with x.months, use months_since instead!
|
|
64
|
+
def since(seconds)
|
|
65
|
+
seconds.since(self)
|
|
66
|
+
end
|
|
67
|
+
alias :in :since
|
|
68
|
+
|
|
69
|
+
# Returns a new Time representing the time a number of specified months ago
|
|
70
|
+
def months_ago(months)
|
|
71
|
+
months_since(-months)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def months_since(months)
|
|
75
|
+
year, month, mday = self.year, self.month, self.mday
|
|
76
|
+
|
|
77
|
+
month += months
|
|
78
|
+
|
|
79
|
+
# in case months is negative
|
|
80
|
+
while month < 1
|
|
81
|
+
month += 12
|
|
82
|
+
year -= 1
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# in case months is positive
|
|
86
|
+
while month > 12
|
|
87
|
+
month -= 12
|
|
88
|
+
year += 1
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
max = ::Time.days_in_month(month, year)
|
|
92
|
+
mday = max if mday > max
|
|
93
|
+
|
|
94
|
+
change(:year => year, :month => month, :mday => mday)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Returns a new Time representing the time a number of specified years ago
|
|
98
|
+
def years_ago(years)
|
|
99
|
+
change(:year => self.year - years)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def years_since(years)
|
|
103
|
+
change(:year => self.year + years)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Short-hand for years_ago(1)
|
|
107
|
+
def last_year
|
|
108
|
+
years_ago(1)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Short-hand for years_since(1)
|
|
112
|
+
def next_year
|
|
113
|
+
years_since(1)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
# Short-hand for months_ago(1)
|
|
118
|
+
def last_month
|
|
119
|
+
months_ago(1)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Short-hand for months_since(1)
|
|
123
|
+
def next_month
|
|
124
|
+
months_since(1)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Returns a new Time representing the "start" of this week (Monday, 0:00)
|
|
128
|
+
def beginning_of_week
|
|
129
|
+
days_to_monday = self.wday!=0 ? self.wday-1 : 6
|
|
130
|
+
(self - days_to_monday.days).midnight
|
|
131
|
+
end
|
|
132
|
+
alias :monday :beginning_of_week
|
|
133
|
+
alias :at_beginning_of_week :beginning_of_week
|
|
134
|
+
|
|
135
|
+
# Returns a new Time representing the start of the given day in next week (default is Monday).
|
|
136
|
+
def next_week(day = :monday)
|
|
137
|
+
days_into_week = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6}
|
|
138
|
+
since(1.week).beginning_of_week.since(days_into_week[day].day).change(:hour => 0)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Returns a new Time representing the start of the day (0:00)
|
|
142
|
+
def beginning_of_day
|
|
143
|
+
(self - self.seconds_since_midnight).change(:usec => 0)
|
|
144
|
+
end
|
|
145
|
+
alias :midnight :beginning_of_day
|
|
146
|
+
alias :at_midnight :beginning_of_day
|
|
147
|
+
alias :at_beginning_of_day :beginning_of_day
|
|
148
|
+
|
|
149
|
+
# Returns a new Time representing the start of the month (1st of the month, 0:00)
|
|
150
|
+
def beginning_of_month
|
|
151
|
+
#self - ((self.mday-1).days + self.seconds_since_midnight)
|
|
152
|
+
change(:mday => 1,:hour => 0, :min => 0, :sec => 0, :usec => 0)
|
|
153
|
+
end
|
|
154
|
+
alias :at_beginning_of_month :beginning_of_month
|
|
155
|
+
|
|
156
|
+
# Returns a new Time representing the end of the month (last day of the month, 0:00)
|
|
157
|
+
def end_of_month
|
|
158
|
+
#self - ((self.mday-1).days + self.seconds_since_midnight)
|
|
159
|
+
last_day = ::Time.days_in_month( self.month, self.year )
|
|
160
|
+
change(:mday => last_day,:hour => 0, :min => 0, :sec => 0, :usec => 0)
|
|
161
|
+
end
|
|
162
|
+
alias :at_end_of_month :end_of_month
|
|
163
|
+
|
|
164
|
+
# Returns a new Time representing the start of the quarter (1st of january, april, july, october, 0:00)
|
|
165
|
+
def beginning_of_quarter
|
|
166
|
+
beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= self.month })
|
|
167
|
+
end
|
|
168
|
+
alias :at_beginning_of_quarter :beginning_of_quarter
|
|
169
|
+
|
|
170
|
+
# Returns a new Time representing the start of the year (1st of january, 0:00)
|
|
171
|
+
def beginning_of_year
|
|
172
|
+
change(:month => 1,:mday => 1,:hour => 0, :min => 0, :sec => 0, :usec => 0)
|
|
173
|
+
end
|
|
174
|
+
alias :at_beginning_of_year :beginning_of_year
|
|
175
|
+
|
|
176
|
+
# Convenience method which returns a new Time representing the time 1 day ago
|
|
177
|
+
def yesterday
|
|
178
|
+
self.ago(1.day)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Convenience method which returns a new Time representing the time 1 day since the instance time
|
|
182
|
+
def tomorrow
|
|
183
|
+
self.since(1.day)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'date'
|
|
2
|
+
require 'time'
|
|
3
|
+
|
|
4
|
+
module ActiveSupport #:nodoc:
|
|
5
|
+
module CoreExtensions #:nodoc:
|
|
6
|
+
module Time #:nodoc:
|
|
7
|
+
# Getting times in different convenient string representations and other objects
|
|
8
|
+
module Conversions
|
|
9
|
+
DATE_FORMATS = {
|
|
10
|
+
:db => "%Y-%m-%d %H:%M:%S",
|
|
11
|
+
:short => "%d %b %H:%M",
|
|
12
|
+
:long => "%B %d, %Y %H:%M",
|
|
13
|
+
:rfc822 => "%a, %d %b %Y %H:%M:%S %z"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
def self.included(klass)
|
|
17
|
+
klass.send(:alias_method, :to_default_s, :to_s)
|
|
18
|
+
klass.send(:alias_method, :to_s, :to_formatted_s)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def to_formatted_s(format = :default)
|
|
22
|
+
DATE_FORMATS[format] ? strftime(DATE_FORMATS[format]).strip : to_default_s
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def to_date
|
|
26
|
+
::Date.new(year, month, day)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# To be able to keep Dates and Times interchangeable on conversions
|
|
30
|
+
def to_time
|
|
31
|
+
self
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
require 'set'
|
|
2
|
+
require File.dirname(__FILE__) + '/core_ext/module/attribute_accessors'
|
|
3
|
+
require File.dirname(__FILE__) + '/core_ext/load_error'
|
|
4
|
+
require File.dirname(__FILE__) + '/core_ext/kernel'
|
|
5
|
+
|
|
6
|
+
module Dependencies #:nodoc:
|
|
7
|
+
extend self
|
|
8
|
+
|
|
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.
|
|
18
|
+
mattr_accessor :loaded
|
|
19
|
+
self.loaded = Set.new
|
|
20
|
+
|
|
21
|
+
# Should we load files or require them?
|
|
22
|
+
mattr_accessor :mechanism
|
|
23
|
+
self.mechanism = :load
|
|
24
|
+
|
|
25
|
+
def load?
|
|
26
|
+
mechanism == :load
|
|
27
|
+
end
|
|
28
|
+
|
|
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
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def associate_with(file_name)
|
|
36
|
+
depend_on(file_name, true)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def clear
|
|
40
|
+
loaded.clear
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def require_or_load(file_name)
|
|
44
|
+
file_name = $1 if file_name =~ /^(.*)\.rb$/
|
|
45
|
+
return if loaded.include?(file_name)
|
|
46
|
+
|
|
47
|
+
# Record that we've seen this file *before* loading it to avoid an
|
|
48
|
+
# infinite loop with mutual dependencies.
|
|
49
|
+
loaded << file_name
|
|
50
|
+
|
|
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
|
|
63
|
+
end
|
|
64
|
+
else
|
|
65
|
+
require file_name
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Record history *after* loading so first load gets warnings.
|
|
69
|
+
history << file_name
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Return the a constant path for the provided parent and constant name
|
|
73
|
+
def constant_path_for(mod, name)
|
|
74
|
+
([Object, Kernel].include? mod) ? name.to_s : "#{mod}::#{name}"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
class LoadingModule
|
|
78
|
+
# Old style environment.rb referenced this method directly. Please note, it doesn't
|
|
79
|
+
# actualy *do* anything any more.
|
|
80
|
+
def self.root(*args)
|
|
81
|
+
if defined?(RAILS_DEFAULT_LOGGER)
|
|
82
|
+
RAILS_DEFAULT_LOGGER.warn "Your environment.rb uses the old syntax, it may not continue to work in future releases."
|
|
83
|
+
RAILS_DEFAULT_LOGGER.warn "For upgrade instructions please see: http://manuals.rubyonrails.com/read/book/19"
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
Object.send(:define_method, :require_or_load) { |file_name| Dependencies.require_or_load(file_name) } unless Object.respond_to?(:require_or_load)
|
|
90
|
+
Object.send(:define_method, :require_dependency) { |file_name| Dependencies.depend_on(file_name) } unless Object.respond_to?(:require_dependency)
|
|
91
|
+
Object.send(:define_method, :require_association) { |file_name| Dependencies.associate_with(file_name) } unless Object.respond_to?(:require_association)
|
|
92
|
+
|
|
93
|
+
class Module #:nodoc:
|
|
94
|
+
# Rename the original handler so we can chain it to the new one
|
|
95
|
+
alias :rails_original_const_missing :const_missing
|
|
96
|
+
|
|
97
|
+
# Use const_missing to autoload associations so we don't have to
|
|
98
|
+
# require_association when using single-table inheritance.
|
|
99
|
+
def const_missing(class_id)
|
|
100
|
+
file_name = class_id.to_s.demodulize.underscore
|
|
101
|
+
file_path = as_load_path.empty? ? file_name : "#{as_load_path}/#{file_name}"
|
|
102
|
+
begin
|
|
103
|
+
require_dependency(file_path)
|
|
104
|
+
brief_name = self == Object ? '' : "#{name}::"
|
|
105
|
+
raise NameError.new("uninitialized constant #{brief_name}#{class_id}") unless const_defined?(class_id)
|
|
106
|
+
return const_get(class_id)
|
|
107
|
+
rescue MissingSourceFile => e
|
|
108
|
+
# Re-raise the error if it does not concern the file we were trying to load.
|
|
109
|
+
raise unless e.is_missing? file_path
|
|
110
|
+
|
|
111
|
+
# Look for a directory in the load path that we ought to load.
|
|
112
|
+
if $LOAD_PATH.any? { |base| File.directory? "#{base}/#{file_path}" }
|
|
113
|
+
mod = Module.new
|
|
114
|
+
const_set class_id, mod # Create the new module
|
|
115
|
+
return mod
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Attempt to access the name from the parent, unless we don't have a valid
|
|
119
|
+
# parent, or the constant is already defined in the parent. If the latter
|
|
120
|
+
# is the case, then we are being queried via self::class_id, and we should
|
|
121
|
+
# avoid returning the constant from the parent if possible.
|
|
122
|
+
if parent && parent != self && ! parents.any? { |p| p.const_defined?(class_id) }
|
|
123
|
+
suppress(NameError) do
|
|
124
|
+
return parent.send(:const_missing, class_id)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
qualified_name = Dependencies.constant_path_for self, class_id
|
|
129
|
+
raise NameError.new("uninitialized constant #{qualified_name}").copy_blame!(e)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
class Class
|
|
135
|
+
def const_missing(class_id)
|
|
136
|
+
if [Object, Kernel].include?(self) || parent == self
|
|
137
|
+
super
|
|
138
|
+
else
|
|
139
|
+
begin
|
|
140
|
+
parent.send :const_missing, class_id
|
|
141
|
+
rescue NameError => e
|
|
142
|
+
# Make sure that the name we are missing is the one that caused the error
|
|
143
|
+
parent_qualified_name = Dependencies.constant_path_for parent, class_id
|
|
144
|
+
raise unless e.missing_name? parent_qualified_name
|
|
145
|
+
qualified_name = Dependencies.constant_path_for self, class_id
|
|
146
|
+
raise NameError.new("uninitialized constant #{qualified_name}").copy_blame!(e)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
class Object #:nodoc:
|
|
153
|
+
def load(file, *extras)
|
|
154
|
+
super(file, *extras)
|
|
155
|
+
rescue Object => exception
|
|
156
|
+
exception.blame_file! file
|
|
157
|
+
raise
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def require(file, *extras)
|
|
161
|
+
super(file, *extras)
|
|
162
|
+
rescue Object => exception
|
|
163
|
+
exception.blame_file! file
|
|
164
|
+
raise
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Add file-blaming to exceptions
|
|
169
|
+
class Exception #:nodoc:
|
|
170
|
+
def blame_file!(file)
|
|
171
|
+
(@blamed_files ||= []).unshift file
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def blamed_files
|
|
175
|
+
@blamed_files ||= []
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def describe_blame
|
|
179
|
+
return nil if blamed_files.empty?
|
|
180
|
+
"This error occurred while loading the following files:\n #{blamed_files.join "\n "}"
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def copy_blame!(exc)
|
|
184
|
+
@blamed_files = exc.blamed_files.clone
|
|
185
|
+
self
|
|
186
|
+
end
|
|
187
|
+
end
|