monetra-ruby 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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,62 @@
|
|
1
|
+
module ActiveSupport
|
2
|
+
module CachingTools #:nodoc:
|
3
|
+
|
4
|
+
# Provide shortcuts to simply the creation of nested default hashes. This
|
5
|
+
# pattern is useful, common practice, and unsightly when done manually.
|
6
|
+
module HashCaching
|
7
|
+
# Dynamically create a nested hash structure used to cache calls to +method_name+
|
8
|
+
# The cache method is named +#{method_name}_cache+ unless :as => :alternate_name
|
9
|
+
# is given.
|
10
|
+
#
|
11
|
+
# The hash structure is created using nested Hash.new. For example:
|
12
|
+
#
|
13
|
+
# def slow_method(a, b) a ** b end
|
14
|
+
#
|
15
|
+
# can be cached using hash_cache :slow_method, which will define the method
|
16
|
+
# slow_method_cache. We can then find the result of a ** b using:
|
17
|
+
#
|
18
|
+
# slow_method_cache[a][b]
|
19
|
+
#
|
20
|
+
# The hash structure returned by slow_method_cache would look like this:
|
21
|
+
#
|
22
|
+
# Hash.new do |as, a|
|
23
|
+
# as[a] = Hash.new do |bs, b|
|
24
|
+
# bs[b] = slow_method(a, b)
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# The generated code is actually compressed onto a single line to maintain
|
29
|
+
# sensible backtrace signatures.
|
30
|
+
#
|
31
|
+
def hash_cache(method_name, options = {})
|
32
|
+
selector = options[:as] || "#{method_name}_cache"
|
33
|
+
method = self.instance_method(method_name)
|
34
|
+
|
35
|
+
args = []
|
36
|
+
code = "def #{selector}(); @#{selector} ||= "
|
37
|
+
|
38
|
+
(1..method.arity).each do |n|
|
39
|
+
args << "v#{n}"
|
40
|
+
code << "Hash.new {|h#{n}, v#{n}| h#{n}[v#{n}] = "
|
41
|
+
end
|
42
|
+
|
43
|
+
# Add the method call with arguments, followed by closing braces and end.
|
44
|
+
code << "#{method_name}(#{args * ', '}) #{'}' * method.arity} end"
|
45
|
+
|
46
|
+
# Extract the line number information from the caller. Exceptions arising
|
47
|
+
# in the generated code should point to the +hash_cache :...+ line.
|
48
|
+
if caller[0] && /^(.*):(\d+)$/ =~ caller[0]
|
49
|
+
file, line_number = $1, $2.to_i
|
50
|
+
else # We can't give good trackback info; fallback to this line:
|
51
|
+
file, line_number = __FILE__, __LINE__
|
52
|
+
end
|
53
|
+
|
54
|
+
# We use eval rather than building proc's because it allows us to avoid
|
55
|
+
# linking the Hash's to this method's binding. Experience has shown that
|
56
|
+
# doing so can cause obtuse memory leaks.
|
57
|
+
class_eval code, file, line_number
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require File.dirname(__FILE__) + '/core_ext/class/attribute_accessors'
|
3
|
+
|
4
|
+
class Logger #:nodoc:
|
5
|
+
cattr_accessor :silencer
|
6
|
+
self.silencer = true
|
7
|
+
|
8
|
+
# Silences the logger for the duration of the block.
|
9
|
+
def silence(temporary_level = Logger::ERROR)
|
10
|
+
if silencer
|
11
|
+
begin
|
12
|
+
old_logger_level, self.level = level, temporary_level
|
13
|
+
yield self
|
14
|
+
ensure
|
15
|
+
self.level = old_logger_level
|
16
|
+
end
|
17
|
+
else
|
18
|
+
yield self
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
alias old_format_message format_message
|
24
|
+
|
25
|
+
# Ruby 1.8.3 transposed the msg and progname arguments to format_message.
|
26
|
+
# We can't test RUBY_VERSION because some distributions don't keep Ruby
|
27
|
+
# and its standard library in sync, leading to installations of Ruby 1.8.2
|
28
|
+
# with Logger from 1.8.3 and vice versa.
|
29
|
+
if method_defined?(:formatter=)
|
30
|
+
def format_message(severity, timestamp, progname, msg)
|
31
|
+
"#{msg}\n"
|
32
|
+
end
|
33
|
+
else
|
34
|
+
def format_message(severity, timestamp, msg, progname)
|
35
|
+
"#{msg}\n"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Dir[File.dirname(__FILE__) + "/core_ext/*.rb"].each { |file| require(file) }
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module ActiveSupport #:nodoc:
|
2
|
+
module CoreExtensions #:nodoc:
|
3
|
+
module Array #:nodoc:
|
4
|
+
module Conversions
|
5
|
+
# Converts the array to comma-seperated sentence where the last element is joined by the connector word. Options:
|
6
|
+
# * <tt>:connector</tt>: The word used to join the last element in arrays with two or more elements (default: "and")
|
7
|
+
# * <tt>:skip_last_comma</tt>: Set to true to return "a, b and c" instead of "a, b, and c".
|
8
|
+
def to_sentence(options = {})
|
9
|
+
options.assert_valid_keys(:connector, :skip_last_comma)
|
10
|
+
options.reverse_merge! :connector => 'and', :skip_last_comma => false
|
11
|
+
|
12
|
+
case length
|
13
|
+
when 0
|
14
|
+
""
|
15
|
+
when 1
|
16
|
+
self[0]
|
17
|
+
when 2
|
18
|
+
"#{self[0]} #{options[:connector]} #{self[1]}"
|
19
|
+
else
|
20
|
+
"#{self[0...-1].join(', ')}#{options[:skip_last_comma] ? '' : ','} #{options[:connector]} #{self[-1]}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# When an array is given to url_for, it is converted to a slash separated string.
|
25
|
+
def to_param
|
26
|
+
join '/'
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.included(klass) #:nodoc:
|
30
|
+
klass.send(:alias_method, :to_default_s, :to_s)
|
31
|
+
klass.send(:alias_method, :to_s, :to_formatted_s)
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_formatted_s(format = :default)
|
35
|
+
case format
|
36
|
+
when :db
|
37
|
+
if respond_to?(:empty?) && self.empty?
|
38
|
+
"null"
|
39
|
+
else
|
40
|
+
collect { |element| element.id }.join(",")
|
41
|
+
end
|
42
|
+
else
|
43
|
+
to_default_s
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_xml(options = {})
|
48
|
+
raise "Not all elements respond to to_xml" unless all? { |e| e.respond_to? :to_xml }
|
49
|
+
|
50
|
+
options[:root] ||= all? { |e| e.is_a?(first.class) && first.class.to_s != "Hash" } ? first.class.to_s.underscore.pluralize : "records"
|
51
|
+
options[:children] ||= options[:root].singularize
|
52
|
+
options[:indent] ||= 2
|
53
|
+
options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
|
54
|
+
|
55
|
+
root = options.delete(:root).to_s
|
56
|
+
children = options.delete(:children)
|
57
|
+
|
58
|
+
if !options.has_key?(:dasherize) || options[:dasherize]
|
59
|
+
root = root.dasherize
|
60
|
+
end
|
61
|
+
|
62
|
+
options[:builder].instruct! unless options.delete(:skip_instruct)
|
63
|
+
|
64
|
+
opts = options.merge({ :skip_instruct => true, :root => children })
|
65
|
+
|
66
|
+
options[:builder].tag!(root) { each { |e| e.to_xml(opts) } }
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module ActiveSupport #:nodoc:
|
2
|
+
module CoreExtensions #:nodoc:
|
3
|
+
module Array #:nodoc:
|
4
|
+
module Grouping
|
5
|
+
# Iterate over an array in groups of a certain size, padding any remaining
|
6
|
+
# slots with specified value (<tt>nil</tt> by default).
|
7
|
+
#
|
8
|
+
# E.g.
|
9
|
+
#
|
10
|
+
# %w(1 2 3 4 5 6 7).in_groups_of(3) {|g| p g}
|
11
|
+
# ["1", "2", "3"]
|
12
|
+
# ["4", "5", "6"]
|
13
|
+
# ["7", nil, nil]
|
14
|
+
def in_groups_of(number, fill_with = nil, &block)
|
15
|
+
require 'enumerator'
|
16
|
+
collection = dup
|
17
|
+
collection << fill_with until collection.size.modulo(number).zero?
|
18
|
+
grouped_collection = [] unless block_given?
|
19
|
+
collection.each_slice(number) do |group|
|
20
|
+
block_given? ? yield(group) : grouped_collection << group
|
21
|
+
end
|
22
|
+
grouped_collection unless block_given?
|
23
|
+
end
|
24
|
+
|
25
|
+
# Divide the array into one or more subarrays based on a delimiting +value+
|
26
|
+
# or the result of an optional block.
|
27
|
+
#
|
28
|
+
# ex.
|
29
|
+
#
|
30
|
+
# [1, 2, 3, 4, 5].split(3) # => [[1, 2], [4, 5]]
|
31
|
+
# (1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]
|
32
|
+
def split(value = nil, &block)
|
33
|
+
block ||= Proc.new { |e| e == value }
|
34
|
+
inject([[]]) do |results, element|
|
35
|
+
if block.call(element)
|
36
|
+
results << []
|
37
|
+
else
|
38
|
+
results.last << element
|
39
|
+
end
|
40
|
+
results
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class Object #:nodoc:
|
2
|
+
# "", " ", nil, [], and {} are blank
|
3
|
+
def blank?
|
4
|
+
if respond_to?(:empty?) && respond_to?(:strip)
|
5
|
+
empty? or strip.empty?
|
6
|
+
elsif respond_to?(:empty?)
|
7
|
+
empty?
|
8
|
+
else
|
9
|
+
!self
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class NilClass #:nodoc:
|
15
|
+
def blank?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class FalseClass #:nodoc:
|
21
|
+
def blank?
|
22
|
+
true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class TrueClass #:nodoc:
|
27
|
+
def blank?
|
28
|
+
false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Array #:nodoc:
|
33
|
+
alias_method :blank?, :empty?
|
34
|
+
end
|
35
|
+
|
36
|
+
class Hash #:nodoc:
|
37
|
+
alias_method :blank?, :empty?
|
38
|
+
end
|
39
|
+
|
40
|
+
class String #:nodoc:
|
41
|
+
def blank?
|
42
|
+
empty? || strip.empty?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Numeric #:nodoc:
|
47
|
+
def blank?
|
48
|
+
false
|
49
|
+
end
|
50
|
+
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
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Extends the class object with class and instance accessors for class attributes,
|
2
|
+
# just like the native attr* accessors for instance attributes.
|
3
|
+
class Class # :nodoc:
|
4
|
+
def cattr_reader(*syms)
|
5
|
+
syms.flatten.each do |sym|
|
6
|
+
class_eval(<<-EOS, __FILE__, __LINE__)
|
7
|
+
unless defined? @@#{sym}
|
8
|
+
@@#{sym} = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.#{sym}
|
12
|
+
@@#{sym}
|
13
|
+
end
|
14
|
+
|
15
|
+
def #{sym}
|
16
|
+
@@#{sym}
|
17
|
+
end
|
18
|
+
EOS
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def cattr_writer(*syms)
|
23
|
+
syms.flatten.each do |sym|
|
24
|
+
class_eval(<<-EOS, __FILE__, __LINE__)
|
25
|
+
unless defined? @@#{sym}
|
26
|
+
@@#{sym} = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.#{sym}=(obj)
|
30
|
+
@@#{sym} = obj
|
31
|
+
end
|
32
|
+
|
33
|
+
def #{sym}=(obj)
|
34
|
+
@@#{sym} = obj
|
35
|
+
end
|
36
|
+
EOS
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def cattr_accessor(*syms)
|
41
|
+
cattr_reader(*syms)
|
42
|
+
cattr_writer(*syms)
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# Retain for backward compatibility. Methods are now included in Class.
|
2
|
+
module ClassInheritableAttributes # :nodoc:
|
3
|
+
end
|
4
|
+
|
5
|
+
# Allows attributes to be shared within an inheritance hierarchy, but where each descendant gets a copy of
|
6
|
+
# their parents' attributes, instead of just a pointer to the same. This means that the child can add elements
|
7
|
+
# to, for example, an array without those additions being shared with either their parent, siblings, or
|
8
|
+
# children, which is unlike the regular class-level attributes that are shared across the entire hierarchy.
|
9
|
+
class Class # :nodoc:
|
10
|
+
def class_inheritable_reader(*syms)
|
11
|
+
syms.each do |sym|
|
12
|
+
class_eval <<-EOS
|
13
|
+
def self.#{sym}
|
14
|
+
read_inheritable_attribute(:#{sym})
|
15
|
+
end
|
16
|
+
|
17
|
+
def #{sym}
|
18
|
+
self.class.#{sym}
|
19
|
+
end
|
20
|
+
EOS
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def class_inheritable_writer(*syms)
|
25
|
+
syms.each do |sym|
|
26
|
+
class_eval <<-EOS
|
27
|
+
def self.#{sym}=(obj)
|
28
|
+
write_inheritable_attribute(:#{sym}, obj)
|
29
|
+
end
|
30
|
+
|
31
|
+
def #{sym}=(obj)
|
32
|
+
self.class.#{sym} = obj
|
33
|
+
end
|
34
|
+
EOS
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def class_inheritable_array_writer(*syms)
|
39
|
+
syms.each do |sym|
|
40
|
+
class_eval <<-EOS
|
41
|
+
def self.#{sym}=(obj)
|
42
|
+
write_inheritable_array(:#{sym}, obj)
|
43
|
+
end
|
44
|
+
|
45
|
+
def #{sym}=(obj)
|
46
|
+
self.class.#{sym} = obj
|
47
|
+
end
|
48
|
+
EOS
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def class_inheritable_hash_writer(*syms)
|
53
|
+
syms.each do |sym|
|
54
|
+
class_eval <<-EOS
|
55
|
+
def self.#{sym}=(obj)
|
56
|
+
write_inheritable_hash(:#{sym}, obj)
|
57
|
+
end
|
58
|
+
|
59
|
+
def #{sym}=(obj)
|
60
|
+
self.class.#{sym} = obj
|
61
|
+
end
|
62
|
+
EOS
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def class_inheritable_accessor(*syms)
|
67
|
+
class_inheritable_reader(*syms)
|
68
|
+
class_inheritable_writer(*syms)
|
69
|
+
end
|
70
|
+
|
71
|
+
def class_inheritable_array(*syms)
|
72
|
+
class_inheritable_reader(*syms)
|
73
|
+
class_inheritable_array_writer(*syms)
|
74
|
+
end
|
75
|
+
|
76
|
+
def class_inheritable_hash(*syms)
|
77
|
+
class_inheritable_reader(*syms)
|
78
|
+
class_inheritable_hash_writer(*syms)
|
79
|
+
end
|
80
|
+
|
81
|
+
def inheritable_attributes
|
82
|
+
@inheritable_attributes ||= {}
|
83
|
+
end
|
84
|
+
|
85
|
+
def write_inheritable_attribute(key, value)
|
86
|
+
inheritable_attributes[key] = value
|
87
|
+
end
|
88
|
+
|
89
|
+
def write_inheritable_array(key, elements)
|
90
|
+
write_inheritable_attribute(key, []) if read_inheritable_attribute(key).nil?
|
91
|
+
write_inheritable_attribute(key, read_inheritable_attribute(key) + elements)
|
92
|
+
end
|
93
|
+
|
94
|
+
def write_inheritable_hash(key, hash)
|
95
|
+
write_inheritable_attribute(key, {}) if read_inheritable_attribute(key).nil?
|
96
|
+
write_inheritable_attribute(key, read_inheritable_attribute(key).merge(hash))
|
97
|
+
end
|
98
|
+
|
99
|
+
def read_inheritable_attribute(key)
|
100
|
+
inheritable_attributes[key]
|
101
|
+
end
|
102
|
+
|
103
|
+
def reset_inheritable_attributes
|
104
|
+
inheritable_attributes.clear
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
def inherited_with_inheritable_attributes(child)
|
109
|
+
inherited_without_inheritable_attributes(child) if respond_to?(:inherited_without_inheritable_attributes)
|
110
|
+
child.instance_variable_set('@inheritable_attributes', inheritable_attributes.dup)
|
111
|
+
end
|
112
|
+
|
113
|
+
alias inherited_without_inheritable_attributes inherited
|
114
|
+
alias inherited inherited_with_inheritable_attributes
|
115
|
+
end
|