red_bikini 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --require ./lib/red_bikini
2
+ --require ./spec/person
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - rbx-19mode
6
+ - jruby-19mode
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in red_bikini.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,27 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ red_bikini (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.2.4)
10
+ rake (10.1.0)
11
+ rspec (2.14.1)
12
+ rspec-core (~> 2.14.0)
13
+ rspec-expectations (~> 2.14.0)
14
+ rspec-mocks (~> 2.14.0)
15
+ rspec-core (2.14.4)
16
+ rspec-expectations (2.14.1)
17
+ diff-lcs (>= 1.1.3, < 2.0)
18
+ rspec-mocks (2.14.3)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ bundler (~> 1.3)
25
+ rake
26
+ red_bikini!
27
+ rspec (~> 2.14)
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Titov Andrey
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,105 @@
1
+ [![Build Status](https://travis-ci.org/idrozd/red_bikini.png?branch=master)](https://travis-ci.org/idrozd/red_bikini)
2
+
3
+ # What is this?
4
+ Something you come up with when you know a little ruby and words `public_exec` stuck in your head for a couple days:
5
+ `instance_exec` on wrapper around receiver to conceal private methods, with aliased setters
6
+
7
+ ### cat spec/show_off_spec.rb
8
+ ```ruby
9
+ describe RedBikini do
10
+
11
+ before{RedBikini.add_to_wardrobe! Person}
12
+
13
+ example 'punchline', contrived: true do
14
+ time = '17:00'
15
+
16
+ expect("Tom, Gia and 'Happy' Mike are heading to the cinema at 17:00").to eq(
17
+ Person.such_that do
18
+ name_is 'Mike'
19
+ friends_are %w[Tom Gia]
20
+ set_nickname 'Happy'
21
+ end.confide('the cinema') do |where|
22
+ "#{friends * ', '} and '#{nickname}' #{name} are heading to #{where} at #{time}"
23
+ end
24
+ )
25
+
26
+ end
27
+
28
+ describe 'access' do
29
+ let(:josephine){ Person.new(1,'Josephine')}
30
+ specify do
31
+ expect{josephine.tell{credit_card_number}}
32
+ .to raise_error NoMethodError # private
33
+ end
34
+ specify do
35
+ expect{josephine.expose{girly_secrets}}
36
+ .to raise_error NoMethodError # protected
37
+ end
38
+ end
39
+
40
+ describe 'Kernel#which' do
41
+ example :even_more_contrived do
42
+ [Person.new(nil, 'George'),
43
+ Person.new(nil, 'Kevin' ),
44
+ Person.new(nil, 'Steven'),
45
+ Person.new(22)].
46
+
47
+ find_all(&which{name and name =~ /ev/}).
48
+
49
+ map(&:name).
50
+ should eq %w[Kevin Steven]
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ ```
57
+ ### cat spec/person.rb
58
+ ```ruby
59
+ Person = Struct.new(:id, :name, :friends, :nickname) do
60
+ OWN_CONST = 'Person const'
61
+ def === other
62
+ other.respond_to? :id and id == other.id
63
+ end
64
+ private
65
+ def credit_card_number
66
+ 'meh'
67
+ end
68
+ protected
69
+ def girly_secrets
70
+ 'nah'
71
+ end
72
+ end
73
+
74
+ ```
75
+
76
+ ### Red Bikini?
77
+ Red for ruby, bikini for informal communication
78
+ Think of objects in bikini
79
+
80
+ ### Why?
81
+ It just would not let me go
82
+
83
+ ### So...
84
+ You probably shouldn't use this for serious things, but I wouldn't discourage you from it of course.
85
+ Some kind of DSL sounds as a candidate topic.
86
+
87
+ Check out other specs for gotchas.
88
+ I would note that inside it uses instance exec applied to a wrapper around
89
+ reciever, so it wouldn`t bind calling context methods (which is good),
90
+ but binds locals and constants.
91
+ - Also, or/equal (`||=`) won't work directly without specifiyng explicit receiver of course (`self.attr ||=` will work)
92
+ - Also, `self` wouldn't work with `case` operator - I don't want to hack reciever class `.===` just for that.
93
+ Although, you may use `_self` for this (original object).
94
+
95
+
96
+ - [spec/closure_binding_spec.rb](spec/closure_binding_spec.rb)
97
+
98
+ - [spec/typing_spec.rb](spec/typing_spec.rb)
99
+
100
+ - [spec/operators_spec.rb](spec/operators_spec.rb)
101
+
102
+ - [spec/aliases_spec.rb](spec/aliases_spec.rb)
103
+
104
+ - [spec/collisions_spec.rb](spec/collisions_spec.rb)
105
+
data/README.md.erb ADDED
@@ -0,0 +1,37 @@
1
+ [![Build Status](https://travis-ci.org/idrozd/red_bikini.png?branch=master)](https://travis-ci.org/idrozd/red_bikini)
2
+
3
+ # What is this?
4
+ Something you come up with when you know a little ruby and words `public_exec` stuck in your head for a couple days:
5
+ `instance_exec` on wrapper around receiver to conceal private methods, with aliased setters
6
+
7
+ ### <%= c = "cat spec/show_off_spec.rb" %>
8
+ ```ruby
9
+ <%= `#{c}` %>
10
+ ```
11
+ ### <%= c = "cat spec/person.rb" %>
12
+ ```ruby
13
+ <%= `#{c}`%>
14
+ ```
15
+
16
+ ### Red Bikini?
17
+ Red for ruby, bikini for informal communication
18
+ Think of objects in bikini
19
+
20
+ ### Why?
21
+ It just would not let me go
22
+
23
+ ### So...
24
+ You probably shouldn't use this for serious things, but I wouldn't discourage you from it of course.
25
+ Some kind of DSL sounds as a candidate topic.
26
+
27
+ Check out other specs for gotchas.
28
+ I would note that inside it uses instance exec applied to a wrapper around
29
+ reciever, so it wouldn`t bind calling context methods (which is good),
30
+ but binds locals and constants.
31
+ - Also, or/equal (`||=`) won't work directly without specifiyng explicit receiver of course (`self.attr ||=` will work)
32
+ - Also, `self` wouldn't work with `case` operator - I don't want to hack reciever class `.===` just for that.
33
+ Although, you may use `_self` for this (original object).
34
+
35
+ <% %w[closure_binding typing operators aliases collisions].each do |spec| %>
36
+ - <%= spec = "spec/#{spec}_spec.rb";"[#{spec}](#{spec})"%>
37
+ <% end %>
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
@@ -0,0 +1,42 @@
1
+ require 'forwardable'
2
+ class RedBikini::Bikini
3
+ extend ::Forwardable
4
+
5
+
6
+ def initialize object
7
+ @__in_bikini__ = object
8
+ end
9
+
10
+ def === other
11
+ @__in_bikini__ === other
12
+ end
13
+
14
+ def _self
15
+ @__in_bikini__
16
+ end
17
+
18
+ def object_method method
19
+ original(method) or setter_imitated_by(method)
20
+ end
21
+ def original method
22
+ @__in_bikini__.respond_to?(method, true) and method
23
+ end
24
+
25
+ def respond_to_missing? method, *args
26
+ @__in_bikini__.respond_to?(object_method(method), *args)
27
+ end
28
+ def method_missing method, *args
29
+ @__in_bikini__.public_send(object_method(method), *args)
30
+ end
31
+
32
+
33
+ def setter_imitated_by method
34
+ [/set_(?<attr>\w+)/,/(?<attr>\w+)(_are|_is)/].find do |setter_matcher|
35
+ String(method).match(setter_matcher){|match| return match['attr'] + ?= }
36
+ end
37
+ end
38
+
39
+ def_delegators :@__in_bikini__, :is_a?, :kind_of?, :instance_of?, :class
40
+
41
+
42
+ end
@@ -0,0 +1,3 @@
1
+ module RedBikini
2
+ VERSION = "0.0.1"
3
+ end
data/lib/red_bikini.rb ADDED
@@ -0,0 +1,41 @@
1
+ module RedBikini
2
+ require_relative 'red_bikini/bikini'
3
+
4
+ def self.add_to_wardrobe! klass=Object
5
+ klass.send :include, InstanceMethods
6
+ klass.send :extend, ClassMethods
7
+ end
8
+
9
+ ExecuteInWrappedContext = ->(receiver, args, block) do
10
+ Bikini.new(receiver).instance_exec *args, &block
11
+ end
12
+
13
+ module InstanceMethods
14
+ def in_public *args, &block
15
+ tap{self.expose *args, &block}
16
+ end
17
+ alias in_bikini in_public
18
+ def expose *args, &block
19
+ ExecuteInWrappedContext.call self, args, block
20
+ end
21
+ alias tell expose
22
+ alias confide expose
23
+ end
24
+
25
+
26
+ module ClassMethods
27
+ def such_that *args, &description
28
+ new(*args).in_public &description
29
+ end
30
+ end
31
+
32
+
33
+ ::Kernel.module_exec do
34
+ def which &block
35
+ proc{|receiver|receiver.expose &block}
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'red_bikini/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "red_bikini"
8
+ spec.version = RedBikini::VERSION
9
+ spec.authors = ["Andrey Titov"]
10
+ spec.email = ["terracote@gmail.com"]
11
+ spec.description = %q{think of public_exec:}
12
+ spec.summary = %q{ instance_exec run on wrapped receiver, with respect to private methods and setter aliases}
13
+ spec.homepage = "https://github.com/idrozd/red_bikini"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ #spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec", "~> 2.14"
24
+ end
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ for t in *.erb; do o=$(basename $t .erb); erb $t > $o && git add $o || exit 1; done
3
+ rspec
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ scripts=`dirname $(readlink -nf $0)`
3
+ ln -s $scripts/git_hooks/pre-commit $scripts/../.git/hooks -f
@@ -0,0 +1,23 @@
1
+ describe RedBikini, 'aliases' do
2
+ before {RedBikini.add_to_wardrobe! Person}
3
+
4
+ example do
5
+ patrick = Person.new(1,'Patrick')
6
+
7
+ [
8
+ patrick.expose{"I'm #{name}"},
9
+ patrick.tell{"I'm #{name}"},
10
+ patrick.confide{"I'm #{name}"},
11
+ "I'm Patrick"
12
+ ].uniq.should have(1).string
13
+ end
14
+
15
+
16
+ example '#in_public and #in_bikini are just tap expose' do
17
+ [
18
+ Person.new.in_public{nickname_is 'Dredd'},
19
+ Person.new.in_bikini{set_nickname 'Dredd'},
20
+ Person.new(nil,nil,nil,'Dredd')
21
+ ].uniq.should have(1).element
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ describe RedBikini do
2
+
3
+ before{RedBikini.add_to_wardrobe! Person}
4
+
5
+
6
+ describe 'closure stuff' do
7
+ let(:joe){Person.new(1,'Joe')}
8
+ HOST_CONST = 'Joe is best'
9
+ example{name = 'Local Joe'; expect(joe.tell{name}).to eq 'Local Joe'}
10
+ context 'there is caller method with same name' do
11
+ let(:name){'Host Joe'}
12
+ specify{expect(joe.tell{name}).to eq 'Joe'}
13
+ end
14
+ specify{expect(joe.tell{HOST_CONST}).to eq 'Joe is best'}
15
+ specify{expect(joe.tell{OWN_CONST}).to eq 'Person const'}
16
+ end
17
+
18
+ end
@@ -0,0 +1,20 @@
1
+ describe RedBikini, 'name collisions' do
2
+ example do
3
+ Battlecruiser = Class.new do
4
+ attr_accessor :captain_has_parrot, :the_course
5
+ def set_the_course where
6
+ "Course is set! Heading #{where}"
7
+ end
8
+ end
9
+
10
+ RedBikini.add_to_wardrobe! Battlecruiser
11
+
12
+ battlecruiser = Battlecruiser.such_that do
13
+ set_the_course 'nowhere'
14
+ captain_has_parrot_is true
15
+ end
16
+
17
+ battlecruiser.the_course.should be_nil
18
+ battlecruiser.captain_has_parrot.should eq true
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ describe RedBikini do
2
+
3
+ before{RedBikini.add_to_wardrobe! Person}
4
+
5
+
6
+ describe do
7
+ example{expect(Person.new(1,'Jack').in_public{name ||= 'George'}.name).to eq 'Jack'}
8
+ example{expect(Person.new(1,nil).in_public{name ||= 'George'}.name).to eq nil}
9
+ example{expect(Person.new(1,nil).in_public{self.name ||= 'George'}.name).to eq 'George'}
10
+ example{expect(Person.new(1,nil).in_public{name_is name || 'George'}.name).to eq 'George'}
11
+ # ... and so on. You`ve got the point
12
+ end
13
+ end
data/spec/person.rb ADDED
@@ -0,0 +1,14 @@
1
+ Person = Struct.new(:id, :name, :friends, :nickname) do
2
+ OWN_CONST = 'Person const'
3
+ def === other
4
+ other.respond_to? :id and id == other.id
5
+ end
6
+ private
7
+ def credit_card_number
8
+ 'meh'
9
+ end
10
+ protected
11
+ def girly_secrets
12
+ 'nah'
13
+ end
14
+ end
@@ -0,0 +1,46 @@
1
+ describe RedBikini do
2
+
3
+ before{RedBikini.add_to_wardrobe! Person}
4
+
5
+ example 'punchline', contrived: true do
6
+ time = '17:00'
7
+
8
+ expect("Tom, Gia and 'Happy' Mike are heading to the cinema at 17:00").to eq(
9
+ Person.such_that do
10
+ name_is 'Mike'
11
+ friends_are %w[Tom Gia]
12
+ set_nickname 'Happy'
13
+ end.confide('the cinema') do |where|
14
+ "#{friends * ', '} and '#{nickname}' #{name} are heading to #{where} at #{time}"
15
+ end
16
+ )
17
+
18
+ end
19
+
20
+ describe 'access' do
21
+ let(:josephine){ Person.new(1,'Josephine')}
22
+ specify do
23
+ expect{josephine.tell{credit_card_number}}
24
+ .to raise_error NoMethodError # private
25
+ end
26
+ specify do
27
+ expect{josephine.expose{girly_secrets}}
28
+ .to raise_error NoMethodError # protected
29
+ end
30
+ end
31
+
32
+ describe 'Kernel#which' do
33
+ example :even_more_contrived do
34
+ [Person.new(nil, 'George'),
35
+ Person.new(nil, 'Kevin' ),
36
+ Person.new(nil, 'Steven'),
37
+ Person.new(22)].
38
+
39
+ find_all(&which{name and name =~ /ev/}).
40
+
41
+ map(&:name).
42
+ should eq %w[Kevin Steven]
43
+ end
44
+ end
45
+
46
+ end
@@ -0,0 +1 @@
1
+ require_relative '../lib/red_bikini'
@@ -0,0 +1,24 @@
1
+ describe RedBikini do
2
+
3
+ before{RedBikini.add_to_wardrobe! Person}
4
+
5
+ describe 'hacked typing' do
6
+ let(:a_person){Person.new(1,'Joe')}
7
+ specify{expect(a_person.tell{self.is_a? Person}).to be_true}
8
+ specify{expect(a_person.tell{self.instance_of? Person}).to be_true}
9
+ specify{expect(a_person.tell{is_a? Person}).to be_true}
10
+ specify{expect(a_person.tell{instance_of? Person}).to be_true}
11
+ specify{expect(a_person.tell{self.class}).to eq Person}
12
+ specify{expect(a_person.tell{kind_of? Person}).to be_true}
13
+ specify{expect(a_person.tell{self}).to be_a Person}
14
+ specify :gotcha do
15
+ expect(a_person.tell{Person === self}).to be_false
16
+
17
+ expect(a_person.tell{Person === _self}).to be_true
18
+ expect(a_person.tell{Person === @__in_bikini__}).to be_true
19
+ end
20
+ specify{expect(a_person.tell{self === Person}).to be_false} # As expected
21
+ specify{expect(a_person.tell{self === Person.new(1)}).to be_true}
22
+ specify{RedBikini.add_to_wardrobe! Class; expect(Fixnum.tell{self === 1}).to be_true}
23
+ end
24
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: red_bikini
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Andrey Titov
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-08-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.3'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.3'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '2.14'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '2.14'
62
+ description: ! 'think of public_exec:'
63
+ email:
64
+ - terracote@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - .rspec
71
+ - .travis.yml
72
+ - Gemfile
73
+ - Gemfile.lock
74
+ - LICENSE
75
+ - README.md
76
+ - README.md.erb
77
+ - Rakefile
78
+ - lib/red_bikini.rb
79
+ - lib/red_bikini/bikini.rb
80
+ - lib/red_bikini/version.rb
81
+ - red_bikini.gemspec
82
+ - script/git_hooks/pre-commit
83
+ - script/install_git_hooks
84
+ - spec/aliases_spec.rb
85
+ - spec/closure_binding_spec.rb
86
+ - spec/collisions_spec.rb
87
+ - spec/operators_spec.rb
88
+ - spec/person.rb
89
+ - spec/show_off_spec.rb
90
+ - spec/spec_helper.rb
91
+ - spec/typing_spec.rb
92
+ homepage: https://github.com/idrozd/red_bikini
93
+ licenses:
94
+ - MIT
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ! '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ segments:
106
+ - 0
107
+ hash: -120012333
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ! '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ segments:
115
+ - 0
116
+ hash: -120012333
117
+ requirements: []
118
+ rubyforge_project:
119
+ rubygems_version: 1.8.25
120
+ signing_key:
121
+ specification_version: 3
122
+ summary: instance_exec run on wrapped receiver, with respect to private methods and
123
+ setter aliases
124
+ test_files:
125
+ - spec/aliases_spec.rb
126
+ - spec/closure_binding_spec.rb
127
+ - spec/collisions_spec.rb
128
+ - spec/operators_spec.rb
129
+ - spec/person.rb
130
+ - spec/show_off_spec.rb
131
+ - spec/spec_helper.rb
132
+ - spec/typing_spec.rb