uber 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGES.md +3 -0
- data/Gemfile +2 -0
- data/README.md +61 -13
- data/lib/uber/inheritable_attr.rb +22 -0
- data/lib/uber/options.rb +70 -0
- data/lib/uber/version.rb +1 -1
- data/test/inheritable_attr_test.rb +54 -0
- data/test/inheritance_test.rb +47 -2
- data/test/options_test.rb +72 -0
- data/test/test_helper.rb +0 -3
- data/test/zeugs.rb +54 -0
- data/uber.gemspec +4 -3
- metadata +37 -18
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 58b218477b8c36e49f66c8bd47175bf605613ef1
|
4
|
+
data.tar.gz: bde8206f4395aa6469f9dfe84eb3651449acd0e3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f08f9af53d76f9800741b6eacd147d031a356b40e309172c1323cf5a80b2f1f70271c1f383f7fbcb2681ac72eaf163b64fc364a36888523688cbbb8147185d22
|
7
|
+
data.tar.gz: 8b6a3e28f375e50b829fe60bf5a2a5ab50daafee28cd5e6334d8488e201b85a12ed915ed0e3c1c84938f5006f5ec55a8b1be07141895bdecc8472c24bfa8348e
|
data/CHANGES.md
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Uber
|
2
2
|
|
3
|
-
|
3
|
+
_Gem-authoring tools like class method inheritance in modules, dynamic options and more._
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -8,22 +8,70 @@ Add this line to your application's Gemfile:
|
|
8
8
|
|
9
9
|
gem 'uber'
|
10
10
|
|
11
|
-
|
11
|
+
Ready?
|
12
12
|
|
13
|
-
|
13
|
+
# Inheritable Class Attributes
|
14
14
|
|
15
|
-
|
15
|
+
This is for you if you want class attributes to be inherited, which is a mandatory mechanism for creating DSLs.
|
16
16
|
|
17
|
-
|
17
|
+
```ruby
|
18
|
+
require 'uber/inheritable_attr'
|
18
19
|
|
19
|
-
|
20
|
+
class Song
|
21
|
+
extend Uber::InheritableAttr
|
20
22
|
|
21
|
-
|
23
|
+
inheritable_attr :properties
|
24
|
+
self.properties = [:title, :track] # initialize it before using it.
|
25
|
+
end
|
26
|
+
```
|
22
27
|
|
23
|
-
|
28
|
+
Note that you have to initialize your attribute which whatever you want - usually a hash or an array.
|
24
29
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
+
You can now use that attribute on the class level.
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
Song.properties #=> [:title, :track]
|
34
|
+
```
|
35
|
+
|
36
|
+
Inheriting from `Song` will result in the `properties` object being `clone`d to the sub-class.
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
class Hit < Song
|
40
|
+
end
|
41
|
+
|
42
|
+
Hit.properties #=> [:title, :track]
|
43
|
+
```
|
44
|
+
|
45
|
+
The cool thing about the inheritance is: you can work on the inherited attribute without any restrictions, as it is a _copy_ of the original.
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
Hit.properties << :number
|
49
|
+
|
50
|
+
Hit.properties #=> [:title, :track, :number]
|
51
|
+
Song.properties #=> [:title, :track]
|
52
|
+
```
|
53
|
+
|
54
|
+
It's similar to ActiveSupport's `class_attribute` but with a simpler implementation resulting in a less dangerous potential. Also, there is no restriction about the way you modify the attribute [as found in `class_attribute`](http://apidock.com/rails/v4.0.2/Class/class_attribute).
|
55
|
+
|
56
|
+
This module is very popular amongst numerous gems like Cells, Representable, Roar and Reform.
|
57
|
+
|
58
|
+
|
59
|
+
# Options
|
60
|
+
|
61
|
+
Implements the pattern of defining configuration options and evaluating them at run-time.
|
62
|
+
|
63
|
+
Usually DSL methods accept a number of options that can either be static values, instance method names as symbols, or blocks (lambdas/Procs).
|
64
|
+
|
65
|
+
Uber::Options.new volume: 9, track: lambda { |s| s.track }
|
66
|
+
|
67
|
+
|
68
|
+
Note that `Options` behaves *and performs* like an ordinary hash when all options are static.
|
69
|
+
|
70
|
+
only use for declarative assets, not at runtime (use a hash)
|
71
|
+
|
72
|
+
|
73
|
+
# License
|
74
|
+
|
75
|
+
Copyright (c) 2014 by Nick Sutterer <apotonick@gmail.com>
|
76
|
+
|
77
|
+
Roar is released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Uber
|
2
|
+
module InheritableAttr
|
3
|
+
def inheritable_attr(name)
|
4
|
+
instance_eval %Q{
|
5
|
+
def #{name}=(v)
|
6
|
+
@#{name} = v
|
7
|
+
end
|
8
|
+
|
9
|
+
def #{name}
|
10
|
+
@#{name} ||= InheritableAttribute.inherit_for(self, :#{name})
|
11
|
+
end
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.inherit_for(klass, name)
|
16
|
+
return unless klass.superclass.respond_to?(name) and value = klass.superclass.send(name)
|
17
|
+
value.clone # only do this once.
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
InheritableAttribute = InheritableAttr
|
22
|
+
end
|
data/lib/uber/options.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
module Uber
|
2
|
+
class Options < Hash
|
3
|
+
def initialize(options)
|
4
|
+
@static = options
|
5
|
+
|
6
|
+
options.each do |k,v|
|
7
|
+
self[k] = option = Value.new(v)
|
8
|
+
@static = nil if option.dynamic?
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# 1.100000 0.060000 1.160000 ( 1.159762) original
|
13
|
+
# 0.120000 0.010000 0.130000 ( 0.135803) return self
|
14
|
+
# 0.930000 0.060000 0.990000 ( 0.997095) without v.evaluate
|
15
|
+
|
16
|
+
# Evaluates every element and returns a hash. Accepts context and arbitrary arguments.
|
17
|
+
def evaluate(context, *args)
|
18
|
+
return @static unless dynamic?
|
19
|
+
|
20
|
+
evaluate_for(context, *args)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Evaluates a single value.
|
24
|
+
def eval(key, *args)
|
25
|
+
self[key].evaluate(*args)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
def evaluate_for(context, *args)
|
30
|
+
{}.tap do |evaluated|
|
31
|
+
each do |k,v|
|
32
|
+
evaluated[k] = v.evaluate(context, *args)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def dynamic?
|
38
|
+
not @static
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
class Value # TODO: rename to Value.
|
43
|
+
def initialize(value, options={})
|
44
|
+
@value = value || true
|
45
|
+
@options = options
|
46
|
+
end
|
47
|
+
|
48
|
+
def evaluate(context, *args)
|
49
|
+
return true if @value.is_a?(TrueClass)
|
50
|
+
|
51
|
+
evaluate_for(context, *args)
|
52
|
+
end
|
53
|
+
|
54
|
+
def dynamic?
|
55
|
+
@options[:instance_method] || @value.kind_of?(Proc)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
def evaluate_for(context, *args)
|
60
|
+
return proc!(context, *args) unless @value.kind_of?(Proc)
|
61
|
+
@value.call(context, *args) # TODO: change to context.instance_exec and deprecate first argument.
|
62
|
+
end
|
63
|
+
|
64
|
+
def proc!(context, *args)
|
65
|
+
return context.send(@value, *args) if @options[:instance_method]
|
66
|
+
@value
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/uber/version.rb
CHANGED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require "uber/inheritable_attr"
|
3
|
+
|
4
|
+
class InheritableAttrTest < MiniTest::Spec
|
5
|
+
describe "::inheritable_attr" do
|
6
|
+
subject {
|
7
|
+
Class.new(Object) do
|
8
|
+
extend Uber::InheritableAttribute
|
9
|
+
inheritable_attr :drinks
|
10
|
+
end
|
11
|
+
}
|
12
|
+
|
13
|
+
it "provides a reader with empty inherited attributes, already" do
|
14
|
+
assert_equal nil, subject.drinks
|
15
|
+
end
|
16
|
+
|
17
|
+
it "provides a reader with empty inherited attributes in a derived class" do
|
18
|
+
assert_equal nil, Class.new(subject).drinks
|
19
|
+
#subject.drinks = true
|
20
|
+
#Class.new(subject).drinks # TODO: crashes.
|
21
|
+
end
|
22
|
+
|
23
|
+
it "provides an attribute copy in subclasses" do
|
24
|
+
subject.drinks = []
|
25
|
+
assert subject.drinks.object_id != Class.new(subject).drinks.object_id
|
26
|
+
end
|
27
|
+
|
28
|
+
it "provides a writer" do
|
29
|
+
subject.drinks = [:cabernet]
|
30
|
+
assert_equal [:cabernet], subject.drinks
|
31
|
+
end
|
32
|
+
|
33
|
+
it "inherits attributes" do
|
34
|
+
subject.drinks = [:cabernet]
|
35
|
+
|
36
|
+
subklass_a = Class.new(subject)
|
37
|
+
subklass_a.drinks << :becks
|
38
|
+
|
39
|
+
subklass_b = Class.new(subject)
|
40
|
+
|
41
|
+
assert_equal [:cabernet], subject.drinks
|
42
|
+
assert_equal [:cabernet, :becks], subklass_a.drinks
|
43
|
+
assert_equal [:cabernet], subklass_b.drinks
|
44
|
+
end
|
45
|
+
|
46
|
+
it "does not inherit attributes if we set explicitely" do
|
47
|
+
subject.drinks = [:cabernet]
|
48
|
+
subklass = Class.new(subject)
|
49
|
+
|
50
|
+
subklass.drinks = [:merlot] # we only want merlot explicitely.
|
51
|
+
assert_equal [:merlot], subklass.drinks # no :cabernet, here
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/test/inheritance_test.rb
CHANGED
@@ -1,7 +1,52 @@
|
|
1
1
|
require 'test_helper'
|
2
|
+
require 'uber/inheritable_included'
|
3
|
+
|
4
|
+
module InheritIncludedTo
|
5
|
+
def self.call(includer, proc)
|
6
|
+
proc.call(includer) # das will ich eigentlich machen
|
7
|
+
|
8
|
+
includer.class_eval do
|
9
|
+
@block = proc
|
10
|
+
|
11
|
+
def self.included(base) #
|
12
|
+
InheritIncludedTo.call(base, instance_variable_get(:@block))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
2
17
|
|
3
18
|
class InheritanceTest < MiniTest::Spec
|
4
|
-
|
5
|
-
|
19
|
+
module Feature
|
20
|
+
#extend Uber::InheritedIncluded
|
21
|
+
|
22
|
+
CODE_BLOCK = lambda { |base| base.class_eval { extend ClassMethods } } # i want that to be executed at every include
|
23
|
+
|
24
|
+
|
25
|
+
def self.included(includer) #
|
26
|
+
# CODE_BLOCK.call(base)
|
27
|
+
InheritIncludedTo.call(includer, CODE_BLOCK)
|
28
|
+
end
|
29
|
+
|
30
|
+
module ClassMethods
|
31
|
+
def feature; end
|
32
|
+
end
|
6
33
|
end
|
34
|
+
|
35
|
+
module Extension
|
36
|
+
include Feature
|
37
|
+
|
38
|
+
# TODO: test overriding ::included
|
39
|
+
end
|
40
|
+
|
41
|
+
module Client
|
42
|
+
include Extension
|
43
|
+
end
|
44
|
+
|
45
|
+
module ExtendedClient
|
46
|
+
include Client
|
47
|
+
end
|
48
|
+
|
49
|
+
it { Extension.must_respond_to :feature }
|
50
|
+
it { Client.must_respond_to :feature }
|
51
|
+
it { ExtendedClient.must_respond_to :feature }
|
7
52
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'uber/options'
|
3
|
+
|
4
|
+
class UberOptionTest < MiniTest::Spec
|
5
|
+
Value = Uber::Options::Value
|
6
|
+
|
7
|
+
describe "#dynamic?" do
|
8
|
+
it { Value.new(1).dynamic?.must_equal false }
|
9
|
+
it { Value.new(true).dynamic?.must_equal false }
|
10
|
+
it { Value.new(:loud).dynamic?.must_equal false }
|
11
|
+
|
12
|
+
it { Value.new(lambda {}).dynamic?.must_equal true }
|
13
|
+
it { Value.new(Proc.new{}).dynamic?.must_equal true }
|
14
|
+
it { Value.new(:method, :instance_method => true).dynamic?.must_equal true }
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
# it "speed" do
|
20
|
+
# require "benchmark"
|
21
|
+
|
22
|
+
# options = 1000000.times.collect do
|
23
|
+
# Uber::Options.new(expires: false)
|
24
|
+
# end
|
25
|
+
|
26
|
+
# time = Benchmark.measure do
|
27
|
+
# options.each do |opt|
|
28
|
+
# opt.evaluate(nil)
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
|
32
|
+
# puts "good results"
|
33
|
+
# puts time
|
34
|
+
# end
|
35
|
+
end
|
36
|
+
|
37
|
+
class UberOptionsTest < MiniTest::Spec
|
38
|
+
Options = Uber::Options
|
39
|
+
|
40
|
+
let (:dynamic) { Options.new(:volume =>1, :style => "Punkrock", :track => Proc.new { |i| i.to_s }) }
|
41
|
+
|
42
|
+
describe "#dynamic?" do
|
43
|
+
it { Options.new(:volume =>1, :style => "Punkrock").send(:dynamic?).must_equal false }
|
44
|
+
it { Options.new(:style => Proc.new{}, :volume =>1).send(:dynamic?).must_equal true }
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#evaluate" do
|
48
|
+
|
49
|
+
it { dynamic.evaluate(999).must_equal({:volume =>1, :style => "Punkrock", :track => "999"}) }
|
50
|
+
|
51
|
+
describe "static" do
|
52
|
+
let (:static) { Options.new(:volume =>1, :style => "Punkrock") }
|
53
|
+
|
54
|
+
it { static.evaluate(nil).must_equal({:volume =>1, :style => "Punkrock"}) }
|
55
|
+
|
56
|
+
it "doesn't evaluate internally" do
|
57
|
+
static.instance_eval do
|
58
|
+
def evaluate_for(*)
|
59
|
+
raise "i shouldn't be called!"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
static.evaluate(nil).must_equal({:volume =>1, :style => "Punkrock"})
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "#eval" do
|
68
|
+
it { dynamic.eval(:volume, 999).must_equal 1 }
|
69
|
+
it { dynamic.eval(:style, 999).must_equal "Punkrock" }
|
70
|
+
it { dynamic.eval(:track, 999).must_equal "999" }
|
71
|
+
end
|
72
|
+
end
|
data/test/test_helper.rb
CHANGED
data/test/zeugs.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
module Feature
|
2
|
+
module ClassMethods
|
3
|
+
def feature
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
# in uber, this would look somehow like
|
8
|
+
# module Feature
|
9
|
+
# module ClassMethods ... end
|
10
|
+
|
11
|
+
# extend Uber::InheritableIncluded
|
12
|
+
# inheritable_included do |includer|
|
13
|
+
# includer.extend ClassMethods
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
|
17
|
+
InheritedIncludedCodeBlock = lambda do |includer|
|
18
|
+
includer.extend ClassMethods
|
19
|
+
end
|
20
|
+
|
21
|
+
module RecursiveIncluded
|
22
|
+
def included(includer)
|
23
|
+
#super # TODO: test me.
|
24
|
+
puts "RecursiveIncluded in #{includer}"
|
25
|
+
|
26
|
+
includer.module_eval do
|
27
|
+
InheritedIncludedCodeBlock.call(includer)
|
28
|
+
extend RecursiveIncluded
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
extend RecursiveIncluded
|
33
|
+
end
|
34
|
+
|
35
|
+
module Client
|
36
|
+
include Feature
|
37
|
+
end
|
38
|
+
|
39
|
+
module Extension
|
40
|
+
include Client
|
41
|
+
end
|
42
|
+
|
43
|
+
module Plugin
|
44
|
+
include Extension
|
45
|
+
end
|
46
|
+
|
47
|
+
module Framework
|
48
|
+
include Plugin
|
49
|
+
end
|
50
|
+
|
51
|
+
Client.feature
|
52
|
+
Extension.feature
|
53
|
+
Plugin.feature
|
54
|
+
Framework.feature
|
data/uber.gemspec
CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |gem|
|
|
5
5
|
gem.authors = ["Nick Sutterer"]
|
6
6
|
gem.email = ["apotonick@gmail.com"]
|
7
7
|
gem.description = %q{A gem-authoring framework.}
|
8
|
-
gem.summary = %q{
|
8
|
+
gem.summary = %q{Gem-authoring tools like class method inheritance in modules, dynamic options and more.}
|
9
9
|
gem.homepage = ""
|
10
10
|
|
11
11
|
gem.files = `git ls-files`.split($\)
|
@@ -14,6 +14,7 @@ Gem::Specification.new do |gem|
|
|
14
14
|
gem.name = "uber"
|
15
15
|
gem.require_paths = ["lib"]
|
16
16
|
gem.version = Uber::VERSION
|
17
|
-
|
18
|
-
gem.add_development_dependency "
|
17
|
+
|
18
|
+
gem.add_development_dependency "rake", ">= 0.10.1"
|
19
|
+
gem.add_development_dependency "minitest", ">= 5.0.0"
|
19
20
|
end
|
metadata
CHANGED
@@ -1,32 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uber
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Nick Sutterer
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-03-06 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.10.1
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.10.1
|
14
27
|
- !ruby/object:Gem::Dependency
|
15
28
|
name: minitest
|
16
29
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
30
|
requirements:
|
19
|
-
- -
|
31
|
+
- - ">="
|
20
32
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
33
|
+
version: 5.0.0
|
22
34
|
type: :development
|
23
35
|
prerelease: false
|
24
36
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
37
|
requirements:
|
27
|
-
- -
|
38
|
+
- - ">="
|
28
39
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
40
|
+
version: 5.0.0
|
30
41
|
description: A gem-authoring framework.
|
31
42
|
email:
|
32
43
|
- apotonick@gmail.com
|
@@ -34,41 +45,49 @@ executables: []
|
|
34
45
|
extensions: []
|
35
46
|
extra_rdoc_files: []
|
36
47
|
files:
|
37
|
-
- .gitignore
|
48
|
+
- ".gitignore"
|
49
|
+
- CHANGES.md
|
38
50
|
- Gemfile
|
39
51
|
- LICENSE
|
40
52
|
- README.md
|
41
53
|
- Rakefile
|
42
54
|
- lib/uber.rb
|
55
|
+
- lib/uber/inheritable_attr.rb
|
56
|
+
- lib/uber/options.rb
|
43
57
|
- lib/uber/version.rb
|
58
|
+
- test/inheritable_attr_test.rb
|
44
59
|
- test/inheritance_test.rb
|
60
|
+
- test/options_test.rb
|
45
61
|
- test/test_helper.rb
|
62
|
+
- test/zeugs.rb
|
46
63
|
- uber.gemspec
|
47
64
|
homepage: ''
|
48
65
|
licenses: []
|
66
|
+
metadata: {}
|
49
67
|
post_install_message:
|
50
68
|
rdoc_options: []
|
51
69
|
require_paths:
|
52
70
|
- lib
|
53
71
|
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
-
none: false
|
55
72
|
requirements:
|
56
|
-
- -
|
73
|
+
- - ">="
|
57
74
|
- !ruby/object:Gem::Version
|
58
75
|
version: '0'
|
59
76
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
-
none: false
|
61
77
|
requirements:
|
62
|
-
- -
|
78
|
+
- - ">="
|
63
79
|
- !ruby/object:Gem::Version
|
64
80
|
version: '0'
|
65
81
|
requirements: []
|
66
82
|
rubyforge_project:
|
67
|
-
rubygems_version:
|
83
|
+
rubygems_version: 2.2.1
|
68
84
|
signing_key:
|
69
|
-
specification_version:
|
70
|
-
summary:
|
71
|
-
more.
|
85
|
+
specification_version: 4
|
86
|
+
summary: Gem-authoring tools like class method inheritance in modules, dynamic options
|
87
|
+
and more.
|
72
88
|
test_files:
|
89
|
+
- test/inheritable_attr_test.rb
|
73
90
|
- test/inheritance_test.rb
|
91
|
+
- test/options_test.rb
|
74
92
|
- test/test_helper.rb
|
93
|
+
- test/zeugs.rb
|