reactive_support 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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