reactive_support 0.1.2
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.
- checksums.yaml +7 -0
- data/CONTRIBUTING.md +162 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +92 -0
- data/files.rb +19 -0
- data/lib/extensions/reactive_extensions.rb +41 -0
- data/lib/reactive_support/core_ext/array/access.rb +34 -0
- data/lib/reactive_support/core_ext/object/blank.rb +189 -0
- data/lib/reactive_support/core_ext/object/deep_dup.rb +54 -0
- data/lib/reactive_support/core_ext/object/duplicable.rb +39 -0
- data/lib/reactive_support/core_ext/object/exist.rb +14 -0
- data/lib/reactive_support/core_ext/object/inclusion.rb +39 -0
- data/lib/reactive_support/core_ext/object/instance_variables.rb +37 -0
- data/lib/reactive_support/core_ext/object/try.rb +46 -0
- data/lib/reactive_support/extensions/reactive_extensions.rb +41 -0
- data/lib/reactive_support.rb +15 -0
- data/reactive_support.gemspec +39 -0
- data/spec/array_spec.rb +71 -0
- data/spec/reactive_extensions_spec.rb +24 -0
- data/spec/reactive_support_spec.rb +314 -0
- data/spec/spec_helper.rb +18 -0
- data/version.rb +14 -0
- metadata +130 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
class Object
|
2
|
+
|
3
|
+
# The +#exists?+ method and its alias, +#exist?+, return +true+ if the object
|
4
|
+
# calling the method is not +nil+.
|
5
|
+
#
|
6
|
+
# 'foobar'.exists? # => true
|
7
|
+
# nil.exists? # => false
|
8
|
+
|
9
|
+
def exists?
|
10
|
+
!self.nil?
|
11
|
+
end
|
12
|
+
|
13
|
+
alias_method :exist?, :exists?
|
14
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class Object
|
2
|
+
|
3
|
+
# The +#in?+ method returns +true+ if the calling object is included in the
|
4
|
+
# +object+ passed as a parameter. The +object+ parameter must be a String,
|
5
|
+
# Enumerable, or other object that responds to +#include?+. If it doesn't,
|
6
|
+
# the #in? method will raise an ArgumentError.
|
7
|
+
#
|
8
|
+
# When passed an Array object, +#in?+ returns +true+ if the calling object
|
9
|
+
# is included as a member of the array:
|
10
|
+
#
|
11
|
+
# 'foo'.in? ['foo', 'bar'] # => true
|
12
|
+
# 'foo'.in? ['bar', 'baz'] # => false
|
13
|
+
#
|
14
|
+
# When passed a Hash object, +#in?+ returns true if the calling object is
|
15
|
+
# included as a key in the hash. To look for an object in a hash's values,
|
16
|
+
# use the hash's +#values+ method.
|
17
|
+
#
|
18
|
+
# 'foo'.in? {'foo' => 'bar'} # => true
|
19
|
+
# 'foo'.in? {'bar' => 'foo'} # => false
|
20
|
+
# 'foo'.in? {'bar' => 'foo'}.values # => true
|
21
|
+
#
|
22
|
+
# When passed a String object, +#in?+ returns +true+ if the the calling object
|
23
|
+
# (which must also be a string) appears verbatim within the parameter object.
|
24
|
+
# If the passed-in object is a string but the calling object is something else,
|
25
|
+
# a TypeError will be returned.
|
26
|
+
#
|
27
|
+
# 'foo'.in? 'foobar' # => true
|
28
|
+
# 'foo'.in? 'foto' # => false
|
29
|
+
# ['foo'].in? 'foobar' # => TypeError
|
30
|
+
#
|
31
|
+
# When passed an object that does not respond to +#include?+, +#in?+ raises
|
32
|
+
# an ArgumentError.
|
33
|
+
|
34
|
+
def in?(object)
|
35
|
+
object.include?(self)
|
36
|
+
rescue NoMethodError
|
37
|
+
raise ArgumentError.new("The parameter passed to #in? must respond to #include?")
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Object
|
2
|
+
# The +#instance_values+ method returns a hash mapping all the calling object's
|
3
|
+
# instance variable names to the variables' values. The hash keys are the
|
4
|
+
# variables' names, as strings, without the '@' prepended to them. Each of the
|
5
|
+
# hash's values is the value corresponding to the given variable name.
|
6
|
+
#
|
7
|
+
# class Widget
|
8
|
+
# def initialize(x,y)
|
9
|
+
# @x, @y = x, y
|
10
|
+
# end
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# widget = Widget.new('foo', 'bar')
|
14
|
+
# widget.instance_values # => {'x' => 'foo', 'y' => 'bar'}
|
15
|
+
|
16
|
+
def instance_values
|
17
|
+
Hash[instance_variables.map {|name| [name[1..-1], instance_variable_get(name) ] }]
|
18
|
+
end
|
19
|
+
|
20
|
+
# The +#instance_variable_names+ method returns an array of the names of
|
21
|
+
# the instance variables defined on the calling object. The names themselves
|
22
|
+
# are returned as strings and, unlike in the +#instance_values+ method,
|
23
|
+
# include the +'@'+ prefix.
|
24
|
+
#
|
25
|
+
# class Widget
|
26
|
+
# def initialize(x,y)
|
27
|
+
# @x, @y = x, y
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# widget = Widget.new(1, 2)
|
32
|
+
# widget.instance_variable_names # => ['@x', '@y']
|
33
|
+
|
34
|
+
def instance_variable_names
|
35
|
+
instance_variables.map {|name| name.to_s }
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Object
|
2
|
+
# The +#try+ method calls the given +method+ (with given +*args+ and +&block+)
|
3
|
+
# on the object calling it. The +#try+ method returns the output of the
|
4
|
+
# method or, if an error is raised, +nil+. It accepts an arbitrary number
|
5
|
+
# of arguments and an optional block, enabling it to be used with any method.
|
6
|
+
#
|
7
|
+
# The first argument is the name of the method to be called, given as a symbol.
|
8
|
+
# The rest are the arguments (if any) that should be passed into that
|
9
|
+
# method. Likewise, the +&block+ parameter will be passed on to the method
|
10
|
+
# being called.
|
11
|
+
#
|
12
|
+
# Examples of a method being called without args:
|
13
|
+
# 'foo'.try(:upcase) # => 'FOO'
|
14
|
+
# nil.try(:upcase) # => nil
|
15
|
+
#
|
16
|
+
# Examples of a method being called with args:
|
17
|
+
# %w(foo bar baz).try(:join, '.') # => 'foo.bar.baz'
|
18
|
+
# nil.try(:join, '.') # => nil
|
19
|
+
#
|
20
|
+
# Examples of a method being called with a block:
|
21
|
+
# { foo: 10, bar: 18, baz: 32 }.try(:reject!) {|k,v| v < 25 } # => { baz: 32 }
|
22
|
+
# nil.try(:reject) {|k,v| v == 'foo' } # => nil
|
23
|
+
#
|
24
|
+
# When called on +nil+, +#try+ returns +nil+ even if the method being sent
|
25
|
+
# is defined for NilClass:
|
26
|
+
# nil.try(:inspect) # => nil
|
27
|
+
#
|
28
|
+
# The +#try+ method can also be called with a block and no arguments. In this case,
|
29
|
+
# the block will be instance_eval'ed:
|
30
|
+
# 'foobar'.try { upcase.truncate(3) } # => 'FOO'
|
31
|
+
# nil.try { upcase.truncate(3) } # => nil
|
32
|
+
|
33
|
+
def try(*args, &block)
|
34
|
+
return self if self.nil?
|
35
|
+
|
36
|
+
if args.empty? && block_given?
|
37
|
+
if block.arity.zero?
|
38
|
+
instance_eval(&block)
|
39
|
+
else
|
40
|
+
yield self
|
41
|
+
end
|
42
|
+
else
|
43
|
+
public_send(*args, &block) if args.respond_to?(:first)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'reactive_support'
|
2
|
+
|
3
|
+
# The ReactiveExtensions module consists of methods I wish ActiveSupport provided.
|
4
|
+
# These methods do not adhere to the ActiveSupport API. If you wish to include
|
5
|
+
# them in your project, you will need to put this in your main project file:
|
6
|
+
# require 'reactive_support/extensions'
|
7
|
+
#
|
8
|
+
# ReactiveExtensions requires ReactiveSupport, so there is no need to require both
|
9
|
+
# explicitly.
|
10
|
+
|
11
|
+
module ReactiveExtensions
|
12
|
+
|
13
|
+
# The +#try_rescue+ method extends ReactiveSupport's +#try+ method so it
|
14
|
+
# rescues NoMethodErrors and TypeErrors as well as returning +nil+ when
|
15
|
+
# called on a +nil+ value.
|
16
|
+
#
|
17
|
+
# Like the +#try+ method, +#try_rescue+ takes 1 or more arguments. The first
|
18
|
+
# argument is the method to be called on the calling object, passed as a
|
19
|
+
# symbol. The others are zero or more arguments that will be passed through to
|
20
|
+
# that method, and +&block+ is an optional block that will be similarly passed through.
|
21
|
+
#
|
22
|
+
# Example of usage identical to +#try+:
|
23
|
+
# nil.try(:map) {|a| a.to_s } # => nil
|
24
|
+
# nil.try_rescue(:map) {|a| a.to_s } # => nil
|
25
|
+
#
|
26
|
+
# Example of usage calling a method that is not defined on the calling object:
|
27
|
+
# 10.try(:to_h) # => TypeError
|
28
|
+
# 10.try_rescue(:to_h) # => nil
|
29
|
+
#
|
30
|
+
# Example of usage with invalid arguments:
|
31
|
+
# %w(foo, bar, baz).try(:join, [:hello, :world]) # => TypeError
|
32
|
+
# %w(foo, bar, baz).try_rescue(:join, [:hello, :world]) # => nil
|
33
|
+
|
34
|
+
def try_rescue(*args, &block)
|
35
|
+
self.try(*args, &block) rescue nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Object
|
40
|
+
include ReactiveExtensions
|
41
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Dir['./lib/reactive_support/core_ext/object/**/*.rb'].each {|f| require f }
|
2
|
+
|
3
|
+
# The ReactiveSupport module implements methods from ActiveSupport. It can be
|
4
|
+
# included in Ruby's +Object+ class by adding +require 'reactive_support'+ to
|
5
|
+
# your project file. Then, ReactiveSupport methods can be called on any Ruby
|
6
|
+
# object just like the object's own methods.
|
7
|
+
#
|
8
|
+
# In this example, ReactiveSupport's #try method is called on an array:
|
9
|
+
# require 'reactive_support'
|
10
|
+
#
|
11
|
+
# arr = %w(foo, bar, baz)
|
12
|
+
# arr.try(:join, '.')
|
13
|
+
|
14
|
+
module ReactiveSupport
|
15
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.expand_path('../version.rb', __FILE__)
|
2
|
+
require File.expand_path('../files.rb', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.specification_version = 1 if s.respond_to? :specification_version=
|
6
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
7
|
+
s.required_ruby_version = '>= 1.9.3'
|
8
|
+
|
9
|
+
s.name = 'reactive_support'
|
10
|
+
s.version = ReactiveSupport.gem_version
|
11
|
+
s.date = '2014-09-24'
|
12
|
+
|
13
|
+
s.description = "ActiveSupport methods re-implemented independently of the Rails ecosystem"
|
14
|
+
s.summary = "ReactiveSupport provides useful ActiveSupport methods in a gem that is simple, stable, agnostic, and transparent."
|
15
|
+
|
16
|
+
s.authors = ["Dana Scheider"]
|
17
|
+
s.email = "dana.scheider@gmail.com"
|
18
|
+
|
19
|
+
# = MANIFEST =
|
20
|
+
s.files = ReactiveSupport.files
|
21
|
+
s.require_path = 'lib'
|
22
|
+
# = MANIFEST =
|
23
|
+
|
24
|
+
s.test_files = s.files.select {|path| path =~ /^spec\/.*.rb/ }
|
25
|
+
s.licenses = 'MIT'
|
26
|
+
|
27
|
+
s.extra_rdoc_files = %w[CONTRIBUTING.md README.md LICENSE]
|
28
|
+
|
29
|
+
s.add_development_dependency 'rspec', '~> 3.1'
|
30
|
+
s.add_development_dependency 'bundler', '~> 1.6'
|
31
|
+
s.add_development_dependency 'coveralls', '~> 0.7'
|
32
|
+
s.add_development_dependency 'simplecov', '~> 0.9'
|
33
|
+
|
34
|
+
s.has_rdoc = true
|
35
|
+
s.homepage = "http://github.com/danascheider/reactive_support"
|
36
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "ReactiveSupport"]
|
37
|
+
s.require_paths = %w[lib]
|
38
|
+
s.rubygems_version = '1.1.1'
|
39
|
+
end
|
data/spec/array_spec.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Array do
|
4
|
+
describe '#from method' do
|
5
|
+
context 'normal use' do
|
6
|
+
context 'positive position' do
|
7
|
+
it 'returns the end of the array' do
|
8
|
+
expect([1, 2, 3, 4, 5].from(2)).to eql [3, 4, 5]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'negative position' do
|
13
|
+
it 'returns the end of the array' do
|
14
|
+
expect([1, 2, 3, 4, 5].from(-2)).to eql [4, 5]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'when array is empty' do
|
20
|
+
it 'returns an empty array' do
|
21
|
+
expect([].from(0)).to eql []
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'position higher than max index' do
|
26
|
+
it 'returns an empty array' do
|
27
|
+
expect([1, 2, 3, 4, 5].from(100)).to eql []
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'position lower than min index' do
|
32
|
+
it 'returns an empty array' do
|
33
|
+
expect([1, 2, 3].from(-4)).to eql []
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#to method' do
|
39
|
+
context 'normal use' do
|
40
|
+
context 'positive position' do
|
41
|
+
it 'returns the beginning of the array' do
|
42
|
+
expect([1, 2, 3, 4, 5].to(2)). to eql [1, 2, 3]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'negative position' do
|
47
|
+
it 'returns the beginning of the array' do
|
48
|
+
expect([1, 2, 3, 4, 5].to(-2)).to eql [1, 2, 3, 4]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when array is empty' do
|
54
|
+
it 'returns an empty array' do
|
55
|
+
expect([].to(0)).to eql []
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'position higher than max index' do
|
60
|
+
it 'returns the whole array' do
|
61
|
+
expect([1, 2, 3].to(10)).to eql [1, 2, 3]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'position lower than min index' do
|
66
|
+
it 'returns an empty array' do
|
67
|
+
expect([1, 2, 3].to(-5)).to eql []
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ReactiveExtensions do
|
4
|
+
|
5
|
+
describe '#try_rescue method' do
|
6
|
+
context 'when self is nil' do
|
7
|
+
it 'returns nil' do
|
8
|
+
expect(nil.try_rescue(:collect) {|i| i + 2 }).to eql nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'when the method can be executed successfully' do
|
13
|
+
it 'calls the method' do
|
14
|
+
expect('foo'.try_rescue(:upcase)).to eql 'FOO'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'when a NoMethodError is raised' do
|
19
|
+
it 'returns nil' do
|
20
|
+
expect(('foo').try_rescue(:bar)).to eql nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,314 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ReactiveSupport do
|
4
|
+
describe '#blank? method' do
|
5
|
+
context 'when true' do
|
6
|
+
hash = {
|
7
|
+
'empty string' => '',
|
8
|
+
'whitespace string' => ' ',
|
9
|
+
'FalseClass' => false,
|
10
|
+
'NilClass' => nil,
|
11
|
+
'empty array' => [],
|
12
|
+
'empty hash' => {}
|
13
|
+
}
|
14
|
+
|
15
|
+
hash.each do |k,v|
|
16
|
+
specify "#{k} returns true" do
|
17
|
+
expect(v.blank?).to be true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when false' do
|
23
|
+
hash = {
|
24
|
+
'non-blank object' => 'foo',
|
25
|
+
'TrueClass' => true,
|
26
|
+
'enumerable with blank members' => [nil, false],
|
27
|
+
'numeric' => 10
|
28
|
+
}
|
29
|
+
|
30
|
+
hash.each do |k,v|
|
31
|
+
specify "#{k} returns false" do
|
32
|
+
expect(v.blank?).to be false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#deep_dup method' do
|
39
|
+
context 'duplicable object' do
|
40
|
+
before(:each) do
|
41
|
+
@str = 'foo'
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns a duplicate' do
|
45
|
+
expect(@str.deep_dup).not_to be @str
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'does not affect the original' do
|
49
|
+
@str.deep_dup.instance_variable_set(:@a, 1)
|
50
|
+
expect(@string.instance_variable_get(:@a)).to eql nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'non-duplicable object' do
|
55
|
+
it 'returns itself' do
|
56
|
+
num = 10
|
57
|
+
expect(num.deep_dup).to be num
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'array' do
|
62
|
+
it 'does not affect the original' do
|
63
|
+
arr = [ [1, 2], 3 ]
|
64
|
+
arr.deep_dup[0][1] = 4
|
65
|
+
expect(arr[0][1]).to eql 2
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'hash' do
|
70
|
+
it 'does not affect the original' do
|
71
|
+
h = { foo: { bar: 1 } }
|
72
|
+
h.deep_dup[:foo][:bar] = 10
|
73
|
+
expect(h[:foo][:bar]).to eql 1
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe '#duplicable? method' do
|
79
|
+
context 'when true' do
|
80
|
+
it 'returns true' do
|
81
|
+
expect(['foo', 'bar', 'baz'].duplicable?).to be true
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'when false' do
|
86
|
+
hash = {
|
87
|
+
'NilClass' => nil,
|
88
|
+
'FalseClass' => false,
|
89
|
+
'TrueClass' => true,
|
90
|
+
'symbol' => :symbol,
|
91
|
+
'numeric' => 10,
|
92
|
+
'method' => method(:puts)
|
93
|
+
}
|
94
|
+
|
95
|
+
hash.each do |k,v|
|
96
|
+
specify "#{k} returns false" do
|
97
|
+
expect(v.duplicable?).to be false
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'BigDecimal' do
|
103
|
+
let(:dec) { BigDecimal.new('4.56') }
|
104
|
+
|
105
|
+
before(:each) do
|
106
|
+
@condition = !!(RUBY_VERSION =~ /^1\.9/ || RUBY_VERSION =~ /jruby/)
|
107
|
+
end
|
108
|
+
context 'Ruby version >= 2.0.0' do
|
109
|
+
it 'returns true' do
|
110
|
+
expect(dec.duplicable?).to be true unless @condition
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'Ruby version 1.9.x' do
|
115
|
+
it 'returns false' do
|
116
|
+
expect(dec.duplicable?).to be false if @condition
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'doesn\'t raise an error' do
|
120
|
+
expect{ dec.duplicable? }.not_to raise_error if @condition
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe '#exist? method' do
|
127
|
+
context 'existent object' do
|
128
|
+
it 'returns true' do
|
129
|
+
expect({foo: :bar}.exist?).to be true
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context 'nil' do
|
134
|
+
it 'returns false' do
|
135
|
+
expect(nil.exist?).to be false
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe '#exists? method' do
|
141
|
+
context 'existent object' do
|
142
|
+
it 'returns true' do
|
143
|
+
expect({foo: :bar}.exists?).to be true
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'nil' do
|
148
|
+
it 'returns false' do
|
149
|
+
expect(nil.exists?).to be false
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe '#in? method' do
|
155
|
+
context 'when true' do
|
156
|
+
hash = {
|
157
|
+
'array contains calling object' => ['foo', 'bar', 'baz'],
|
158
|
+
'hash contains the given key' => { 'foo' => 'bar' },
|
159
|
+
'string contains the given characters' => 'foolish'
|
160
|
+
}
|
161
|
+
|
162
|
+
hash.each do |k,v|
|
163
|
+
specify k do
|
164
|
+
expect('foo'.in? v).to be true
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context 'when false' do
|
170
|
+
hash = {
|
171
|
+
'array doesn\'t contain calling object' => ['bar', 'baz'],
|
172
|
+
'hash doesn\'t contain given key' => { bar: :baz },
|
173
|
+
'string doesn\'t contain given characters' => 'something else'
|
174
|
+
}
|
175
|
+
|
176
|
+
hash.each do |k,v|
|
177
|
+
specify k do
|
178
|
+
expect('foo'.in? v).to be false
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
context 'error' do
|
184
|
+
hash = {
|
185
|
+
'incompatible data types' => [{foo: 'bar'}, 'foobar', TypeError],
|
186
|
+
'invalid parameter' => [10, 1000, ArgumentError]
|
187
|
+
}
|
188
|
+
|
189
|
+
hash.each do |k,v|
|
190
|
+
specify k do
|
191
|
+
expect{ v[0].in? v[1] }.to raise_error(v[2])
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
describe '#instance_values method' do
|
198
|
+
before(:each) do
|
199
|
+
class C
|
200
|
+
def initialize(x,y)
|
201
|
+
@x, @y = x, y
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
@c = C.new('foo', 'bar')
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'returns a hash' do
|
209
|
+
expect(@c.instance_values).to be_a(Hash)
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'uses instance variable names without @ as keys' do
|
213
|
+
['x', 'y'].each {|var| expect(@c.instance_values).to have_key(var) }
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'returns variable values' do
|
217
|
+
[['x', 'foo'], ['y','bar']].each {|(var, val)| expect(@c.instance_values[var]). to eql val }
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
describe '#instance_variable_names method' do
|
222
|
+
before(:all) do
|
223
|
+
class C
|
224
|
+
def initialize(x, y)
|
225
|
+
@x, @y = x, y
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
@c = C.new(1, 2)
|
230
|
+
end
|
231
|
+
|
232
|
+
it 'returns an array' do
|
233
|
+
expect(@c.instance_variable_names).to be_an Array
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'includes the name of the instance variables' do
|
237
|
+
['@x', '@y'].each {|var| expect(@c.instance_variable_names).to include(var) }
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
describe '#present? method' do
|
242
|
+
context 'when true' do
|
243
|
+
hash = {
|
244
|
+
'non-empty object' => ['foo'],
|
245
|
+
'TrueClass' => true,
|
246
|
+
'enumerable with blank members' => [nil, false],
|
247
|
+
'numeric' => 8.2
|
248
|
+
}
|
249
|
+
|
250
|
+
hash.each do |k,v|
|
251
|
+
specify k do
|
252
|
+
expect(v.present?).to be true
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
context 'when false' do
|
258
|
+
hash = {
|
259
|
+
'empty string' => '',
|
260
|
+
'whitespace string' => ' ',
|
261
|
+
'FalseClass' => false,
|
262
|
+
'NilClass' => nil,
|
263
|
+
'empty array' => [],
|
264
|
+
'empty hash' => {}
|
265
|
+
}
|
266
|
+
|
267
|
+
hash.each do |k,v|
|
268
|
+
specify k do
|
269
|
+
expect(v.present?).to be false
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
describe '#try method' do
|
276
|
+
context 'NilClass' do
|
277
|
+
it 'returns nil' do
|
278
|
+
expect(nil.try(:inspect)).to be nil
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
context 'when the calling object is not nil' do
|
283
|
+
context 'no args, no block' do
|
284
|
+
it 'evaluates the method' do
|
285
|
+
expect('foo'.try(:to_i)).to eql 0
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
context 'no method, no args, block given' do
|
290
|
+
it 'tries to evaluate the block' do
|
291
|
+
expect(-17.25.try { abs.truncate }).to eql 17
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
context 'with args' do
|
296
|
+
it 'evaluates the method' do
|
297
|
+
expect(%w(foo bar baz).try(:join, '.')).to eql 'foo.bar.baz'
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
context 'with block' do
|
302
|
+
it 'evaluates the method' do
|
303
|
+
expect([1, 2, 3].try(:collect) {|i| i + 1 }).to eql [2, 3, 4]
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
context 'when the method is invalid' do
|
309
|
+
it 'raises an error' do
|
310
|
+
expect{ 'foo'.try(:collect) {|i| i * 3 } }.to raise_error(NoMethodError)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
require 'coveralls'
|
3
|
+
require 'rspec'
|
4
|
+
|
5
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
6
|
+
SimpleCov::Formatter::HTMLFormatter,
|
7
|
+
Coveralls::SimpleCov::Formatter
|
8
|
+
]
|
9
|
+
SimpleCov.start if ENV["COVERAGE"]
|
10
|
+
Coveralls.wear!
|
11
|
+
|
12
|
+
require_relative '../lib/reactive_support'
|
13
|
+
require_relative '../lib/reactive_support/core_ext/array/access'
|
14
|
+
require_relative '../lib/reactive_support/extensions/reactive_extensions'
|
15
|
+
|
16
|
+
RSpec.configure do |c|
|
17
|
+
c.order = 'random'
|
18
|
+
end
|
data/version.rb
ADDED