docile 1.2.0 → 1.3.4
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 +5 -5
- data/.travis.yml +24 -18
- data/Gemfile +4 -4
- data/HISTORY.md +31 -1
- data/LICENSE +1 -1
- data/README.md +36 -5
- data/Rakefile +10 -10
- data/docile.gemspec +39 -29
- data/lib/docile.rb +5 -4
- data/lib/docile/backtrace_filter.rb +22 -0
- data/lib/docile/chaining_fallback_context_proxy.rb +2 -2
- data/lib/docile/execution.rb +8 -2
- data/lib/docile/fallback_context_proxy.rb +39 -3
- data/lib/docile/version.rb +1 -1
- data/on_what.rb +13 -5
- metadata +29 -17
- data/spec/docile_spec.rb +0 -362
- data/spec/spec_helper.rb +0 -31
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 3ecef57f8977694d10721b6f18ece9744d03288b21e67d8fd8a4d3bca2837a57
|
|
4
|
+
data.tar.gz: e10ccdb31a0ffeb6fca27bb1f54250fd0c0a881afa70d2eac58145b05616a820
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0f8331a837ca968790f87bb9cdcc213d35da6c5973f4d9dcb56a604849c476c8d99d20dcdc921388389aed85f3b7eb2894eabcb90abfd42a1f1214817a631264
|
|
7
|
+
data.tar.gz: cffe4f42680621637b3103607a96c5511712f0d298c30401e04bfce08997a702fdcc5f965b8737e8531f12d330612ada1887818f93e109facfaaac215eb9243c
|
data/.travis.yml
CHANGED
|
@@ -1,37 +1,43 @@
|
|
|
1
1
|
language: ruby
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
# See https://docs.travis-ci.com/user/languages/ruby/#Rubinius
|
|
7
|
-
dist: trusty
|
|
3
|
+
branches:
|
|
4
|
+
only:
|
|
5
|
+
- master
|
|
8
6
|
|
|
9
7
|
rvm:
|
|
10
8
|
# MRI
|
|
11
9
|
- ruby-head
|
|
10
|
+
- 2.7
|
|
11
|
+
- 2.6
|
|
12
|
+
- 2.5
|
|
12
13
|
- 2.4
|
|
13
14
|
- 2.3
|
|
14
15
|
- 2.2
|
|
15
16
|
- 2.1
|
|
16
|
-
- 2.0
|
|
17
|
-
- 1.9.2 # allowed to fail until Travis binary for this is fixed
|
|
18
17
|
- 1.9.3
|
|
19
|
-
- 1.8.7
|
|
18
|
+
- 1.8.7
|
|
20
19
|
- ree
|
|
21
20
|
# JRuby
|
|
22
21
|
- jruby-head
|
|
23
|
-
- jruby-9.
|
|
24
|
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
# Rubinius
|
|
28
|
-
- rubinius-3
|
|
22
|
+
- jruby-9.2
|
|
23
|
+
# Truffleruby
|
|
24
|
+
- truffleruby-head
|
|
25
|
+
- truffleruby-20.3.0
|
|
29
26
|
|
|
30
|
-
|
|
27
|
+
jobs:
|
|
31
28
|
allow_failures:
|
|
32
29
|
- rvm: ruby-head
|
|
33
|
-
- rvm: 1.9.2 # See build error https://travis-ci.org/tcrayford/Values/jobs/202728857
|
|
34
30
|
- rvm: jruby-head
|
|
35
|
-
- rvm:
|
|
36
|
-
-
|
|
31
|
+
- rvm: truffleruby-head
|
|
32
|
+
# NOTE (2020-12-18): Failing access to Rubygems with following error:
|
|
33
|
+
# Unable to download data from https://rubygems.org/ - hostname was not
|
|
34
|
+
# match with the server certificate (https://rubygems.org/specs.4.8.gz)
|
|
35
|
+
#
|
|
36
|
+
# See Travis CI topic here:
|
|
37
|
+
# https://travis-ci.community/t/ruby-1-8-7-and-ree-builds-broken-by-ssl-certificate-failure/10866
|
|
38
|
+
#
|
|
39
|
+
# TODO (2020-12-18): Either find a fix or remove testing of 1.8 versions
|
|
40
|
+
- rvm: 1.8.7
|
|
41
|
+
- rvm: ree
|
|
42
|
+
|
|
37
43
|
fast_finish: true
|
data/Gemfile
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
require File.expand_path(
|
|
2
|
-
source
|
|
1
|
+
require File.expand_path("on_what", File.dirname(__FILE__))
|
|
2
|
+
source "https://rubygems.org"
|
|
3
3
|
|
|
4
4
|
# Travis-only dependencies go here
|
|
5
|
-
if on_travis? && !
|
|
5
|
+
if on_travis? && !on_less_than_2_3? && !on_rubinius?
|
|
6
6
|
group :test do
|
|
7
|
-
gem
|
|
7
|
+
gem "codecov", ">= 0.0.9", :require => false
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
|
data/HISTORY.md
CHANGED
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
# HISTORY
|
|
2
2
|
|
|
3
|
-
## [Unreleased changes](http://github.com/ms-ati/docile/compare/v1.
|
|
3
|
+
## [Unreleased changes](http://github.com/ms-ati/docile/compare/v1.3.4...master)
|
|
4
|
+
|
|
5
|
+
- ...
|
|
6
|
+
|
|
7
|
+
## [v1.3.4 (Dec 22, 2020)](http://github.com/ms-ati/docile/compare/v1.3.3...v1.3.4)
|
|
8
|
+
|
|
9
|
+
- Special thanks to Benoit Daloze (@eregon):
|
|
10
|
+
- Fix delegation on Ruby 2.7 (issues #45 and #44, PR #52)
|
|
11
|
+
|
|
12
|
+
## [v1.3.3 (Dec 18, 2020)](http://github.com/ms-ati/docile/compare/v1.3.2...v1.3.3)
|
|
13
|
+
|
|
14
|
+
- Special thanks (again!) to Taichi Ishitani (@taichi-ishitani):
|
|
15
|
+
- Fix keyword arg warnings on Ruby 2.7 (issue #44, PR #45)
|
|
16
|
+
- Filter Docile's source files from backtrace (issue #35, PR #36)
|
|
17
|
+
|
|
18
|
+
## [v1.3.2 (Jun 12, 2019)](http://github.com/ms-ati/docile/compare/v1.3.1...v1.3.2)
|
|
19
|
+
|
|
20
|
+
- Special thanks (again!) to Taichi Ishitani (@taichi-ishitani):
|
|
21
|
+
- Fix for DSL object is replaced when #dsl_eval is nested (#33, PR #34)
|
|
22
|
+
|
|
23
|
+
## [v1.3.1 (May 24, 2018)](http://github.com/ms-ati/docile/compare/v1.3.0...v1.3.1)
|
|
24
|
+
|
|
25
|
+
- Special thanks to Taichi Ishitani (@taichi-ishitani):
|
|
26
|
+
- Fix for when DSL object is also the block's context (#30)
|
|
27
|
+
|
|
28
|
+
## [v1.3.0 (Feb 7, 2018)](http://github.com/ms-ati/docile/compare/v1.2.0...v1.3.0)
|
|
29
|
+
|
|
30
|
+
- Allow helper methods in block's context to call DSL methods
|
|
31
|
+
- Add SemVer release policy explicitly
|
|
32
|
+
- Standardize on double-quoted string literals
|
|
33
|
+
- Workaround some more Travis CI shenanigans
|
|
4
34
|
|
|
5
35
|
## [v1.2.0 (Jan 11, 2018)](http://github.com/ms-ati/docile/compare/v1.1.5...v1.2.0)
|
|
6
36
|
|
data/LICENSE
CHANGED
data/README.md
CHANGED
|
@@ -8,9 +8,8 @@
|
|
|
8
8
|
[](http://inch-ci.org/github/ms-ati/docile)
|
|
9
9
|
|
|
10
10
|
[](https://travis-ci.org/ms-ati/docile)
|
|
11
|
-
[](https://gemnasium.com/ms-ati/docile)
|
|
12
|
-
[](https://codeclimate.com/github/ms-ati/docile)
|
|
13
11
|
[](https://codecov.io/github/ms-ati/docile)
|
|
12
|
+
[](https://codeclimate.com/github/ms-ati/docile/maintainability)
|
|
14
13
|
|
|
15
14
|
Ruby makes it possible to create very expressive **Domain Specific
|
|
16
15
|
Languages**, or **DSL**'s for short. However, it requires some deep knowledge and
|
|
@@ -48,13 +47,41 @@ def with_array(arr=[], &block)
|
|
|
48
47
|
end
|
|
49
48
|
```
|
|
50
49
|
|
|
51
|
-
|
|
50
|
+
Easy!
|
|
51
|
+
|
|
52
|
+
### Next step: Allow helper methods to call DSL methods
|
|
53
|
+
|
|
54
|
+
What if, in our use of the methods of Array as a DSL, we want to extract
|
|
55
|
+
helper methods which in turn call DSL methods?
|
|
56
|
+
|
|
57
|
+
```ruby
|
|
58
|
+
def pop_sum_and_push(n)
|
|
59
|
+
sum = 0
|
|
60
|
+
n.times { sum += pop }
|
|
61
|
+
push sum
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
Docile.dsl_eval([]) do
|
|
65
|
+
push 5
|
|
66
|
+
push 6
|
|
67
|
+
pop_sum_and_push(2)
|
|
68
|
+
end
|
|
69
|
+
#=> [11]
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Without Docile, you may find this sort of code extraction to be more
|
|
73
|
+
challenging.
|
|
52
74
|
|
|
53
75
|
### Wait! Can't I do that with just `instance_eval` or `instance_exec`?
|
|
54
76
|
|
|
55
77
|
Good question!
|
|
56
78
|
|
|
57
|
-
|
|
79
|
+
In short: **No**.
|
|
80
|
+
|
|
81
|
+
Not if you want the code in the block to be able to refer to anything
|
|
82
|
+
the block would normally have access to from the surrounding context.
|
|
83
|
+
|
|
84
|
+
Let's be very specific. Docile internally uses `instance_exec` (see [execution.rb#26](lib/docile/execution.rb#L26)), adding a small layer to support referencing *local variables*, *instance variables*, and *methods* from the _block's context_ **or** the target _object's context_, interchangeably. This is "**the hard part**", where most folks making a DSL in Ruby throw up their hands.
|
|
58
85
|
|
|
59
86
|
For example:
|
|
60
87
|
|
|
@@ -328,6 +355,10 @@ Works on [all ruby versions since 1.8.7](https://github.com/ms-ati/docile/blob/m
|
|
|
328
355
|
|
|
329
356
|
Used by some pretty cool gems to implement their DSLs, notably including [SimpleCov](https://github.com/colszowka/simplecov). Keep an eye out for new gems using Docile at the [Ruby Toolbox](https://www.ruby-toolbox.com/projects/docile).
|
|
330
357
|
|
|
358
|
+
## Release Policy
|
|
359
|
+
|
|
360
|
+
Docile releases follow [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html).
|
|
361
|
+
|
|
331
362
|
## Note on Patches/Pull Requests
|
|
332
363
|
|
|
333
364
|
* Fork the project.
|
|
@@ -343,7 +374,7 @@ Used by some pretty cool gems to implement their DSLs, notably including [Simple
|
|
|
343
374
|
|
|
344
375
|
## Copyright & License
|
|
345
376
|
|
|
346
|
-
Copyright (c) 2012-
|
|
377
|
+
Copyright (c) 2012-2021 Marc Siegel.
|
|
347
378
|
|
|
348
379
|
Licensed under the [MIT License](http://choosealicense.com/licenses/mit/), see [LICENSE](LICENSE) for details.
|
|
349
380
|
|
data/Rakefile
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
3
|
-
require
|
|
4
|
-
require File.expand_path(
|
|
1
|
+
require "rake/clean"
|
|
2
|
+
require "bundler/gem_tasks"
|
|
3
|
+
require "rspec/core/rake_task"
|
|
4
|
+
require File.expand_path("on_what", File.dirname(__FILE__))
|
|
5
5
|
|
|
6
6
|
# Default task for `rake` is to run rspec
|
|
7
7
|
task :default => [:spec]
|
|
@@ -10,19 +10,19 @@ task :default => [:spec]
|
|
|
10
10
|
RSpec::Core::RakeTask.new
|
|
11
11
|
|
|
12
12
|
# Configure `rake clobber` to delete all generated files
|
|
13
|
-
CLOBBER.include(
|
|
13
|
+
CLOBBER.include("pkg", "doc", "coverage")
|
|
14
14
|
|
|
15
15
|
# To limit needed compatibility with versions of dependencies, only configure
|
|
16
16
|
# yard doc generation when *not* on Travis, JRuby, or < 2.0
|
|
17
17
|
if !on_travis? && !on_jruby? && !on_less_than_2_0?
|
|
18
|
-
require
|
|
19
|
-
require
|
|
20
|
-
require
|
|
21
|
-
require
|
|
18
|
+
require "github/markup"
|
|
19
|
+
require "redcarpet"
|
|
20
|
+
require "yard"
|
|
21
|
+
require "yard/rake/yardoc_task"
|
|
22
22
|
|
|
23
23
|
YARD::Rake::YardocTask.new do |t|
|
|
24
24
|
OTHER_PATHS = %w()
|
|
25
|
-
t.files = [
|
|
25
|
+
t.files = ["lib/**/*.rb", OTHER_PATHS]
|
|
26
26
|
t.options = %w(--markup-provider=redcarpet --markup=markdown --main=README.md)
|
|
27
27
|
end
|
|
28
28
|
end
|
data/docile.gemspec
CHANGED
|
@@ -1,45 +1,55 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
require
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
|
2
|
+
require File.expand_path("on_what", File.dirname(__FILE__))
|
|
3
|
+
require "docile/version"
|
|
4
4
|
|
|
5
5
|
Gem::Specification.new do |s|
|
|
6
|
-
s.name =
|
|
6
|
+
s.name = "docile"
|
|
7
7
|
s.version = Docile::VERSION
|
|
8
|
-
s.author =
|
|
9
|
-
s.email =
|
|
10
|
-
s.homepage =
|
|
11
|
-
s.summary =
|
|
12
|
-
s.description =
|
|
13
|
-
|
|
8
|
+
s.author = "Marc Siegel"
|
|
9
|
+
s.email = "marc@usainnov.com"
|
|
10
|
+
s.homepage = "https://ms-ati.github.io/docile/"
|
|
11
|
+
s.summary = "Docile keeps your Ruby DSLs tame and well-behaved."
|
|
12
|
+
s.description = "Docile treats the methods of a given ruby object as a DSL " \
|
|
13
|
+
"(domain specific language) within a given block. \n\n" \
|
|
14
|
+
"Killer feature: you can also reference methods, instance " \
|
|
15
|
+
"variables, and local variables from the original (non-DSL) "\
|
|
16
|
+
"context within the block. \n\n" \
|
|
17
|
+
"Docile releases follow Semantic Versioning as defined at " \
|
|
18
|
+
"semver.org."
|
|
19
|
+
s.license = "MIT"
|
|
14
20
|
|
|
15
21
|
# Files included in the gem
|
|
16
|
-
s.files = `git ls-files`.split("\
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
s.require_paths =
|
|
22
|
+
s.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
23
|
+
f.match(%r{^(test|spec|features)/})
|
|
24
|
+
end
|
|
25
|
+
s.require_paths = ["lib"]
|
|
20
26
|
|
|
21
27
|
# Specify oldest supported Ruby version
|
|
22
|
-
s.required_ruby_version =
|
|
28
|
+
s.required_ruby_version = ">= 1.8.7"
|
|
23
29
|
|
|
24
|
-
# Run rspec tests from rake
|
|
25
|
-
s.add_development_dependency
|
|
26
|
-
s.add_development_dependency
|
|
27
|
-
s.add_development_dependency
|
|
30
|
+
# Run rspec tests from rake even on old Ruby versions
|
|
31
|
+
s.add_development_dependency "rake", "~> 10.5" if on_less_than_1_9_3? # Pin compatible rake on old rubies, see: https://github.com/travis-ci/travis.rb/issues/380
|
|
32
|
+
s.add_development_dependency "rake", "< 11.0" unless on_less_than_1_9_3? # See http://stackoverflow.com/questions/35893584/nomethoderror-undefined-method-last-comment-after-upgrading-to-rake-11
|
|
33
|
+
s.add_development_dependency "rspec", "~> 3.0"
|
|
34
|
+
s.add_development_dependency "rspec-expectations", "!= 3.8.3" # Workaround for RSpec's issue, see: https://github.com/rspec/rspec-expectations/issues/1111
|
|
28
35
|
|
|
29
|
-
#
|
|
30
|
-
|
|
36
|
+
# Run code coverage where possible - not on Rubinius
|
|
37
|
+
unless on_rubinius?
|
|
38
|
+
# Pin versions for Travis builds on 1.9
|
|
39
|
+
s.add_development_dependency "json", "< 2.0" if on_less_than_2_0?
|
|
31
40
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
41
|
+
# Pin versions for Travis builds on 1.8
|
|
42
|
+
s.add_development_dependency "mime-types" , "~> 1.25.1" if on_1_8?
|
|
43
|
+
s.add_development_dependency "rest-client", "~> 1.6.8" if on_1_8?
|
|
44
|
+
end
|
|
35
45
|
|
|
36
46
|
# To limit needed compatibility with versions of dependencies, only configure
|
|
37
|
-
# yard doc generation when *not* on Travis, JRuby, or < 2.0
|
|
38
|
-
if !on_travis? && !on_jruby? && !on_less_than_2_0?
|
|
47
|
+
# yard doc generation when *not* on Travis, JRuby, Rubinius, or < 2.0
|
|
48
|
+
if !on_travis? && !on_jruby? && !on_rubinius? && !on_less_than_2_0?
|
|
39
49
|
# Github flavored markdown in YARD documentation
|
|
40
50
|
# http://blog.nikosd.com/2011/11/github-flavored-markdown-in-yard.html
|
|
41
|
-
s.add_development_dependency
|
|
42
|
-
s.add_development_dependency
|
|
43
|
-
s.add_development_dependency
|
|
51
|
+
s.add_development_dependency "yard"
|
|
52
|
+
s.add_development_dependency "redcarpet"
|
|
53
|
+
s.add_development_dependency "github-markup"
|
|
44
54
|
end
|
|
45
55
|
end
|
data/lib/docile.rb
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
3
|
-
require
|
|
4
|
-
require
|
|
1
|
+
require "docile/version"
|
|
2
|
+
require "docile/execution"
|
|
3
|
+
require "docile/fallback_context_proxy"
|
|
4
|
+
require "docile/chaining_fallback_context_proxy"
|
|
5
|
+
require "docile/backtrace_filter"
|
|
5
6
|
|
|
6
7
|
# Docile keeps your Ruby DSLs tame and well-behaved.
|
|
7
8
|
module Docile
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Docile
|
|
2
|
+
# @api private
|
|
3
|
+
#
|
|
4
|
+
# This is used to remove entries pointing to Docile's source files
|
|
5
|
+
# from {Exception#backtrace} and {Exception#backtrace_locations}.
|
|
6
|
+
#
|
|
7
|
+
# If {NoMethodError} is caught then the exception object will be extended
|
|
8
|
+
# by this module to add filter functionalities.
|
|
9
|
+
module BacktraceFilter
|
|
10
|
+
FILTER_PATTERN = /lib\/docile/
|
|
11
|
+
|
|
12
|
+
def backtrace
|
|
13
|
+
super.select { |trace| trace !~ FILTER_PATTERN }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
if ::Exception.public_method_defined?(:backtrace_locations)
|
|
17
|
+
def backtrace_locations
|
|
18
|
+
super.select { |location| location.absolute_path !~ FILTER_PATTERN }
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/docile/execution.rb
CHANGED
|
@@ -15,16 +15,22 @@ module Docile
|
|
|
15
15
|
# @param block [Proc] the block of DSL commands to be executed
|
|
16
16
|
# @return [Object] the return value of the block
|
|
17
17
|
def exec_in_proxy_context(dsl, proxy_type, *args, &block)
|
|
18
|
-
block_context = eval(
|
|
18
|
+
block_context = eval("self", block.binding)
|
|
19
19
|
proxy_context = proxy_type.new(dsl, block_context)
|
|
20
20
|
begin
|
|
21
21
|
block_context.instance_variables.each do |ivar|
|
|
22
22
|
value_from_block = block_context.instance_variable_get(ivar)
|
|
23
23
|
proxy_context.instance_variable_set(ivar, value_from_block)
|
|
24
24
|
end
|
|
25
|
+
|
|
25
26
|
proxy_context.instance_exec(*args, &block)
|
|
26
27
|
ensure
|
|
28
|
+
if block_context.respond_to?(:__docile_undo_fallback__)
|
|
29
|
+
block_context.send(:__docile_undo_fallback__)
|
|
30
|
+
end
|
|
31
|
+
|
|
27
32
|
block_context.instance_variables.each do |ivar|
|
|
33
|
+
next unless proxy_context.instance_variables.include?(ivar)
|
|
28
34
|
value_from_dsl_proxy = proxy_context.instance_variable_get(ivar)
|
|
29
35
|
block_context.instance_variable_set(ivar, value_from_dsl_proxy)
|
|
30
36
|
end
|
|
@@ -32,4 +38,4 @@ module Docile
|
|
|
32
38
|
end
|
|
33
39
|
module_function :exec_in_proxy_context
|
|
34
40
|
end
|
|
35
|
-
end
|
|
41
|
+
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "set"
|
|
2
2
|
|
|
3
3
|
module Docile
|
|
4
4
|
# @api private
|
|
@@ -17,10 +17,14 @@ module Docile
|
|
|
17
17
|
# The set of methods which will **not** be proxied, but instead answered
|
|
18
18
|
# by this object directly.
|
|
19
19
|
NON_PROXIED_METHODS = Set[:__send__, :object_id, :__id__, :==, :equal?,
|
|
20
|
-
:
|
|
20
|
+
:"!", :"!=", :instance_exec, :instance_variables,
|
|
21
21
|
:instance_variable_get, :instance_variable_set,
|
|
22
22
|
:remove_instance_variable]
|
|
23
23
|
|
|
24
|
+
# The set of methods which will **not** fallback from the block's context
|
|
25
|
+
# to the dsl object.
|
|
26
|
+
NON_FALLBACK_METHODS = Set[:class, :self, :respond_to?, :instance_of?]
|
|
27
|
+
|
|
24
28
|
# The set of instance variables which are local to this object and hidden.
|
|
25
29
|
# All other instance variables will be copied in and out of this object
|
|
26
30
|
# from the scope in which this proxy was created.
|
|
@@ -38,6 +42,32 @@ module Docile
|
|
|
38
42
|
def initialize(receiver, fallback)
|
|
39
43
|
@__receiver__ = receiver
|
|
40
44
|
@__fallback__ = fallback
|
|
45
|
+
|
|
46
|
+
# Enables calling DSL methods from helper methods in the block's context
|
|
47
|
+
unless fallback.respond_to?(:method_missing)
|
|
48
|
+
# NOTE: There's no {#define_singleton_method} on Ruby 1.8.x
|
|
49
|
+
singleton_class = (class << fallback; self; end)
|
|
50
|
+
|
|
51
|
+
# instrument {#method_missing} on the block's context to fallback to
|
|
52
|
+
# the DSL object. This allows helper methods in the block's context to
|
|
53
|
+
# contain calls to methods on the DSL object.
|
|
54
|
+
singleton_class.
|
|
55
|
+
send(:define_method, :method_missing) do |method, *args, &block|
|
|
56
|
+
m = method.to_sym
|
|
57
|
+
if !NON_FALLBACK_METHODS.include?(m) && !fallback.respond_to?(m) && receiver.respond_to?(m)
|
|
58
|
+
receiver.__send__(method.to_sym, *args, &block)
|
|
59
|
+
else
|
|
60
|
+
super(method, *args, &block)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# instrument a helper method to remove the above instrumentation
|
|
65
|
+
singleton_class.
|
|
66
|
+
send(:define_method, :__docile_undo_fallback__) do
|
|
67
|
+
singleton_class.send(:remove_method, :method_missing)
|
|
68
|
+
singleton_class.send(:remove_method, :__docile_undo_fallback__)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
41
71
|
end
|
|
42
72
|
|
|
43
73
|
# @return [Array<Symbol>] Instance variable names, excluding
|
|
@@ -56,8 +86,14 @@ module Docile
|
|
|
56
86
|
if @__receiver__.respond_to?(method.to_sym)
|
|
57
87
|
@__receiver__.__send__(method.to_sym, *args, &block)
|
|
58
88
|
else
|
|
59
|
-
|
|
89
|
+
begin
|
|
90
|
+
@__fallback__.__send__(method.to_sym, *args, &block)
|
|
91
|
+
rescue NoMethodError => e
|
|
92
|
+
e.extend(BacktraceFilter)
|
|
93
|
+
raise e
|
|
94
|
+
end
|
|
60
95
|
end
|
|
61
96
|
end
|
|
97
|
+
ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true)
|
|
62
98
|
end
|
|
63
99
|
end
|
data/lib/docile/version.rb
CHANGED
data/on_what.rb
CHANGED
|
@@ -2,21 +2,29 @@
|
|
|
2
2
|
# between Rakefile, gemspec, and spec_helper. Not for use in actual library.
|
|
3
3
|
|
|
4
4
|
def on_travis?
|
|
5
|
-
ENV[
|
|
5
|
+
ENV["CI"] == "true"
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
def on_jruby?
|
|
9
|
-
defined?(RUBY_ENGINE) &&
|
|
9
|
+
defined?(RUBY_ENGINE) && "jruby" == RUBY_ENGINE
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def on_rubinius?
|
|
13
|
+
defined?(RUBY_ENGINE) && "rbx" == RUBY_ENGINE
|
|
10
14
|
end
|
|
11
15
|
|
|
12
16
|
def on_1_8?
|
|
13
|
-
RUBY_VERSION.start_with?
|
|
17
|
+
RUBY_VERSION.start_with? "1.8"
|
|
14
18
|
end
|
|
15
19
|
|
|
16
20
|
def on_less_than_1_9_3?
|
|
17
|
-
RUBY_VERSION <
|
|
21
|
+
RUBY_VERSION < "1.9.3"
|
|
18
22
|
end
|
|
19
23
|
|
|
20
24
|
def on_less_than_2_0?
|
|
21
|
-
RUBY_VERSION <
|
|
25
|
+
RUBY_VERSION < "2.0.0"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def on_less_than_2_3?
|
|
29
|
+
RUBY_VERSION < "2.3.0"
|
|
22
30
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: docile
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Marc Siegel
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2020-12-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rake
|
|
@@ -30,14 +30,28 @@ dependencies:
|
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 3.0
|
|
33
|
+
version: '3.0'
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 3.0
|
|
40
|
+
version: '3.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rspec-expectations
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "!="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: 3.8.3
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "!="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: 3.8.3
|
|
41
55
|
- !ruby/object:Gem::Dependency
|
|
42
56
|
name: yard
|
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -80,8 +94,10 @@ dependencies:
|
|
|
80
94
|
- - ">="
|
|
81
95
|
- !ruby/object:Gem::Version
|
|
82
96
|
version: '0'
|
|
83
|
-
description: Docile
|
|
84
|
-
|
|
97
|
+
description: "Docile treats the methods of a given ruby object as a DSL (domain specific
|
|
98
|
+
language) within a given block. \n\nKiller feature: you can also reference methods,
|
|
99
|
+
instance variables, and local variables from the original (non-DSL) context within
|
|
100
|
+
the block. \n\nDocile releases follow Semantic Versioning as defined at semver.org."
|
|
85
101
|
email: marc@usainnov.com
|
|
86
102
|
executables: []
|
|
87
103
|
extensions: []
|
|
@@ -98,18 +114,17 @@ files:
|
|
|
98
114
|
- Rakefile
|
|
99
115
|
- docile.gemspec
|
|
100
116
|
- lib/docile.rb
|
|
117
|
+
- lib/docile/backtrace_filter.rb
|
|
101
118
|
- lib/docile/chaining_fallback_context_proxy.rb
|
|
102
119
|
- lib/docile/execution.rb
|
|
103
120
|
- lib/docile/fallback_context_proxy.rb
|
|
104
121
|
- lib/docile/version.rb
|
|
105
122
|
- on_what.rb
|
|
106
|
-
- spec/docile_spec.rb
|
|
107
|
-
- spec/spec_helper.rb
|
|
108
123
|
homepage: https://ms-ati.github.io/docile/
|
|
109
124
|
licenses:
|
|
110
125
|
- MIT
|
|
111
126
|
metadata: {}
|
|
112
|
-
post_install_message:
|
|
127
|
+
post_install_message:
|
|
113
128
|
rdoc_options: []
|
|
114
129
|
require_paths:
|
|
115
130
|
- lib
|
|
@@ -124,11 +139,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
124
139
|
- !ruby/object:Gem::Version
|
|
125
140
|
version: '0'
|
|
126
141
|
requirements: []
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
signing_key:
|
|
142
|
+
rubygems_version: 3.1.4
|
|
143
|
+
signing_key:
|
|
130
144
|
specification_version: 4
|
|
131
|
-
summary: Docile keeps your Ruby DSLs tame and well-behaved
|
|
132
|
-
test_files:
|
|
133
|
-
- spec/docile_spec.rb
|
|
134
|
-
- spec/spec_helper.rb
|
|
145
|
+
summary: Docile keeps your Ruby DSLs tame and well-behaved.
|
|
146
|
+
test_files: []
|
data/spec/docile_spec.rb
DELETED
|
@@ -1,362 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require 'singleton'
|
|
3
|
-
|
|
4
|
-
describe Docile do
|
|
5
|
-
|
|
6
|
-
describe '.dsl_eval' do
|
|
7
|
-
|
|
8
|
-
context 'when DSL context object is an Array' do
|
|
9
|
-
let(:array) { [] }
|
|
10
|
-
let!(:result) { execute_dsl_against_array }
|
|
11
|
-
|
|
12
|
-
def execute_dsl_against_array
|
|
13
|
-
Docile.dsl_eval(array) do
|
|
14
|
-
push 1
|
|
15
|
-
push 2
|
|
16
|
-
pop
|
|
17
|
-
push 3
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
it 'executes the block against the DSL context object' do
|
|
22
|
-
expect(array).to eq([1, 3])
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
it 'returns the DSL object after executing block against it' do
|
|
26
|
-
expect(result).to eq(array)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
it "doesn't proxy #__id__" do
|
|
30
|
-
Docile.dsl_eval(array) { expect(__id__).not_to eq(array.__id__) }
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
it "raises NoMethodError if the DSL object doesn't implement the method" do
|
|
34
|
-
expect { Docile.dsl_eval(array) { no_such_method } }.to raise_error(NoMethodError)
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
Pizza = Struct.new(:cheese, :pepperoni, :bacon, :sauce)
|
|
39
|
-
|
|
40
|
-
class PizzaBuilder
|
|
41
|
-
def cheese(v=true); @cheese = v; end
|
|
42
|
-
def pepperoni(v=true); @pepperoni = v; end
|
|
43
|
-
def bacon(v=true); @bacon = v; end
|
|
44
|
-
def sauce(v=nil); @sauce = v; end
|
|
45
|
-
def build
|
|
46
|
-
Pizza.new(!!@cheese, !!@pepperoni, !!@bacon, @sauce)
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
context 'when DSL context object is a Builder pattern' do
|
|
51
|
-
let(:builder) { PizzaBuilder.new }
|
|
52
|
-
let(:result) { execute_dsl_against_builder_and_call_build }
|
|
53
|
-
|
|
54
|
-
def execute_dsl_against_builder_and_call_build
|
|
55
|
-
@sauce = :extra
|
|
56
|
-
Docile.dsl_eval(builder) do
|
|
57
|
-
bacon
|
|
58
|
-
cheese
|
|
59
|
-
sauce @sauce
|
|
60
|
-
end.build
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
it 'returns correctly built object' do
|
|
64
|
-
expect(result).to eq(Pizza.new(true, false, true, :extra))
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
class InnerDSL
|
|
69
|
-
def initialize; @b = 'b'; end
|
|
70
|
-
attr_accessor :b
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
class OuterDSL
|
|
74
|
-
def initialize; @a = 'a'; end
|
|
75
|
-
attr_accessor :a
|
|
76
|
-
|
|
77
|
-
def inner(&block)
|
|
78
|
-
Docile.dsl_eval(InnerDSL.new, &block)
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def inner_with_params(param, &block)
|
|
82
|
-
Docile.dsl_eval(InnerDSL.new, param, :foo, &block)
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def outer(&block)
|
|
87
|
-
Docile.dsl_eval(OuterDSL.new, &block)
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
context 'when given parameters for the DSL block' do
|
|
91
|
-
def parameterized(*args, &block)
|
|
92
|
-
Docile.dsl_eval(OuterDSL.new, *args, &block)
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
it 'passes parameters to the block' do
|
|
96
|
-
parameterized(1,2,3) do |x,y,z|
|
|
97
|
-
expect(x).to eq(1)
|
|
98
|
-
expect(y).to eq(2)
|
|
99
|
-
expect(z).to eq(3)
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
it 'finds parameters before methods' do
|
|
104
|
-
parameterized(1) { |a| expect(a).to eq(1) }
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
it 'find outer dsl parameters in inner dsl scope' do
|
|
108
|
-
parameterized(1,2,3) do |a,b,c|
|
|
109
|
-
inner_with_params(c) do |d,e|
|
|
110
|
-
expect(a).to eq(1)
|
|
111
|
-
expect(b).to eq(2)
|
|
112
|
-
expect(c).to eq(3)
|
|
113
|
-
expect(d).to eq(c)
|
|
114
|
-
expect(e).to eq(:foo)
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
class DSLWithNoMethod
|
|
121
|
-
def initialize(b); @b = b; end
|
|
122
|
-
attr_accessor :b
|
|
123
|
-
def push_element
|
|
124
|
-
@b.push 1
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
context 'when DSL have NoMethod error inside' do
|
|
129
|
-
it 'raise error from nil' do
|
|
130
|
-
Docile.dsl_eval(DSLWithNoMethod.new(nil)) do
|
|
131
|
-
expect { push_element }.to raise_error(NoMethodError, /undefined method `push' (for|on) nil:NilClass/)
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
context 'when DSL blocks are nested' do
|
|
137
|
-
|
|
138
|
-
context 'method lookup' do
|
|
139
|
-
it 'finds method of outer dsl in outer dsl scope' do
|
|
140
|
-
outer { expect(a).to eq('a') }
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
it 'finds method of inner dsl in inner dsl scope' do
|
|
144
|
-
outer { inner { expect(b).to eq('b') } }
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
it 'finds method of outer dsl in inner dsl scope' do
|
|
148
|
-
outer { inner { expect(a).to eq('a') } }
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
it "finds method of block's context in outer dsl scope" do
|
|
152
|
-
def c; 'c'; end
|
|
153
|
-
outer { expect(c).to eq('c') }
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
it "finds method of block's context in inner dsl scope" do
|
|
157
|
-
def c; 'c'; end
|
|
158
|
-
outer { inner { expect(c).to eq('c') } }
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
it 'finds method of outer dsl in preference to block context' do
|
|
162
|
-
def a; 'not a'; end
|
|
163
|
-
outer { expect(a).to eq('a') }
|
|
164
|
-
outer { inner { expect(a).to eq('a') } }
|
|
165
|
-
end
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
context 'local variable lookup' do
|
|
169
|
-
it 'finds local variable from block context in outer dsl scope' do
|
|
170
|
-
foo = 'foo'
|
|
171
|
-
outer { expect(foo).to eq('foo') }
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
it 'finds local variable from block definition in inner dsl scope' do
|
|
175
|
-
bar = 'bar'
|
|
176
|
-
outer { inner { expect(bar).to eq('bar') } }
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
context 'instance variable lookup' do
|
|
181
|
-
it 'finds instance variable from block definition in outer dsl scope' do
|
|
182
|
-
@iv1 = 'iv1'; outer { expect(@iv1).to eq('iv1') }
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
it "proxies instance variable assignments in block in outer dsl scope back into block's context" do
|
|
186
|
-
@iv1 = 'foo'; outer { @iv1 = 'bar' }; expect(@iv1).to eq('bar')
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
it 'finds instance variable from block definition in inner dsl scope' do
|
|
190
|
-
@iv2 = 'iv2'; outer { inner { expect(@iv2).to eq('iv2') } }
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
it "proxies instance variable assignments in block in inner dsl scope back into block's context" do
|
|
194
|
-
@iv2 = 'foo'; outer { inner { @iv2 = 'bar' } }; expect(@iv2).to eq('bar')
|
|
195
|
-
end
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
context 'when DSL context object is a Dispatch pattern' do
|
|
201
|
-
class DispatchScope
|
|
202
|
-
def params
|
|
203
|
-
{ :a => 1, :b => 2, :c => 3 }
|
|
204
|
-
end
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
class MessageDispatch
|
|
208
|
-
include Singleton
|
|
209
|
-
|
|
210
|
-
def initialize
|
|
211
|
-
@responders = {}
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
def add_responder path, &block
|
|
215
|
-
@responders[path] = block
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
def dispatch path, request
|
|
219
|
-
Docile.dsl_eval(DispatchScope.new, request, &@responders[path])
|
|
220
|
-
end
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
def respond(path, &block)
|
|
224
|
-
MessageDispatch.instance.add_responder(path, &block)
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
def send_request(path, request)
|
|
228
|
-
MessageDispatch.instance.dispatch(path, request)
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
it 'dispatches correctly' do
|
|
232
|
-
@first = @second = nil
|
|
233
|
-
|
|
234
|
-
respond '/path' do |request|
|
|
235
|
-
@first = request
|
|
236
|
-
end
|
|
237
|
-
|
|
238
|
-
respond '/new_bike' do |bike|
|
|
239
|
-
@second = "Got a new #{bike}"
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
def x(y) ; "Got a #{y}"; end
|
|
243
|
-
respond '/third' do |third|
|
|
244
|
-
expect(x(third)).to eq('Got a third thing')
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
fourth = nil
|
|
248
|
-
respond '/params' do |arg|
|
|
249
|
-
fourth = params[arg]
|
|
250
|
-
end
|
|
251
|
-
|
|
252
|
-
send_request '/path', 1
|
|
253
|
-
send_request '/new_bike', 'ten speed'
|
|
254
|
-
send_request '/third', 'third thing'
|
|
255
|
-
send_request '/params', :b
|
|
256
|
-
|
|
257
|
-
expect(@first).to eq(1)
|
|
258
|
-
expect(@second).to eq('Got a new ten speed')
|
|
259
|
-
expect(fourth).to eq(2)
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
end
|
|
265
|
-
|
|
266
|
-
describe '.dsl_eval_with_block_return' do
|
|
267
|
-
let(:array) { [] }
|
|
268
|
-
let!(:result) { execute_dsl_against_array }
|
|
269
|
-
|
|
270
|
-
def execute_dsl_against_array
|
|
271
|
-
Docile.dsl_eval_with_block_return(array) do
|
|
272
|
-
push 1
|
|
273
|
-
push 2
|
|
274
|
-
pop
|
|
275
|
-
push 3
|
|
276
|
-
'Return me!'
|
|
277
|
-
end
|
|
278
|
-
end
|
|
279
|
-
|
|
280
|
-
it 'executes the block against the DSL context object' do
|
|
281
|
-
expect(array).to eq([1, 3])
|
|
282
|
-
end
|
|
283
|
-
|
|
284
|
-
it "returns the block's return value" do
|
|
285
|
-
expect(result).to eq('Return me!')
|
|
286
|
-
end
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
describe '.dsl_eval_immutable' do
|
|
290
|
-
|
|
291
|
-
context 'when DSL context object is a frozen String' do
|
|
292
|
-
let(:original) { "I'm immutable!".freeze }
|
|
293
|
-
let!(:result) { execute_non_mutating_dsl_against_string }
|
|
294
|
-
|
|
295
|
-
def execute_non_mutating_dsl_against_string
|
|
296
|
-
Docile.dsl_eval_immutable(original) do
|
|
297
|
-
reverse
|
|
298
|
-
upcase
|
|
299
|
-
end
|
|
300
|
-
end
|
|
301
|
-
|
|
302
|
-
it "doesn't modify the original string" do
|
|
303
|
-
expect(original).to eq("I'm immutable!")
|
|
304
|
-
end
|
|
305
|
-
|
|
306
|
-
it 'chains the commands in the block against the DSL context object' do
|
|
307
|
-
expect(result).to eq("!ELBATUMMI M'I")
|
|
308
|
-
end
|
|
309
|
-
end
|
|
310
|
-
|
|
311
|
-
context 'when DSL context object is a number' do
|
|
312
|
-
let(:original) { 84.5 }
|
|
313
|
-
let!(:result) { execute_non_mutating_dsl_against_number }
|
|
314
|
-
|
|
315
|
-
def execute_non_mutating_dsl_against_number
|
|
316
|
-
Docile.dsl_eval_immutable(original) do
|
|
317
|
-
fdiv(2)
|
|
318
|
-
floor
|
|
319
|
-
end
|
|
320
|
-
end
|
|
321
|
-
|
|
322
|
-
it 'chains the commands in the block against the DSL context object' do
|
|
323
|
-
expect(result).to eq(42)
|
|
324
|
-
end
|
|
325
|
-
end
|
|
326
|
-
end
|
|
327
|
-
|
|
328
|
-
end
|
|
329
|
-
|
|
330
|
-
describe Docile::FallbackContextProxy do
|
|
331
|
-
|
|
332
|
-
describe '#instance_variables' do
|
|
333
|
-
subject { create_fcp_and_set_one_instance_variable.instance_variables }
|
|
334
|
-
let(:expected_type_of_names) { type_of_ivar_names_on_this_ruby }
|
|
335
|
-
let(:actual_type_of_names) { subject.first.class }
|
|
336
|
-
let(:excluded) { Docile::FallbackContextProxy::NON_PROXIED_INSTANCE_VARIABLES }
|
|
337
|
-
|
|
338
|
-
def create_fcp_and_set_one_instance_variable
|
|
339
|
-
fcp = Docile::FallbackContextProxy.new(nil, nil)
|
|
340
|
-
fcp.instance_variable_set(:@foo, 'foo')
|
|
341
|
-
fcp
|
|
342
|
-
end
|
|
343
|
-
|
|
344
|
-
def type_of_ivar_names_on_this_ruby
|
|
345
|
-
@a = 1
|
|
346
|
-
instance_variables.first.class
|
|
347
|
-
end
|
|
348
|
-
|
|
349
|
-
it 'returns proxied instance variables' do
|
|
350
|
-
expect(subject.map(&:to_sym)).to include(:@foo)
|
|
351
|
-
end
|
|
352
|
-
|
|
353
|
-
it "doesn't return non-proxied instance variables" do
|
|
354
|
-
expect(subject.map(&:to_sym)).not_to include(*excluded)
|
|
355
|
-
end
|
|
356
|
-
|
|
357
|
-
it 'preserves the type (String or Symbol) of names on this ruby version' do
|
|
358
|
-
expect(actual_type_of_names).to eq(expected_type_of_names)
|
|
359
|
-
end
|
|
360
|
-
end
|
|
361
|
-
|
|
362
|
-
end
|
data/spec/spec_helper.rb
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
require File.expand_path('on_what', File.dirname(File.dirname(__FILE__)))
|
|
2
|
-
|
|
3
|
-
# Code coverage (via SimpleCov) on Ruby 1.9+
|
|
4
|
-
unless on_1_8?
|
|
5
|
-
begin
|
|
6
|
-
require 'simplecov'
|
|
7
|
-
SimpleCov.start do
|
|
8
|
-
add_filter '/spec/' # exclude test code
|
|
9
|
-
add_filter '/vendor/' # exclude gems which are vendored on Travis CI
|
|
10
|
-
add_filter '/on_what.rb' # exclude help used only in gemspec
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# On CI we publish simplecov results to codecov.io
|
|
14
|
-
if on_travis?
|
|
15
|
-
require 'codecov'
|
|
16
|
-
SimpleCov.formatter = SimpleCov::Formatter::Codecov
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# Due to circular dependency (simplecov depends on docile), remove docile and require again below
|
|
20
|
-
Object.send(:remove_const, :Docile)
|
|
21
|
-
$LOADED_FEATURES.reject! { |f| f =~ /\/docile\// }
|
|
22
|
-
rescue LoadError
|
|
23
|
-
warn 'warning: simplecov or codecov gems not found; skipping coverage'
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
lib_dir = File.join(File.dirname(File.dirname(__FILE__)), 'lib')
|
|
28
|
-
$LOAD_PATH.unshift lib_dir unless $LOAD_PATH.include? lib_dir
|
|
29
|
-
|
|
30
|
-
# Require Docile again, now with coverage enabled on 1.9+
|
|
31
|
-
require 'docile'
|