csd 0.0.15 → 0.0.16
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/.gitignore +1 -0
- data/COPYING +367 -0
- data/Rakefile +10 -10
- data/VERSION +1 -1
- data/bin/ai +19 -0
- data/csd.gemspec +257 -35
- data/lib/active_support.rb +75 -0
- data/lib/active_support/all.rb +3 -0
- data/lib/active_support/backtrace_cleaner.rb +94 -0
- data/lib/active_support/base64.rb +42 -0
- data/lib/active_support/basic_object.rb +21 -0
- data/lib/active_support/benchmarkable.rb +60 -0
- data/lib/active_support/buffered_logger.rb +132 -0
- data/lib/active_support/builder.rb +6 -0
- data/lib/active_support/cache.rb +626 -0
- data/lib/active_support/cache/compressed_mem_cache_store.rb +13 -0
- data/lib/active_support/cache/file_store.rb +188 -0
- data/lib/active_support/cache/mem_cache_store.rb +191 -0
- data/lib/active_support/cache/memory_store.rb +159 -0
- data/lib/active_support/cache/strategy/local_cache.rb +164 -0
- data/lib/active_support/cache/synchronized_memory_store.rb +11 -0
- data/lib/active_support/callbacks.rb +600 -0
- data/lib/active_support/concern.rb +29 -0
- data/lib/active_support/configurable.rb +36 -0
- data/lib/active_support/core_ext.rb +3 -0
- data/lib/active_support/core_ext/array.rb +7 -0
- data/lib/active_support/core_ext/array/access.rb +46 -0
- data/lib/active_support/core_ext/array/conversions.rb +164 -0
- data/lib/active_support/core_ext/array/extract_options.rb +29 -0
- data/lib/active_support/core_ext/array/grouping.rb +100 -0
- data/lib/active_support/core_ext/array/random_access.rb +20 -0
- data/lib/active_support/core_ext/array/uniq_by.rb +17 -0
- data/lib/active_support/core_ext/array/wrap.rb +22 -0
- data/lib/active_support/core_ext/benchmark.rb +7 -0
- data/lib/active_support/core_ext/big_decimal.rb +1 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +27 -0
- data/lib/active_support/core_ext/cgi.rb +1 -0
- data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +19 -0
- data/lib/active_support/core_ext/class.rb +4 -0
- data/lib/active_support/core_ext/class/attribute.rb +67 -0
- data/lib/active_support/core_ext/class/attribute_accessors.rb +63 -0
- data/lib/active_support/core_ext/class/delegating_attributes.rb +44 -0
- data/lib/active_support/core_ext/class/inheritable_attributes.rb +232 -0
- data/lib/active_support/core_ext/class/subclasses.rb +55 -0
- data/lib/active_support/core_ext/date/acts_like.rb +8 -0
- data/lib/active_support/core_ext/date/calculations.rb +240 -0
- data/lib/active_support/core_ext/date/conversions.rb +99 -0
- data/lib/active_support/core_ext/date/freeze.rb +31 -0
- data/lib/active_support/core_ext/date_time/acts_like.rb +13 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +113 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +102 -0
- data/lib/active_support/core_ext/date_time/zones.rb +17 -0
- data/lib/active_support/core_ext/enumerable.rb +119 -0
- data/lib/active_support/core_ext/exception.rb +3 -0
- data/lib/active_support/core_ext/file.rb +2 -0
- data/lib/active_support/core_ext/file/atomic.rb +41 -0
- data/lib/active_support/core_ext/file/path.rb +5 -0
- data/lib/active_support/core_ext/float.rb +1 -0
- data/lib/active_support/core_ext/float/rounding.rb +19 -0
- data/lib/active_support/core_ext/hash.rb +8 -0
- data/lib/active_support/core_ext/hash/conversions.rb +150 -0
- data/lib/active_support/core_ext/hash/deep_merge.rb +16 -0
- data/lib/active_support/core_ext/hash/diff.rb +13 -0
- data/lib/active_support/core_ext/hash/except.rb +24 -0
- data/lib/active_support/core_ext/hash/indifferent_access.rb +14 -0
- data/lib/active_support/core_ext/hash/keys.rb +45 -0
- data/lib/active_support/core_ext/hash/reverse_merge.rb +28 -0
- data/lib/active_support/core_ext/hash/slice.rb +38 -0
- data/lib/active_support/core_ext/integer.rb +3 -0
- data/lib/active_support/core_ext/integer/inflections.rb +14 -0
- data/lib/active_support/core_ext/integer/multiple.rb +6 -0
- data/lib/active_support/core_ext/integer/time.rb +39 -0
- data/lib/active_support/core_ext/kernel.rb +5 -0
- data/lib/active_support/core_ext/kernel/agnostics.rb +11 -0
- data/lib/active_support/core_ext/kernel/debugger.rb +16 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +62 -0
- data/lib/active_support/core_ext/kernel/requires.rb +26 -0
- data/lib/active_support/core_ext/kernel/singleton_class.rb +13 -0
- data/lib/active_support/core_ext/load_error.rb +23 -0
- data/lib/active_support/core_ext/logger.rb +146 -0
- data/lib/active_support/core_ext/module.rb +12 -0
- data/lib/active_support/core_ext/module/aliasing.rb +70 -0
- data/lib/active_support/core_ext/module/anonymous.rb +24 -0
- data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +31 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +32 -0
- data/lib/active_support/core_ext/module/attribute_accessors.rb +66 -0
- data/lib/active_support/core_ext/module/delegation.rb +146 -0
- data/lib/active_support/core_ext/module/deprecation.rb +9 -0
- data/lib/active_support/core_ext/module/introspection.rb +88 -0
- data/lib/active_support/core_ext/module/method_names.rb +14 -0
- data/lib/active_support/core_ext/module/reachable.rb +10 -0
- data/lib/active_support/core_ext/module/remove_method.rb +6 -0
- data/lib/active_support/core_ext/module/synchronization.rb +42 -0
- data/lib/active_support/core_ext/name_error.rb +18 -0
- data/lib/active_support/core_ext/numeric.rb +2 -0
- data/lib/active_support/core_ext/numeric/bytes.rb +44 -0
- data/lib/active_support/core_ext/numeric/time.rb +77 -0
- data/lib/active_support/core_ext/object.rb +14 -0
- data/lib/active_support/core_ext/object/acts_like.rb +10 -0
- data/lib/active_support/core_ext/object/blank.rb +76 -0
- data/lib/active_support/core_ext/object/conversions.rb +4 -0
- data/lib/active_support/core_ext/object/duplicable.rb +65 -0
- data/lib/active_support/core_ext/object/extending.rb +11 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +67 -0
- data/lib/active_support/core_ext/object/misc.rb +2 -0
- data/lib/active_support/core_ext/object/returning.rb +42 -0
- data/lib/active_support/core_ext/object/to_param.rb +49 -0
- data/lib/active_support/core_ext/object/to_query.rb +27 -0
- data/lib/active_support/core_ext/object/try.rb +36 -0
- data/lib/active_support/core_ext/object/with_options.rb +26 -0
- data/lib/active_support/core_ext/proc.rb +14 -0
- data/lib/active_support/core_ext/process.rb +1 -0
- data/lib/active_support/core_ext/process/daemon.rb +23 -0
- data/lib/active_support/core_ext/range.rb +4 -0
- data/lib/active_support/core_ext/range/blockless_step.rb +29 -0
- data/lib/active_support/core_ext/range/conversions.rb +21 -0
- data/lib/active_support/core_ext/range/include_range.rb +21 -0
- data/lib/active_support/core_ext/range/overlaps.rb +8 -0
- data/lib/active_support/core_ext/regexp.rb +5 -0
- data/lib/active_support/core_ext/rexml.rb +46 -0
- data/lib/active_support/core_ext/string.rb +12 -0
- data/lib/active_support/core_ext/string/access.rb +99 -0
- data/lib/active_support/core_ext/string/behavior.rb +7 -0
- data/lib/active_support/core_ext/string/conversions.rb +61 -0
- data/lib/active_support/core_ext/string/encoding.rb +11 -0
- data/lib/active_support/core_ext/string/exclude.rb +6 -0
- data/lib/active_support/core_ext/string/filters.rb +49 -0
- data/lib/active_support/core_ext/string/inflections.rb +149 -0
- data/lib/active_support/core_ext/string/interpolation.rb +2 -0
- data/lib/active_support/core_ext/string/multibyte.rb +72 -0
- data/lib/active_support/core_ext/string/output_safety.rb +109 -0
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -0
- data/lib/active_support/core_ext/string/xchar.rb +18 -0
- data/lib/active_support/core_ext/time/acts_like.rb +8 -0
- data/lib/active_support/core_ext/time/calculations.rb +282 -0
- data/lib/active_support/core_ext/time/conversions.rb +85 -0
- data/lib/active_support/core_ext/time/marshal.rb +56 -0
- data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +10 -0
- data/lib/active_support/core_ext/time/zones.rb +78 -0
- data/lib/active_support/core_ext/uri.rb +22 -0
- data/lib/active_support/dependencies.rb +628 -0
- data/lib/active_support/dependencies/autoload.rb +50 -0
- data/lib/active_support/deprecation.rb +18 -0
- data/lib/active_support/deprecation/behaviors.rb +38 -0
- data/lib/active_support/deprecation/method_wrappers.rb +29 -0
- data/lib/active_support/deprecation/proxy_wrappers.rb +74 -0
- data/lib/active_support/deprecation/reporting.rb +56 -0
- data/lib/active_support/duration.rb +105 -0
- data/lib/active_support/gzip.rb +25 -0
- data/lib/active_support/hash_with_indifferent_access.rb +145 -0
- data/lib/active_support/i18n.rb +8 -0
- data/lib/active_support/inflections.rb +56 -0
- data/lib/active_support/inflector.rb +7 -0
- data/lib/active_support/inflector/inflections.rb +211 -0
- data/lib/active_support/inflector/methods.rb +141 -0
- data/lib/active_support/inflector/transliterate.rb +97 -0
- data/lib/active_support/json.rb +2 -0
- data/lib/active_support/json/backends/jsongem.rb +43 -0
- data/lib/active_support/json/backends/yajl.rb +40 -0
- data/lib/active_support/json/backends/yaml.rb +90 -0
- data/lib/active_support/json/decoding.rb +51 -0
- data/lib/active_support/json/encoding.rb +254 -0
- data/lib/active_support/json/variable.rb +11 -0
- data/lib/active_support/lazy_load_hooks.rb +27 -0
- data/lib/active_support/locale/en.yml +36 -0
- data/lib/active_support/memoizable.rb +103 -0
- data/lib/active_support/message_encryptor.rb +71 -0
- data/lib/active_support/message_verifier.rb +62 -0
- data/lib/active_support/multibyte.rb +44 -0
- data/lib/active_support/multibyte/chars.rb +480 -0
- data/lib/active_support/multibyte/exceptions.rb +8 -0
- data/lib/active_support/multibyte/unicode.rb +393 -0
- data/lib/active_support/multibyte/utils.rb +60 -0
- data/lib/active_support/notifications.rb +81 -0
- data/lib/active_support/notifications/fanout.rb +93 -0
- data/lib/active_support/notifications/instrumenter.rb +56 -0
- data/lib/active_support/option_merger.rb +25 -0
- data/lib/active_support/ordered_hash.rb +158 -0
- data/lib/active_support/ordered_options.rb +27 -0
- data/lib/active_support/railtie.rb +100 -0
- data/lib/active_support/rescuable.rb +114 -0
- data/lib/active_support/ruby/shim.rb +22 -0
- data/lib/active_support/secure_random.rb +199 -0
- data/lib/active_support/string_inquirer.rb +21 -0
- data/lib/active_support/test_case.rb +42 -0
- data/lib/active_support/testing/assertions.rb +82 -0
- data/lib/active_support/testing/declarative.rb +40 -0
- data/lib/active_support/testing/default.rb +9 -0
- data/lib/active_support/testing/deprecation.rb +55 -0
- data/lib/active_support/testing/isolation.rb +154 -0
- data/lib/active_support/testing/pending.rb +48 -0
- data/lib/active_support/testing/performance.rb +455 -0
- data/lib/active_support/testing/setup_and_teardown.rb +111 -0
- data/lib/active_support/time.rb +34 -0
- data/lib/active_support/time/autoload.rb +5 -0
- data/lib/active_support/time_with_zone.rb +341 -0
- data/lib/active_support/values/time_zone.rb +377 -0
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +10 -0
- data/lib/active_support/whiny_nil.rb +60 -0
- data/lib/active_support/xml_mini.rb +158 -0
- data/lib/active_support/xml_mini/jdom.rb +168 -0
- data/lib/active_support/xml_mini/libxml.rb +80 -0
- data/lib/active_support/xml_mini/libxmlsax.rb +85 -0
- data/lib/active_support/xml_mini/nokogiri.rb +78 -0
- data/lib/active_support/xml_mini/nokogirisax.rb +83 -0
- data/lib/active_support/xml_mini/rexml.rb +129 -0
- data/lib/csd.rb +82 -2
- data/lib/csd/application.rb +2 -0
- data/lib/csd/application/default.rb +51 -0
- data/lib/csd/application/default/base.rb +15 -0
- data/lib/csd/application/minisip.rb +25 -0
- data/lib/csd/application/minisip/about.yml +14 -0
- data/lib/csd/application/minisip/base.rb +161 -0
- data/lib/csd/application/minisip/error.rb +11 -0
- data/lib/csd/application/minisip/options/common.rb +0 -0
- data/lib/csd/application/minisip/options/compile.rb +59 -0
- data/lib/csd/{applications → application}/minisip/unix/base.rb +10 -11
- data/lib/csd/application/opensips/about.yml +2 -0
- data/lib/csd/applications.rb +55 -0
- data/lib/csd/commands.rb +88 -65
- data/lib/csd/error.rb +31 -0
- data/lib/csd/extensions.rb +1 -0
- data/lib/{extensions → csd/extensions}/core/array.rb +2 -2
- data/lib/csd/extensions/core/dir.rb +46 -0
- data/lib/{extensions → csd/extensions}/core/file.rb +2 -2
- data/lib/{extensions → csd/extensions}/core/object.rb +2 -2
- data/lib/csd/extensions/core/option_parser.rb +33 -0
- data/lib/{extensions → csd/extensions}/core/pathname.rb +12 -3
- data/lib/{extensions → csd/extensions}/core/string.rb +2 -2
- data/lib/{extensions → csd/extensions}/gem/platform.rb +6 -2
- data/lib/csd/global_open_struct.rb +18 -0
- data/lib/csd/options.rb +124 -95
- data/lib/csd/path.rb +31 -0
- data/lib/csd/ui.rb +1 -0
- data/lib/csd/ui/cli.rb +7 -0
- data/lib/csd/ui/ui.rb +46 -0
- data/lib/csd/version.rb +9 -0
- data/lib/term/ansicolor.rb +102 -0
- data/lib/term/ansicolor/.keep +0 -0
- data/lib/term/ansicolor/version.rb +10 -0
- data/test/functional/test_applications.rb +86 -0
- data/test/functional/test_commands.rb +42 -29
- data/test/functional/test_options.rb +98 -0
- data/test/helper.rb +14 -0
- data/test/unit/test_dir.rb +38 -0
- data/test/unit/test_pathname.rb +32 -0
- metadata +253 -40
- data/LICENSE +0 -20
- data/bin/csd +0 -8
- data/lib/csd/applications/base.rb +0 -33
- data/lib/csd/applications/minisip/base.rb +0 -125
- data/lib/csd/applications/minisip/init.rb +0 -20
- data/lib/csd/init.rb +0 -69
- data/lib/csd/path_container.rb +0 -15
- data/publish +0 -29
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
class Time
|
4
|
+
# Ruby 1.8-cvs and early 1.9 series define private Time#to_date
|
5
|
+
%w(to_date to_datetime).each do |method|
|
6
|
+
if private_instance_methods.include?(method) || private_instance_methods.include?(method.to_sym)
|
7
|
+
public method
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'active_support/time_with_zone'
|
2
|
+
|
3
|
+
class Time
|
4
|
+
class << self
|
5
|
+
attr_accessor :zone_default
|
6
|
+
|
7
|
+
# Returns the TimeZone for the current request, if this has been set (via Time.zone=).
|
8
|
+
# If <tt>Time.zone</tt> has not been set for the current request, returns the TimeZone specified in <tt>config.time_zone</tt>.
|
9
|
+
def zone
|
10
|
+
Thread.current[:time_zone] || zone_default
|
11
|
+
end
|
12
|
+
|
13
|
+
# Sets <tt>Time.zone</tt> to a TimeZone object for the current request/thread.
|
14
|
+
#
|
15
|
+
# This method accepts any of the following:
|
16
|
+
#
|
17
|
+
# * A Rails TimeZone object.
|
18
|
+
# * An identifier for a Rails TimeZone object (e.g., "Eastern Time (US & Canada)", <tt>-5.hours</tt>).
|
19
|
+
# * A TZInfo::Timezone object.
|
20
|
+
# * An identifier for a TZInfo::Timezone object (e.g., "America/New_York").
|
21
|
+
#
|
22
|
+
# Here's an example of how you might set <tt>Time.zone</tt> on a per request basis -- <tt>current_user.time_zone</tt>
|
23
|
+
# just needs to return a string identifying the user's preferred TimeZone:
|
24
|
+
#
|
25
|
+
# class ApplicationController < ActionController::Base
|
26
|
+
# before_filter :set_time_zone
|
27
|
+
#
|
28
|
+
# def set_time_zone
|
29
|
+
# Time.zone = current_user.time_zone
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
def zone=(time_zone)
|
33
|
+
Thread.current[:time_zone] = get_zone(time_zone)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Allows override of <tt>Time.zone</tt> locally inside supplied block; resets <tt>Time.zone</tt> to existing value when done.
|
37
|
+
def use_zone(time_zone)
|
38
|
+
old_zone, ::Time.zone = ::Time.zone, get_zone(time_zone)
|
39
|
+
yield
|
40
|
+
ensure
|
41
|
+
::Time.zone = old_zone
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns <tt>Time.zone.now</tt> when <tt>config.time_zone</tt> is set, otherwise just returns <tt>Time.now</tt>.
|
45
|
+
def current
|
46
|
+
::Time.zone_default ? ::Time.zone.now : ::Time.now
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def get_zone(time_zone)
|
51
|
+
return time_zone if time_zone.nil? || time_zone.is_a?(ActiveSupport::TimeZone)
|
52
|
+
# lookup timezone based on identifier (unless we've been passed a TZInfo::Timezone)
|
53
|
+
unless time_zone.respond_to?(:period_for_local)
|
54
|
+
time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone) rescue nil
|
55
|
+
end
|
56
|
+
# Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone
|
57
|
+
if time_zone
|
58
|
+
time_zone.is_a?(ActiveSupport::TimeZone) ? time_zone : ActiveSupport::TimeZone.create(time_zone.name, nil, time_zone)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns the simultaneous time in <tt>Time.zone</tt>.
|
64
|
+
#
|
65
|
+
# Time.zone = 'Hawaii' # => 'Hawaii'
|
66
|
+
# Time.utc(2000).in_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00
|
67
|
+
#
|
68
|
+
# This method is similar to Time#localtime, except that it uses <tt>Time.zone</tt> as the local zone
|
69
|
+
# instead of the operating system's time zone.
|
70
|
+
#
|
71
|
+
# You can also pass in a TimeZone instance or string that identifies a TimeZone as an argument,
|
72
|
+
# and the conversion will be based on that zone instead of <tt>Time.zone</tt>.
|
73
|
+
#
|
74
|
+
# Time.utc(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
|
75
|
+
def in_time_zone(zone = ::Time.zone)
|
76
|
+
ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.__send__(:get_zone, zone))
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
if RUBY_VERSION >= '1.9'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
str = "\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E" # Ni-ho-nn-go in UTF-8, means Japanese.
|
7
|
+
|
8
|
+
parser = URI::Parser.new
|
9
|
+
|
10
|
+
unless str == parser.unescape(parser.escape(str))
|
11
|
+
URI::Parser.class_eval do
|
12
|
+
remove_method :unescape
|
13
|
+
def unescape(str, escaped = /%[a-fA-F\d]{2}/)
|
14
|
+
# TODO: Are we actually sure that ASCII == UTF-8?
|
15
|
+
# YK: My initial experiments say yes, but let's be sure please
|
16
|
+
enc = str.encoding
|
17
|
+
enc = Encoding::UTF_8 if enc == Encoding::US_ASCII
|
18
|
+
str.gsub(escaped) { [$&[1, 2].hex].pack('C') }.force_encoding(enc)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,628 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'thread'
|
3
|
+
require 'pathname'
|
4
|
+
require 'active_support/core_ext/module/aliasing'
|
5
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
6
|
+
require 'active_support/core_ext/module/introspection'
|
7
|
+
require 'active_support/core_ext/module/anonymous'
|
8
|
+
require 'active_support/core_ext/object/blank'
|
9
|
+
require 'active_support/core_ext/load_error'
|
10
|
+
require 'active_support/core_ext/name_error'
|
11
|
+
require 'active_support/core_ext/string/starts_ends_with'
|
12
|
+
require 'active_support/inflector'
|
13
|
+
|
14
|
+
module ActiveSupport #:nodoc:
|
15
|
+
module Dependencies #:nodoc:
|
16
|
+
extend self
|
17
|
+
|
18
|
+
# Should we turn on Ruby warnings on the first load of dependent files?
|
19
|
+
mattr_accessor :warnings_on_first_load
|
20
|
+
self.warnings_on_first_load = false
|
21
|
+
|
22
|
+
# All files ever loaded.
|
23
|
+
mattr_accessor :history
|
24
|
+
self.history = Set.new
|
25
|
+
|
26
|
+
# All files currently loaded.
|
27
|
+
mattr_accessor :loaded
|
28
|
+
self.loaded = Set.new
|
29
|
+
|
30
|
+
# Should we load files or require them?
|
31
|
+
mattr_accessor :mechanism
|
32
|
+
self.mechanism = ENV['NO_RELOAD'] ? :require : :load
|
33
|
+
|
34
|
+
# The set of directories from which we may automatically load files. Files
|
35
|
+
# under these directories will be reloaded on each request in development mode,
|
36
|
+
# unless the directory also appears in load_once_paths.
|
37
|
+
mattr_accessor :load_paths
|
38
|
+
self.load_paths = []
|
39
|
+
|
40
|
+
# The set of directories from which automatically loaded constants are loaded
|
41
|
+
# only once. All directories in this set must also be present in +load_paths+.
|
42
|
+
mattr_accessor :load_once_paths
|
43
|
+
self.load_once_paths = []
|
44
|
+
|
45
|
+
# An array of qualified constant names that have been loaded. Adding a name to
|
46
|
+
# this array will cause it to be unloaded the next time Dependencies are cleared.
|
47
|
+
mattr_accessor :autoloaded_constants
|
48
|
+
self.autoloaded_constants = []
|
49
|
+
|
50
|
+
mattr_accessor :references
|
51
|
+
self.references = {}
|
52
|
+
|
53
|
+
# An array of constant names that need to be unloaded on every request. Used
|
54
|
+
# to allow arbitrary constants to be marked for unloading.
|
55
|
+
mattr_accessor :explicitly_unloadable_constants
|
56
|
+
self.explicitly_unloadable_constants = []
|
57
|
+
|
58
|
+
# The logger is used for generating information on the action run-time (including benchmarking) if available.
|
59
|
+
# Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers.
|
60
|
+
mattr_accessor :logger
|
61
|
+
|
62
|
+
# Set to true to enable logging of const_missing and file loads
|
63
|
+
mattr_accessor :log_activity
|
64
|
+
self.log_activity = false
|
65
|
+
|
66
|
+
class WatchStack < Array
|
67
|
+
def initialize
|
68
|
+
@mutex = Mutex.new
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.locked(*methods)
|
72
|
+
methods.each { |m| class_eval "def #{m}(*) lock { super } end", __FILE__, __LINE__ }
|
73
|
+
end
|
74
|
+
|
75
|
+
def get(key)
|
76
|
+
(val = assoc(key)) ? val[1] : []
|
77
|
+
end
|
78
|
+
|
79
|
+
locked :concat, :each, :delete_if, :<<
|
80
|
+
|
81
|
+
def new_constants_for(frames)
|
82
|
+
constants = []
|
83
|
+
frames.each do |mod_name, prior_constants|
|
84
|
+
mod = Inflector.constantize(mod_name) if Dependencies.qualified_const_defined?(mod_name)
|
85
|
+
next unless mod.is_a?(Module)
|
86
|
+
|
87
|
+
new_constants = mod.local_constant_names - prior_constants
|
88
|
+
get(mod_name).concat(new_constants)
|
89
|
+
|
90
|
+
new_constants.each do |suffix|
|
91
|
+
constants << ([mod_name, suffix] - ["Object"]).join("::")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
constants
|
95
|
+
end
|
96
|
+
|
97
|
+
# Add a set of modules to the watch stack, remembering the initial constants
|
98
|
+
def add_modules(modules)
|
99
|
+
list = modules.map do |desc|
|
100
|
+
name = Dependencies.to_constant_name(desc)
|
101
|
+
consts = Dependencies.qualified_const_defined?(name) ?
|
102
|
+
Inflector.constantize(name).local_constant_names : []
|
103
|
+
[name, consts]
|
104
|
+
end
|
105
|
+
concat(list)
|
106
|
+
list
|
107
|
+
end
|
108
|
+
|
109
|
+
def lock
|
110
|
+
@mutex.synchronize { yield self }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# An internal stack used to record which constants are loaded by any block.
|
115
|
+
mattr_accessor :constant_watch_stack
|
116
|
+
self.constant_watch_stack = WatchStack.new
|
117
|
+
|
118
|
+
# Module includes this module
|
119
|
+
module ModuleConstMissing #:nodoc:
|
120
|
+
def self.append_features(base)
|
121
|
+
base.class_eval do
|
122
|
+
# Emulate #exclude via an ivar
|
123
|
+
return if defined?(@_const_missing) && @_const_missing
|
124
|
+
@_const_missing = instance_method(:const_missing)
|
125
|
+
remove_method(:const_missing)
|
126
|
+
end
|
127
|
+
super
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.exclude_from(base)
|
131
|
+
base.class_eval do
|
132
|
+
define_method :const_missing, @_const_missing
|
133
|
+
@_const_missing = nil
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Use const_missing to autoload associations so we don't have to
|
138
|
+
# require_association when using single-table inheritance.
|
139
|
+
def const_missing(const_name, nesting = nil)
|
140
|
+
klass_name = name.presence || "Object"
|
141
|
+
|
142
|
+
if !nesting
|
143
|
+
# We'll assume that the nesting of Foo::Bar is ["Foo::Bar", "Foo"]
|
144
|
+
# even though it might not be, such as in the case of
|
145
|
+
# class Foo::Bar; Baz; end
|
146
|
+
nesting = []
|
147
|
+
klass_name.to_s.scan(/::|$/) { nesting.unshift $` }
|
148
|
+
end
|
149
|
+
|
150
|
+
# If there are multiple levels of nesting to search under, the top
|
151
|
+
# level is the one we want to report as the lookup fail.
|
152
|
+
error = nil
|
153
|
+
|
154
|
+
nesting.each do |namespace|
|
155
|
+
begin
|
156
|
+
return Dependencies.load_missing_constant namespace.constantize, const_name
|
157
|
+
rescue NoMethodError then raise
|
158
|
+
rescue NameError => e
|
159
|
+
error ||= e
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# Raise the first error for this set. If this const_missing came from an
|
164
|
+
# earlier const_missing, this will result in the real error bubbling
|
165
|
+
# all the way up
|
166
|
+
raise error
|
167
|
+
end
|
168
|
+
|
169
|
+
def unloadable(const_desc = self)
|
170
|
+
super(const_desc)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# Object includes this module
|
175
|
+
module Loadable #:nodoc:
|
176
|
+
def self.exclude_from(base)
|
177
|
+
base.class_eval { define_method(:load, Kernel.instance_method(:load)) }
|
178
|
+
end
|
179
|
+
|
180
|
+
def require_or_load(file_name)
|
181
|
+
Dependencies.require_or_load(file_name)
|
182
|
+
end
|
183
|
+
|
184
|
+
def require_dependency(file_name, message = "No such file to load -- %s")
|
185
|
+
unless file_name.is_a?(String)
|
186
|
+
raise ArgumentError, "the file name must be a String -- you passed #{file_name.inspect}"
|
187
|
+
end
|
188
|
+
|
189
|
+
Dependencies.depend_on(file_name, false, message)
|
190
|
+
end
|
191
|
+
|
192
|
+
def require_association(file_name)
|
193
|
+
Dependencies.associate_with(file_name)
|
194
|
+
end
|
195
|
+
|
196
|
+
def load_dependency(file)
|
197
|
+
if Dependencies.load?
|
198
|
+
Dependencies.new_constants_in(Object) { yield }.presence
|
199
|
+
else
|
200
|
+
yield
|
201
|
+
end
|
202
|
+
rescue Exception => exception # errors from loading file
|
203
|
+
exception.blame_file! file
|
204
|
+
raise
|
205
|
+
end
|
206
|
+
|
207
|
+
def load(file, *)
|
208
|
+
load_dependency(file) { super }
|
209
|
+
end
|
210
|
+
|
211
|
+
def require(file, *)
|
212
|
+
load_dependency(file) { super }
|
213
|
+
end
|
214
|
+
|
215
|
+
# Mark the given constant as unloadable. Unloadable constants are removed each
|
216
|
+
# time dependencies are cleared.
|
217
|
+
#
|
218
|
+
# Note that marking a constant for unloading need only be done once. Setup
|
219
|
+
# or init scripts may list each unloadable constant that may need unloading;
|
220
|
+
# each constant will be removed for every subsequent clear, as opposed to for
|
221
|
+
# the first clear.
|
222
|
+
#
|
223
|
+
# The provided constant descriptor may be a (non-anonymous) module or class,
|
224
|
+
# or a qualified constant name as a string or symbol.
|
225
|
+
#
|
226
|
+
# Returns true if the constant was not previously marked for unloading, false
|
227
|
+
# otherwise.
|
228
|
+
def unloadable(const_desc)
|
229
|
+
Dependencies.mark_for_unload const_desc
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
# Exception file-blaming
|
234
|
+
module Blamable #:nodoc:
|
235
|
+
def blame_file!(file)
|
236
|
+
(@blamed_files ||= []).unshift file
|
237
|
+
end
|
238
|
+
|
239
|
+
def blamed_files
|
240
|
+
@blamed_files ||= []
|
241
|
+
end
|
242
|
+
|
243
|
+
def describe_blame
|
244
|
+
return nil if blamed_files.empty?
|
245
|
+
"This error occurred while loading the following files:\n #{blamed_files.join "\n "}"
|
246
|
+
end
|
247
|
+
|
248
|
+
def copy_blame!(exc)
|
249
|
+
@blamed_files = exc.blamed_files.clone
|
250
|
+
self
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
def hook!
|
255
|
+
Object.class_eval { include Loadable }
|
256
|
+
Module.class_eval { include ModuleConstMissing }
|
257
|
+
Exception.class_eval { include Blamable }
|
258
|
+
true
|
259
|
+
end
|
260
|
+
|
261
|
+
def unhook!
|
262
|
+
ModuleConstMissing.exclude_from(Module)
|
263
|
+
Loadable.exclude_from(Object)
|
264
|
+
true
|
265
|
+
end
|
266
|
+
|
267
|
+
def load?
|
268
|
+
mechanism == :load
|
269
|
+
end
|
270
|
+
|
271
|
+
def depend_on(file_name, swallow_load_errors = false, message = "No such file to load -- %s.rb")
|
272
|
+
path = search_for_file(file_name)
|
273
|
+
require_or_load(path || file_name)
|
274
|
+
rescue LoadError => load_error
|
275
|
+
unless swallow_load_errors
|
276
|
+
if file_name = load_error.message[/ -- (.*?)(\.rb)?$/, 1]
|
277
|
+
raise LoadError.new(message % file_name).copy_blame!(load_error)
|
278
|
+
end
|
279
|
+
raise
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def associate_with(file_name)
|
284
|
+
depend_on(file_name, true)
|
285
|
+
end
|
286
|
+
|
287
|
+
def clear
|
288
|
+
log_call
|
289
|
+
loaded.clear
|
290
|
+
remove_unloadable_constants!
|
291
|
+
end
|
292
|
+
|
293
|
+
def require_or_load(file_name, const_path = nil)
|
294
|
+
log_call file_name, const_path
|
295
|
+
file_name = $1 if file_name =~ /^(.*)\.rb$/
|
296
|
+
expanded = File.expand_path(file_name)
|
297
|
+
return if loaded.include?(expanded)
|
298
|
+
|
299
|
+
# Record that we've seen this file *before* loading it to avoid an
|
300
|
+
# infinite loop with mutual dependencies.
|
301
|
+
loaded << expanded
|
302
|
+
|
303
|
+
begin
|
304
|
+
if load?
|
305
|
+
log "loading #{file_name}"
|
306
|
+
|
307
|
+
# Enable warnings iff this file has not been loaded before and
|
308
|
+
# warnings_on_first_load is set.
|
309
|
+
load_args = ["#{file_name}.rb"]
|
310
|
+
load_args << const_path unless const_path.nil?
|
311
|
+
|
312
|
+
if !warnings_on_first_load or history.include?(expanded)
|
313
|
+
result = load_file(*load_args)
|
314
|
+
else
|
315
|
+
enable_warnings { result = load_file(*load_args) }
|
316
|
+
end
|
317
|
+
else
|
318
|
+
log "requiring #{file_name}"
|
319
|
+
result = require file_name
|
320
|
+
end
|
321
|
+
rescue Exception
|
322
|
+
loaded.delete expanded
|
323
|
+
raise
|
324
|
+
end
|
325
|
+
|
326
|
+
# Record history *after* loading so first load gets warnings.
|
327
|
+
history << expanded
|
328
|
+
return result
|
329
|
+
end
|
330
|
+
|
331
|
+
# Is the provided constant path defined?
|
332
|
+
def qualified_const_defined?(path)
|
333
|
+
names = path.sub(/^::/, '').to_s.split('::')
|
334
|
+
|
335
|
+
names.inject(Object) do |mod, name|
|
336
|
+
return false unless local_const_defined?(mod, name)
|
337
|
+
mod.const_get name
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
if Module.method(:const_defined?).arity == 1
|
342
|
+
# Does this module define this constant?
|
343
|
+
# Wrapper to accomodate changing Module#const_defined? in Ruby 1.9
|
344
|
+
def local_const_defined?(mod, const)
|
345
|
+
mod.const_defined?(const)
|
346
|
+
end
|
347
|
+
else
|
348
|
+
def local_const_defined?(mod, const) #:nodoc:
|
349
|
+
mod.const_defined?(const, false)
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
# Given +path+, a filesystem path to a ruby file, return an array of constant
|
354
|
+
# paths which would cause Dependencies to attempt to load this file.
|
355
|
+
def loadable_constants_for_path(path, bases = load_paths)
|
356
|
+
expanded_path = Pathname.new(path[/\A(.*?)(\.rb)?\Z/, 1]).expand_path
|
357
|
+
|
358
|
+
bases.inject([]) do |paths, root|
|
359
|
+
expanded_root = Pathname.new(root).expand_path
|
360
|
+
nesting = expanded_path.relative_path_from(expanded_root).to_s
|
361
|
+
next paths if nesting =~ /\.\./
|
362
|
+
paths << nesting.camelize
|
363
|
+
end.uniq
|
364
|
+
end
|
365
|
+
|
366
|
+
# Search for a file in load_paths matching the provided suffix.
|
367
|
+
def search_for_file(path_suffix)
|
368
|
+
path_suffix = path_suffix.sub(/(\.rb)?$/, ".rb")
|
369
|
+
|
370
|
+
load_paths.each do |root|
|
371
|
+
path = File.join(root, path_suffix)
|
372
|
+
return path if File.file? path
|
373
|
+
end
|
374
|
+
nil # Gee, I sure wish we had first_match ;-)
|
375
|
+
end
|
376
|
+
|
377
|
+
# Does the provided path_suffix correspond to an autoloadable module?
|
378
|
+
# Instead of returning a boolean, the autoload base for this module is returned.
|
379
|
+
def autoloadable_module?(path_suffix)
|
380
|
+
load_paths.each do |load_path|
|
381
|
+
return load_path if File.directory? File.join(load_path, path_suffix)
|
382
|
+
end
|
383
|
+
nil
|
384
|
+
end
|
385
|
+
|
386
|
+
def load_once_path?(path)
|
387
|
+
load_once_paths.any? { |base| path.starts_with? base }
|
388
|
+
end
|
389
|
+
|
390
|
+
# Attempt to autoload the provided module name by searching for a directory
|
391
|
+
# matching the expect path suffix. If found, the module is created and assigned
|
392
|
+
# to +into+'s constants with the name +const_name+. Provided that the directory
|
393
|
+
# was loaded from a reloadable base path, it is added to the set of constants
|
394
|
+
# that are to be unloaded.
|
395
|
+
def autoload_module!(into, const_name, qualified_name, path_suffix)
|
396
|
+
return nil unless base_path = autoloadable_module?(path_suffix)
|
397
|
+
mod = Module.new
|
398
|
+
into.const_set const_name, mod
|
399
|
+
autoloaded_constants << qualified_name unless load_once_paths.include?(base_path)
|
400
|
+
return mod
|
401
|
+
end
|
402
|
+
|
403
|
+
# Load the file at the provided path. +const_paths+ is a set of qualified
|
404
|
+
# constant names. When loading the file, Dependencies will watch for the
|
405
|
+
# addition of these constants. Each that is defined will be marked as
|
406
|
+
# autoloaded, and will be removed when Dependencies.clear is next called.
|
407
|
+
#
|
408
|
+
# If the second parameter is left off, then Dependencies will construct a set
|
409
|
+
# of names that the file at +path+ may define. See
|
410
|
+
# +loadable_constants_for_path+ for more details.
|
411
|
+
def load_file(path, const_paths = loadable_constants_for_path(path))
|
412
|
+
log_call path, const_paths
|
413
|
+
const_paths = [const_paths].compact unless const_paths.is_a? Array
|
414
|
+
parent_paths = const_paths.collect { |const_path| /(.*)::[^:]+\Z/ =~ const_path ? $1 : :Object }
|
415
|
+
|
416
|
+
result = nil
|
417
|
+
newly_defined_paths = new_constants_in(*parent_paths) do
|
418
|
+
result = Kernel.load path
|
419
|
+
end
|
420
|
+
|
421
|
+
autoloaded_constants.concat newly_defined_paths unless load_once_path?(path)
|
422
|
+
autoloaded_constants.uniq!
|
423
|
+
log "loading #{path} defined #{newly_defined_paths * ', '}" unless newly_defined_paths.empty?
|
424
|
+
return result
|
425
|
+
end
|
426
|
+
|
427
|
+
# Return the constant path for the provided parent and constant name.
|
428
|
+
def qualified_name_for(mod, name)
|
429
|
+
mod_name = to_constant_name mod
|
430
|
+
mod_name == "Object" ? name.to_s : "#{mod_name}::#{name}"
|
431
|
+
end
|
432
|
+
|
433
|
+
# Load the constant named +const_name+ which is missing from +from_mod+. If
|
434
|
+
# it is not possible to load the constant into from_mod, try its parent module
|
435
|
+
# using const_missing.
|
436
|
+
def load_missing_constant(from_mod, const_name)
|
437
|
+
log_call from_mod, const_name
|
438
|
+
|
439
|
+
unless qualified_const_defined?(from_mod.name) && Inflector.constantize(from_mod.name).equal?(from_mod)
|
440
|
+
raise ArgumentError, "A copy of #{from_mod} has been removed from the module tree but is still active!"
|
441
|
+
end
|
442
|
+
|
443
|
+
raise ArgumentError, "#{from_mod} is not missing constant #{const_name}!" if local_const_defined?(from_mod, const_name)
|
444
|
+
|
445
|
+
qualified_name = qualified_name_for from_mod, const_name
|
446
|
+
path_suffix = qualified_name.underscore
|
447
|
+
|
448
|
+
trace = caller.reject {|l| l =~ %r{#{Regexp.escape(__FILE__)}}}
|
449
|
+
name_error = NameError.new("uninitialized constant #{qualified_name}")
|
450
|
+
name_error.set_backtrace(trace)
|
451
|
+
|
452
|
+
file_path = search_for_file(path_suffix)
|
453
|
+
|
454
|
+
if file_path && ! loaded.include?(File.expand_path(file_path)) # We found a matching file to load
|
455
|
+
require_or_load file_path
|
456
|
+
raise LoadError, "Expected #{file_path} to define #{qualified_name}" unless local_const_defined?(from_mod, const_name)
|
457
|
+
return from_mod.const_get(const_name)
|
458
|
+
elsif mod = autoload_module!(from_mod, const_name, qualified_name, path_suffix)
|
459
|
+
return mod
|
460
|
+
elsif (parent = from_mod.parent) && parent != from_mod &&
|
461
|
+
! from_mod.parents.any? { |p| local_const_defined?(p, const_name) }
|
462
|
+
# If our parents do not have a constant named +const_name+ then we are free
|
463
|
+
# to attempt to load upwards. If they do have such a constant, then this
|
464
|
+
# const_missing must be due to from_mod::const_name, which should not
|
465
|
+
# return constants from from_mod's parents.
|
466
|
+
begin
|
467
|
+
return parent.const_missing(const_name)
|
468
|
+
rescue NameError => e
|
469
|
+
raise unless e.missing_name? qualified_name_for(parent, const_name)
|
470
|
+
raise name_error
|
471
|
+
end
|
472
|
+
else
|
473
|
+
raise name_error
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
# Remove the constants that have been autoloaded, and those that have been
|
478
|
+
# marked for unloading.
|
479
|
+
def remove_unloadable_constants!
|
480
|
+
autoloaded_constants.each { |const| remove_constant const }
|
481
|
+
autoloaded_constants.clear
|
482
|
+
Reference.clear!
|
483
|
+
explicitly_unloadable_constants.each { |const| remove_constant const }
|
484
|
+
end
|
485
|
+
|
486
|
+
class Reference
|
487
|
+
@@constants = Hash.new { |h, k| h[k] = Inflector.constantize(k) }
|
488
|
+
|
489
|
+
attr_reader :name
|
490
|
+
|
491
|
+
def initialize(name)
|
492
|
+
@name = name.to_s
|
493
|
+
@@constants[@name] = name if name.respond_to?(:name)
|
494
|
+
end
|
495
|
+
|
496
|
+
def get
|
497
|
+
@@constants[@name]
|
498
|
+
end
|
499
|
+
|
500
|
+
def self.clear!
|
501
|
+
@@constants.clear
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
505
|
+
def ref(name)
|
506
|
+
references[name] ||= Reference.new(name)
|
507
|
+
end
|
508
|
+
|
509
|
+
def constantize(name)
|
510
|
+
ref(name).get
|
511
|
+
end
|
512
|
+
|
513
|
+
# Determine if the given constant has been automatically loaded.
|
514
|
+
def autoloaded?(desc)
|
515
|
+
# No name => anonymous module.
|
516
|
+
return false if desc.is_a?(Module) && desc.anonymous?
|
517
|
+
name = to_constant_name desc
|
518
|
+
return false unless qualified_const_defined? name
|
519
|
+
return autoloaded_constants.include?(name)
|
520
|
+
end
|
521
|
+
|
522
|
+
# Will the provided constant descriptor be unloaded?
|
523
|
+
def will_unload?(const_desc)
|
524
|
+
autoloaded?(const_desc) ||
|
525
|
+
explicitly_unloadable_constants.include?(to_constant_name(const_desc))
|
526
|
+
end
|
527
|
+
|
528
|
+
# Mark the provided constant name for unloading. This constant will be
|
529
|
+
# unloaded on each request, not just the next one.
|
530
|
+
def mark_for_unload(const_desc)
|
531
|
+
name = to_constant_name const_desc
|
532
|
+
if explicitly_unloadable_constants.include? name
|
533
|
+
return false
|
534
|
+
else
|
535
|
+
explicitly_unloadable_constants << name
|
536
|
+
return true
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
# Run the provided block and detect the new constants that were loaded during
|
541
|
+
# its execution. Constants may only be regarded as 'new' once -- so if the
|
542
|
+
# block calls +new_constants_in+ again, then the constants defined within the
|
543
|
+
# inner call will not be reported in this one.
|
544
|
+
#
|
545
|
+
# If the provided block does not run to completion, and instead raises an
|
546
|
+
# exception, any new constants are regarded as being only partially defined
|
547
|
+
# and will be removed immediately.
|
548
|
+
def new_constants_in(*descs)
|
549
|
+
log_call(*descs)
|
550
|
+
watch_frames = constant_watch_stack.add_modules(descs)
|
551
|
+
|
552
|
+
aborting = true
|
553
|
+
begin
|
554
|
+
yield # Now yield to the code that is to define new constants.
|
555
|
+
aborting = false
|
556
|
+
ensure
|
557
|
+
new_constants = constant_watch_stack.new_constants_for(watch_frames)
|
558
|
+
|
559
|
+
log "New constants: #{new_constants * ', '}"
|
560
|
+
return new_constants unless aborting
|
561
|
+
|
562
|
+
log "Error during loading, removing partially loaded constants "
|
563
|
+
new_constants.each {|c| remove_constant(c) }.clear
|
564
|
+
end
|
565
|
+
|
566
|
+
return []
|
567
|
+
ensure
|
568
|
+
# Remove the stack frames that we added.
|
569
|
+
watch_frames.each {|f| constant_watch_stack.delete(f) } if watch_frames.present?
|
570
|
+
end
|
571
|
+
|
572
|
+
class LoadingModule #:nodoc:
|
573
|
+
# Old style environment.rb referenced this method directly. Please note, it doesn't
|
574
|
+
# actually *do* anything any more.
|
575
|
+
def self.root(*args)
|
576
|
+
if defined?(Rails) && Rails.logger
|
577
|
+
Rails.logger.warn "Your environment.rb uses the old syntax, it may not continue to work in future releases."
|
578
|
+
Rails.logger.warn "For upgrade instructions please see: http://manuals.rubyonrails.com/read/book/19"
|
579
|
+
end
|
580
|
+
end
|
581
|
+
end
|
582
|
+
|
583
|
+
# Convert the provided const desc to a qualified constant name (as a string).
|
584
|
+
# A module, class, symbol, or string may be provided.
|
585
|
+
def to_constant_name(desc) #:nodoc:
|
586
|
+
name = case desc
|
587
|
+
when String then desc.sub(/^::/, '')
|
588
|
+
when Symbol then desc.to_s
|
589
|
+
when Module
|
590
|
+
desc.name.presence ||
|
591
|
+
raise(ArgumentError, "Anonymous modules have no name to be referenced by")
|
592
|
+
else raise TypeError, "Not a valid constant descriptor: #{desc.inspect}"
|
593
|
+
end
|
594
|
+
end
|
595
|
+
|
596
|
+
def remove_constant(const) #:nodoc:
|
597
|
+
return false unless qualified_const_defined? const
|
598
|
+
|
599
|
+
# Normalize ::Foo, Foo, Object::Foo, and ::Object::Foo to Object::Foo
|
600
|
+
names = const.to_s.sub(/^::(Object)?/, 'Object::').split("::")
|
601
|
+
to_remove = names.pop
|
602
|
+
parent = Inflector.constantize(names * '::')
|
603
|
+
|
604
|
+
log "removing constant #{const}"
|
605
|
+
parent.instance_eval { remove_const to_remove }
|
606
|
+
|
607
|
+
return true
|
608
|
+
end
|
609
|
+
|
610
|
+
protected
|
611
|
+
def log_call(*args)
|
612
|
+
if logger && log_activity
|
613
|
+
arg_str = args.collect { |arg| arg.inspect } * ', '
|
614
|
+
/in `([a-z_\?\!]+)'/ =~ caller(1).first
|
615
|
+
selector = $1 || '<unknown>'
|
616
|
+
log "called #{selector}(#{arg_str})"
|
617
|
+
end
|
618
|
+
end
|
619
|
+
|
620
|
+
def log(msg)
|
621
|
+
if logger && log_activity
|
622
|
+
logger.debug "Dependencies: #{msg}"
|
623
|
+
end
|
624
|
+
end
|
625
|
+
end
|
626
|
+
end
|
627
|
+
|
628
|
+
ActiveSupport::Dependencies.hook!
|