activesupport-refinements 0.0.1
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 +17 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +32 -0
- data/Rakefile +1 -0
- data/activesupport-refinements.gemspec +21 -0
- data/lib/active_support/refinements/core_ext/array.rb +7 -0
- data/lib/active_support/refinements/core_ext/array/access.rb +56 -0
- data/lib/active_support/refinements/core_ext/array/conversions.rb +224 -0
- data/lib/active_support/refinements/core_ext/array/extract_options.rb +31 -0
- data/lib/active_support/refinements/core_ext/array/grouping.rb +101 -0
- data/lib/active_support/refinements/core_ext/array/prepend_and_append.rb +9 -0
- data/lib/active_support/refinements/core_ext/array/uniq_by.rb +21 -0
- data/lib/active_support/refinements/core_ext/array/wrap.rb +48 -0
- data/lib/active_support/refinements/core_ext/benchmark.rb +7 -0
- data/lib/active_support/refinements/core_ext/big_decimal.rb +1 -0
- data/lib/active_support/refinements/core_ext/big_decimal/conversions.rb +32 -0
- data/lib/active_support/refinements/core_ext/class.rb +4 -0
- data/lib/active_support/refinements/core_ext/class/attribute.rb +119 -0
- data/lib/active_support/refinements/core_ext/class/attribute_accessors.rb +172 -0
- data/lib/active_support/refinements/core_ext/class/delegating_attributes.rb +42 -0
- data/lib/active_support/refinements/core_ext/class/subclasses.rb +44 -0
- data/lib/active_support/refinements/core_ext/date.rb +5 -0
- data/lib/active_support/refinements/core_ext/date/acts_like.rb +10 -0
- data/lib/active_support/refinements/core_ext/date/calculations.rb +123 -0
- data/lib/active_support/refinements/core_ext/date/conversions.rb +86 -0
- data/lib/active_support/refinements/core_ext/date/zones.rb +17 -0
- data/lib/active_support/refinements/core_ext/date_and_time/calculations.rb +232 -0
- data/lib/active_support/refinements/core_ext/date_time.rb +4 -0
- data/lib/active_support/refinements/core_ext/date_time/acts_like.rb +15 -0
- data/lib/active_support/refinements/core_ext/date_time/calculations.rb +143 -0
- data/lib/active_support/refinements/core_ext/date_time/conversions.rb +93 -0
- data/lib/active_support/refinements/core_ext/date_time/zones.rb +26 -0
- data/lib/active_support/refinements/core_ext/enumerable.rb +82 -0
- data/lib/active_support/refinements/core_ext/exception.rb +5 -0
- data/lib/active_support/refinements/core_ext/file.rb +1 -0
- data/lib/active_support/refinements/core_ext/file/atomic.rb +60 -0
- data/lib/active_support/refinements/core_ext/hash.rb +8 -0
- data/lib/active_support/refinements/core_ext/hash/conversions.rb +161 -0
- data/lib/active_support/refinements/core_ext/hash/deep_merge.rb +29 -0
- data/lib/active_support/refinements/core_ext/hash/diff.rb +15 -0
- data/lib/active_support/refinements/core_ext/hash/except.rb +17 -0
- data/lib/active_support/refinements/core_ext/hash/indifferent_access.rb +24 -0
- data/lib/active_support/refinements/core_ext/hash/keys.rb +140 -0
- data/lib/active_support/refinements/core_ext/hash/reverse_merge.rb +24 -0
- data/lib/active_support/refinements/core_ext/hash/slice.rb +42 -0
- data/lib/active_support/refinements/core_ext/integer.rb +3 -0
- data/lib/active_support/refinements/core_ext/integer/inflections.rb +31 -0
- data/lib/active_support/refinements/core_ext/integer/multiple.rb +12 -0
- data/lib/active_support/refinements/core_ext/integer/time.rb +43 -0
- data/lib/active_support/refinements/core_ext/kernel.rb +4 -0
- data/lib/active_support/refinements/core_ext/kernel/agnostics.rb +13 -0
- data/lib/active_support/refinements/core_ext/kernel/debugger.rb +12 -0
- data/lib/active_support/refinements/core_ext/kernel/reporting.rb +97 -0
- data/lib/active_support/refinements/core_ext/kernel/singleton_class.rb +8 -0
- data/lib/active_support/refinements/core_ext/load_error.rb +27 -0
- data/lib/active_support/refinements/core_ext/logger.rb +86 -0
- data/lib/active_support/refinements/core_ext/module.rb +10 -0
- data/lib/active_support/refinements/core_ext/module/aliasing.rb +69 -0
- data/lib/active_support/refinements/core_ext/module/anonymous.rb +21 -0
- data/lib/active_support/refinements/core_ext/module/attr_internal.rb +40 -0
- data/lib/active_support/refinements/core_ext/module/attribute_accessors.rb +68 -0
- data/lib/active_support/refinements/core_ext/module/delegation.rb +172 -0
- data/lib/active_support/refinements/core_ext/module/deprecation.rb +27 -0
- data/lib/active_support/refinements/core_ext/module/introspection.rb +80 -0
- data/lib/active_support/refinements/core_ext/module/qualified_const.rb +54 -0
- data/lib/active_support/refinements/core_ext/module/reachable.rb +10 -0
- data/lib/active_support/refinements/core_ext/module/remove_method.rb +14 -0
- data/lib/active_support/refinements/core_ext/name_error.rb +20 -0
- data/lib/active_support/refinements/core_ext/numeric.rb +3 -0
- data/lib/active_support/refinements/core_ext/numeric/bytes.rb +46 -0
- data/lib/active_support/refinements/core_ext/numeric/conversions.rb +137 -0
- data/lib/active_support/refinements/core_ext/numeric/time.rb +81 -0
- data/lib/active_support/refinements/core_ext/object.rb +14 -0
- data/lib/active_support/refinements/core_ext/object/acts_like.rb +12 -0
- data/lib/active_support/refinements/core_ext/object/blank.rb +107 -0
- data/lib/active_support/refinements/core_ext/object/conversions.rb +4 -0
- data/lib/active_support/refinements/core_ext/object/deep_dup.rb +48 -0
- data/lib/active_support/refinements/core_ext/object/duplicable.rb +92 -0
- data/lib/active_support/refinements/core_ext/object/inclusion.rb +27 -0
- data/lib/active_support/refinements/core_ext/object/instance_variables.rb +30 -0
- data/lib/active_support/refinements/core_ext/object/to_json.rb +27 -0
- data/lib/active_support/refinements/core_ext/object/to_param.rb +60 -0
- data/lib/active_support/refinements/core_ext/object/to_query.rb +29 -0
- data/lib/active_support/refinements/core_ext/object/try.rb +72 -0
- data/lib/active_support/refinements/core_ext/object/with_options.rb +44 -0
- data/lib/active_support/refinements/core_ext/proc.rb +19 -0
- data/lib/active_support/refinements/core_ext/range.rb +3 -0
- data/lib/active_support/refinements/core_ext/range/conversions.rb +21 -0
- data/lib/active_support/refinements/core_ext/range/include_range.rb +23 -0
- data/lib/active_support/refinements/core_ext/range/overlaps.rb +10 -0
- data/lib/active_support/refinements/core_ext/regexp.rb +7 -0
- data/lib/active_support/refinements/core_ext/string.rb +13 -0
- data/lib/active_support/refinements/core_ext/string/access.rb +106 -0
- data/lib/active_support/refinements/core_ext/string/behavior.rb +8 -0
- data/lib/active_support/refinements/core_ext/string/conversions.rb +60 -0
- data/lib/active_support/refinements/core_ext/string/encoding.rb +10 -0
- data/lib/active_support/refinements/core_ext/string/exclude.rb +13 -0
- data/lib/active_support/refinements/core_ext/string/filters.rb +54 -0
- data/lib/active_support/refinements/core_ext/string/indent.rb +45 -0
- data/lib/active_support/refinements/core_ext/string/inflections.rb +214 -0
- data/lib/active_support/refinements/core_ext/string/inquiry.rb +15 -0
- data/lib/active_support/refinements/core_ext/string/multibyte.rb +58 -0
- data/lib/active_support/refinements/core_ext/string/output_safety.rb +194 -0
- data/lib/active_support/refinements/core_ext/string/starts_ends_with.rb +6 -0
- data/lib/active_support/refinements/core_ext/string/strip.rb +28 -0
- data/lib/active_support/refinements/core_ext/string/xchar.rb +18 -0
- data/lib/active_support/refinements/core_ext/time.rb +5 -0
- data/lib/active_support/refinements/core_ext/time/acts_like.rb +10 -0
- data/lib/active_support/refinements/core_ext/time/calculations.rb +251 -0
- data/lib/active_support/refinements/core_ext/time/conversions.rb +65 -0
- data/lib/active_support/refinements/core_ext/time/marshal.rb +30 -0
- data/lib/active_support/refinements/core_ext/time/zones.rb +98 -0
- data/lib/active_support/refinements/core_ext/uri.rb +28 -0
- data/lib/activesupport-refinements.rb +9 -0
- data/lib/activesupport-refinements/version.rb +5 -0
- data/refine_core_ext.rb +45 -0
- data/spec/hwia_spec.rb +15 -0
- data/spec/try_spec.rb +18 -0
- metadata +182 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module ObjectExt; end; module ObjectExt::DeepDup
|
|
2
|
+
require 'active_support/refinements/core_ext/object/duplicable'
|
|
3
|
+
|
|
4
|
+
refine Object do
|
|
5
|
+
# Returns a deep copy of object if it's duplicable. If it's
|
|
6
|
+
# not duplicable, returns +self+.
|
|
7
|
+
#
|
|
8
|
+
# object = Object.new
|
|
9
|
+
# dup = object.deep_dup
|
|
10
|
+
# dup.instance_variable_set(:@a, 1)
|
|
11
|
+
#
|
|
12
|
+
# object.instance_variable_defined?(:@a) #=> false
|
|
13
|
+
# dup.instance_variable_defined?(:@a) #=> true
|
|
14
|
+
def deep_dup
|
|
15
|
+
duplicable? ? dup : self
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
refine Array do
|
|
20
|
+
# Returns a deep copy of array.
|
|
21
|
+
#
|
|
22
|
+
# array = [1, [2, 3]]
|
|
23
|
+
# dup = array.deep_dup
|
|
24
|
+
# dup[1][2] = 4
|
|
25
|
+
#
|
|
26
|
+
# array[1][2] #=> nil
|
|
27
|
+
# dup[1][2] #=> 4
|
|
28
|
+
def deep_dup
|
|
29
|
+
map { |it| it.deep_dup }
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
refine Hash do
|
|
34
|
+
# Returns a deep copy of hash.
|
|
35
|
+
#
|
|
36
|
+
# hash = { a: { b: 'b' } }
|
|
37
|
+
# dup = hash.deep_dup
|
|
38
|
+
# dup[:a][:c] = 'c'
|
|
39
|
+
#
|
|
40
|
+
# hash[:a][:c] #=> nil
|
|
41
|
+
# dup[:a][:c] #=> "c"
|
|
42
|
+
def deep_dup
|
|
43
|
+
each_with_object(dup) do |(key, value), hash|
|
|
44
|
+
hash[key.deep_dup] = value.deep_dup
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
module ObjectExt; end; module ObjectExt::Duplicable
|
|
2
|
+
#--
|
|
3
|
+
# Most objects are cloneable, but not all. For example you can't dup +nil+:
|
|
4
|
+
#
|
|
5
|
+
# nil.dup # => TypeError: can't dup NilClass
|
|
6
|
+
#
|
|
7
|
+
# Classes may signal their instances are not duplicable removing +dup+/+clone+
|
|
8
|
+
# or raising exceptions from them. So, to dup an arbitrary object you normally
|
|
9
|
+
# use an optimistic approach and are ready to catch an exception, say:
|
|
10
|
+
#
|
|
11
|
+
# arbitrary_object.dup rescue object
|
|
12
|
+
#
|
|
13
|
+
# Rails dups objects in a few critical spots where they are not that arbitrary.
|
|
14
|
+
# That rescue is very expensive (like 40 times slower than a predicate), and it
|
|
15
|
+
# is often triggered.
|
|
16
|
+
#
|
|
17
|
+
# That's why we hardcode the following cases and check duplicable? instead of
|
|
18
|
+
# using that rescue idiom.
|
|
19
|
+
#++
|
|
20
|
+
refine Object do
|
|
21
|
+
# Can you safely dup this object?
|
|
22
|
+
#
|
|
23
|
+
# False for +nil+, +false+, +true+, symbol, and number objects;
|
|
24
|
+
# true otherwise.
|
|
25
|
+
def duplicable?
|
|
26
|
+
true
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
refine NilClass do
|
|
31
|
+
# +nil+ is not duplicable:
|
|
32
|
+
#
|
|
33
|
+
# nil.duplicable? # => false
|
|
34
|
+
# nil.dup # => TypeError: can't dup NilClass
|
|
35
|
+
def duplicable?
|
|
36
|
+
false
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
refine FalseClass do
|
|
41
|
+
# +false+ is not duplicable:
|
|
42
|
+
#
|
|
43
|
+
# false.duplicable? # => false
|
|
44
|
+
# false.dup # => TypeError: can't dup FalseClass
|
|
45
|
+
def duplicable?
|
|
46
|
+
false
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
refine TrueClass do
|
|
51
|
+
# +true+ is not duplicable:
|
|
52
|
+
#
|
|
53
|
+
# true.duplicable? # => false
|
|
54
|
+
# true.dup # => TypeError: can't dup TrueClass
|
|
55
|
+
def duplicable?
|
|
56
|
+
false
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
refine Symbol do
|
|
61
|
+
# Symbols are not duplicable:
|
|
62
|
+
#
|
|
63
|
+
# :my_symbol.duplicable? # => false
|
|
64
|
+
# :my_symbol.dup # => TypeError: can't dup Symbol
|
|
65
|
+
def duplicable?
|
|
66
|
+
false
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
refine Numeric do
|
|
71
|
+
# Numbers are not duplicable:
|
|
72
|
+
#
|
|
73
|
+
# 3.duplicable? # => false
|
|
74
|
+
# 3.dup # => TypeError: can't dup Fixnum
|
|
75
|
+
def duplicable?
|
|
76
|
+
false
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
require 'bigdecimal'
|
|
81
|
+
refine BigDecimal do
|
|
82
|
+
begin
|
|
83
|
+
BigDecimal.new('4.56').dup
|
|
84
|
+
|
|
85
|
+
def duplicable?
|
|
86
|
+
true
|
|
87
|
+
end
|
|
88
|
+
rescue TypeError
|
|
89
|
+
# can't dup, so use superclass implementation
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module ObjectExt; end; module ObjectExt::Inclusion
|
|
2
|
+
refine Object do
|
|
3
|
+
# Returns true if this object is included in the argument(s). Argument must be
|
|
4
|
+
# any object which responds to +#include?+ or optionally, multiple arguments can be passed in. Usage:
|
|
5
|
+
#
|
|
6
|
+
# characters = ['Konata', 'Kagami', 'Tsukasa']
|
|
7
|
+
# 'Konata'.in?(characters) # => true
|
|
8
|
+
#
|
|
9
|
+
# character = 'Konata'
|
|
10
|
+
# character.in?('Konata', 'Kagami', 'Tsukasa') # => true
|
|
11
|
+
#
|
|
12
|
+
# This will throw an ArgumentError if a single argument is passed in and it doesn't respond
|
|
13
|
+
# to +#include?+.
|
|
14
|
+
def in?(*args)
|
|
15
|
+
if args.length > 1
|
|
16
|
+
args.include? self
|
|
17
|
+
else
|
|
18
|
+
another_object = args.first
|
|
19
|
+
if another_object.respond_to? :include?
|
|
20
|
+
another_object.include? self
|
|
21
|
+
else
|
|
22
|
+
raise ArgumentError.new 'The single parameter passed to #in? must respond to #include?'
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module ObjectExt; end; module ObjectExt::InstanceVariables
|
|
2
|
+
refine Object do
|
|
3
|
+
# Returns a hash with string keys that maps instance variable names without "@" to their
|
|
4
|
+
# corresponding values.
|
|
5
|
+
#
|
|
6
|
+
# class C
|
|
7
|
+
# def initialize(x, y)
|
|
8
|
+
# @x, @y = x, y
|
|
9
|
+
# end
|
|
10
|
+
# end
|
|
11
|
+
#
|
|
12
|
+
# C.new(0, 1).instance_values # => {"x" => 0, "y" => 1}
|
|
13
|
+
def instance_values
|
|
14
|
+
Hash[instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Returns an array of instance variable names including "@".
|
|
18
|
+
#
|
|
19
|
+
# class C
|
|
20
|
+
# def initialize(x, y)
|
|
21
|
+
# @x, @y = x, y
|
|
22
|
+
# end
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
25
|
+
# C.new(0, 1).instance_variable_names # => ["@y", "@x"]
|
|
26
|
+
def instance_variable_names
|
|
27
|
+
instance_variables.map { |var| var.to_s }
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Hack to load json gem first so we can overwrite its to_json.
|
|
2
|
+
begin
|
|
3
|
+
require 'json'
|
|
4
|
+
rescue LoadError
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
# The JSON gem adds a few modules to Ruby core classes containing :to_json definition, overwriting
|
|
8
|
+
# their default behavior. That said, we need to define the basic to_json method in all of them,
|
|
9
|
+
# otherwise they will always use to_json gem implementation, which is backwards incompatible in
|
|
10
|
+
# several cases (for instance, the JSON implementation for Hash does not work) with inheritance
|
|
11
|
+
# and consequently classes as ActiveSupport::OrderedHash cannot be serialized to json.
|
|
12
|
+
[Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].each do |klass|
|
|
13
|
+
klass.class_eval do
|
|
14
|
+
# Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info.
|
|
15
|
+
def to_json(options = nil)
|
|
16
|
+
ActiveSupport::JSON.encode(self, options)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
module Process
|
|
22
|
+
class Status
|
|
23
|
+
def as_json(options = nil)
|
|
24
|
+
{ :exitstatus => exitstatus, :pid => pid }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module ObjectExt; end; module ObjectExt::ToParam
|
|
2
|
+
refine Object do
|
|
3
|
+
# Alias of <tt>to_s</tt>.
|
|
4
|
+
def to_param
|
|
5
|
+
to_s
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
refine NilClass do
|
|
10
|
+
# Returns +self+.
|
|
11
|
+
def to_param
|
|
12
|
+
self
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
refine TrueClass do
|
|
17
|
+
# Returns +self+.
|
|
18
|
+
def to_param
|
|
19
|
+
self
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
refine FalseClass do
|
|
24
|
+
# Returns +self+.
|
|
25
|
+
def to_param
|
|
26
|
+
self
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
refine Array do
|
|
31
|
+
# Calls <tt>to_param</tt> on all its elements and joins the result with
|
|
32
|
+
# slashes. This is used by <tt>url_for</tt> in Action Pack.
|
|
33
|
+
def to_param
|
|
34
|
+
collect { |e| e.to_param }.join '/'
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
refine Hash do
|
|
39
|
+
# Returns a string representation of the receiver suitable for use as a URL
|
|
40
|
+
# query string:
|
|
41
|
+
#
|
|
42
|
+
# {name: 'David', nationality: 'Danish'}.to_param
|
|
43
|
+
# # => "name=David&nationality=Danish"
|
|
44
|
+
#
|
|
45
|
+
# An optional namespace can be passed to enclose the param names:
|
|
46
|
+
#
|
|
47
|
+
# {name: 'David', nationality: 'Danish'}.to_param('user')
|
|
48
|
+
# # => "user[name]=David&user[nationality]=Danish"
|
|
49
|
+
#
|
|
50
|
+
# The string pairs "key=value" that conform the query string
|
|
51
|
+
# are sorted lexicographically in ascending order.
|
|
52
|
+
#
|
|
53
|
+
# This method is also aliased as +to_query+.
|
|
54
|
+
def to_param(namespace = nil)
|
|
55
|
+
collect do |key, value|
|
|
56
|
+
value.to_query(namespace ? "#{namespace}[#{key}]" : key)
|
|
57
|
+
end.sort * '&'
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module ObjectExt; end; module ObjectExt::ToQuery
|
|
2
|
+
require 'active_support/refinements/core_ext/object/to_param'
|
|
3
|
+
|
|
4
|
+
refine Object do
|
|
5
|
+
# Converts an object into a string suitable for use as a URL query string, using the given <tt>key</tt> as the
|
|
6
|
+
# param name.
|
|
7
|
+
#
|
|
8
|
+
# Note: This method is defined as a default implementation for all Objects for Hash#to_query to work.
|
|
9
|
+
def to_query(key)
|
|
10
|
+
require 'cgi' unless defined?(CGI) && defined?(CGI::escape)
|
|
11
|
+
"#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}"
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
refine Array do
|
|
16
|
+
# Converts an array into a string suitable for use as a URL query string,
|
|
17
|
+
# using the given +key+ as the param name.
|
|
18
|
+
#
|
|
19
|
+
# ['Rails', 'coding'].to_query('hobbies') # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
|
|
20
|
+
def to_query(key)
|
|
21
|
+
prefix = "#{key}[]"
|
|
22
|
+
collect { |value| value.to_query(prefix) }.join '&'
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
refine Hash do
|
|
27
|
+
# alias_method :to_query, :to_param
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module ObjectExt; end; module ObjectExt::Try
|
|
2
|
+
refine Object do
|
|
3
|
+
# Invokes the public method identified by the symbol +method+, passing it any arguments
|
|
4
|
+
# and/or the block specified, just like the regular Ruby <tt>Object#public_send</tt> does.
|
|
5
|
+
#
|
|
6
|
+
# *Unlike* that method however, a +NoMethodError+ exception will *not* be raised
|
|
7
|
+
# and +nil+ will be returned instead, if the receiving object is a +nil+ object or NilClass.
|
|
8
|
+
#
|
|
9
|
+
# This is also true if the receiving object does not implemented the tried method. It will
|
|
10
|
+
# return +nil+ in that case as well.
|
|
11
|
+
#
|
|
12
|
+
# If try is called without a method to call, it will yield any given block with the object.
|
|
13
|
+
#
|
|
14
|
+
# Please also note that +try+ is defined on +Object+, therefore it won't work with
|
|
15
|
+
# subclasses of +BasicObject+. For example, using try with +SimpleDelegator+ will
|
|
16
|
+
# delegate +try+ to target instead of calling it on delegator itself.
|
|
17
|
+
#
|
|
18
|
+
# Without +try+
|
|
19
|
+
# @person && @person.name
|
|
20
|
+
# or
|
|
21
|
+
# @person ? @person.name : nil
|
|
22
|
+
#
|
|
23
|
+
# With +try+
|
|
24
|
+
# @person.try(:name)
|
|
25
|
+
#
|
|
26
|
+
# +try+ also accepts arguments and/or a block, for the method it is trying
|
|
27
|
+
# Person.try(:find, 1)
|
|
28
|
+
# @people.try(:collect) {|p| p.name}
|
|
29
|
+
#
|
|
30
|
+
# Without a method argument try will yield to the block unless the receiver is nil.
|
|
31
|
+
# @person.try { |p| "#{p.first_name} #{p.last_name}" }
|
|
32
|
+
#
|
|
33
|
+
# +try+ behaves like +Object#public_send+, unless called on +NilClass+.
|
|
34
|
+
def try(*a, &b)
|
|
35
|
+
if a.empty? && block_given?
|
|
36
|
+
yield self
|
|
37
|
+
else
|
|
38
|
+
public_send(*a, &b) if respond_to?(a.first)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Same as #try, but will raise a NoMethodError exception if the receiving is not nil and
|
|
43
|
+
# does not implemented the tried method.
|
|
44
|
+
def try!(*a, &b)
|
|
45
|
+
if a.empty? && block_given?
|
|
46
|
+
yield self
|
|
47
|
+
else
|
|
48
|
+
public_send(*a, &b)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
refine NilClass do
|
|
54
|
+
# Calling +try+ on +nil+ always returns +nil+.
|
|
55
|
+
# It becomes specially helpful when navigating through associations that may return +nil+.
|
|
56
|
+
#
|
|
57
|
+
# nil.try(:name) # => nil
|
|
58
|
+
#
|
|
59
|
+
# Without +try+
|
|
60
|
+
# @person && !@person.children.blank? && @person.children.first.name
|
|
61
|
+
#
|
|
62
|
+
# With +try+
|
|
63
|
+
# @person.try(:children).try(:first).try(:name)
|
|
64
|
+
def try(*args)
|
|
65
|
+
nil
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def try!(*args)
|
|
69
|
+
nil
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module ObjectExt; end; module ObjectExt::WithOptions
|
|
2
|
+
require 'active_support/option_merger'
|
|
3
|
+
|
|
4
|
+
refine Object do
|
|
5
|
+
# An elegant way to factor duplication out of options passed to a series of
|
|
6
|
+
# method calls. Each method called in the block, with the block variable as
|
|
7
|
+
# the receiver, will have its options merged with the default +options+ hash
|
|
8
|
+
# provided. Each method called on the block variable must take an options
|
|
9
|
+
# hash as its final argument.
|
|
10
|
+
#
|
|
11
|
+
# Without <tt>with_options></tt>, this code contains duplication:
|
|
12
|
+
#
|
|
13
|
+
# class Account < ActiveRecord::Base
|
|
14
|
+
# has_many :customers, dependent: :destroy
|
|
15
|
+
# has_many :products, dependent: :destroy
|
|
16
|
+
# has_many :invoices, dependent: :destroy
|
|
17
|
+
# has_many :expenses, dependent: :destroy
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# Using <tt>with_options</tt>, we can remove the duplication:
|
|
21
|
+
#
|
|
22
|
+
# class Account < ActiveRecord::Base
|
|
23
|
+
# with_options dependent: :destroy do |assoc|
|
|
24
|
+
# assoc.has_many :customers
|
|
25
|
+
# assoc.has_many :products
|
|
26
|
+
# assoc.has_many :invoices
|
|
27
|
+
# assoc.has_many :expenses
|
|
28
|
+
# end
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
# It can also be used with an explicit receiver:
|
|
32
|
+
#
|
|
33
|
+
# I18n.with_options locale: user.locale, scope: 'newsletter' do |i18n|
|
|
34
|
+
# subject i18n.t :subject
|
|
35
|
+
# body i18n.t :body, user_name: user.name
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
# <tt>with_options</tt> can also be nested since the call is forwarded to its receiver.
|
|
39
|
+
# Each nesting level will merge inherited defaults in addition to their own.
|
|
40
|
+
def with_options(options)
|
|
41
|
+
yield ActiveSupport::OptionMerger.new(self, options)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module ProcExt
|
|
2
|
+
require "active_support/core_ext/kernel/singleton_class"
|
|
3
|
+
require "active_support/deprecation"
|
|
4
|
+
|
|
5
|
+
refine Proc do
|
|
6
|
+
def bind(object)
|
|
7
|
+
ActiveSupport::Deprecation.warn 'Proc#bind is deprecated and will be removed in future versions', caller
|
|
8
|
+
|
|
9
|
+
block, time = self, Time.now
|
|
10
|
+
object.class_eval do
|
|
11
|
+
method_name = "__bind_#{time.to_i}_#{time.usec}"
|
|
12
|
+
define_method(method_name, &block)
|
|
13
|
+
method = instance_method(method_name)
|
|
14
|
+
remove_method(method_name)
|
|
15
|
+
method
|
|
16
|
+
end.bind(object)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|