traitee 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +49 -0
- data/lib/traitee.rb +6 -0
- data/lib/traitee/conflict_solver.rb +42 -0
- data/lib/traitee/dict.rb +34 -0
- data/lib/traitee/merger.rb +16 -0
- data/lib/traitee/trait.rb +45 -0
- data/lib/traitee/version.rb +3 -0
- metadata +66 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b069bf35397a5bd4aebf916dc02feeb4b7b3425b
|
4
|
+
data.tar.gz: 7f3f30df241c16e2cd809db9d042e88477f7a78e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 74f8c42932ad0027f4fe3e698e434d74b358c59cdc742427ac46712f8d8ead8e959d18bd452199ee2ff9ad1edab948423ba8b839f2a23b862f9eed22b3f1daa8
|
7
|
+
data.tar.gz: b6a3e2c8af18e513d38964b14a88597b9914ca887b994f6e4ee3eac2b76e616033bc04feb82f48aecd802caec624c33dc0fcab545874be3d252f4d575fa0a98b
|
data/README.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Traitee
|
2
|
+
|
3
|
+
Mixins or so-called traits for Ruby (like module does not exist :)).
|
4
|
+
|
5
|
+
## How to use Traitee
|
6
|
+
```ruby
|
7
|
+
require 'traitee'
|
8
|
+
|
9
|
+
class Transporter
|
10
|
+
extend(Traitee::Trait)
|
11
|
+
|
12
|
+
serves do
|
13
|
+
def shipping_address
|
14
|
+
'Koniarkova 101, 831 07 Bratislava Slovakia'
|
15
|
+
end
|
16
|
+
|
17
|
+
def current_range
|
18
|
+
kms_left = rand(600) + 10
|
19
|
+
"You have around #{kms_left} kms left."
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Shipper
|
25
|
+
extend(Traitee::Trait)
|
26
|
+
|
27
|
+
attr_accessor :width, :height, :depth
|
28
|
+
|
29
|
+
serves do
|
30
|
+
def set_dimensions(w, h, d)
|
31
|
+
@width = w
|
32
|
+
@height = h
|
33
|
+
@depth = d
|
34
|
+
end
|
35
|
+
|
36
|
+
def dimensions
|
37
|
+
"#{@width} x #{@height} x #{@depth}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class Shipment
|
43
|
+
extend Traitee::Merger
|
44
|
+
merge Shipper, Transporter
|
45
|
+
end
|
46
|
+
|
47
|
+
shipment = Shipment.new
|
48
|
+
```
|
49
|
+
For more examples take a look into files inside examples folder.
|
data/lib/traitee.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module Traitee
|
2
|
+
class MethodsInConflict < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
class ConflictSolver
|
6
|
+
attr_reader :conflicting_methods
|
7
|
+
|
8
|
+
def initialize(methods)
|
9
|
+
@methods = methods
|
10
|
+
@conflicting_methods = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
# java reference :P, actual resolved module holder
|
14
|
+
def this
|
15
|
+
@this ||= Module.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def conflictless_method_map
|
19
|
+
@methods.reduce({}) do |res, map|
|
20
|
+
res.merge!(map) { |method_name, method_a, method_b| solve_possible_conflict(method_name, method_a, method_b) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# let it build, actual error will be raised later on all the usages of the method
|
25
|
+
def solve_possible_conflict(method_name, method_a, method_b)
|
26
|
+
method_a == method_b ? method_a : method_in_conflict(method_name, method_a, method_b)
|
27
|
+
end
|
28
|
+
|
29
|
+
def method_in_conflict(method_name, method_a, method_b)
|
30
|
+
conflict_solver = self
|
31
|
+
@conflicting_methods[method_name] = [method_a, method_b]
|
32
|
+
|
33
|
+
# define a method which raises an error - uncallable
|
34
|
+
this.send(:define_method, method_name) do
|
35
|
+
_method_a, _method_b = conflict_solver.conflicting_methods[method_name]
|
36
|
+
fail MethodsInConflict.new "Modules are in conflict with method :#{method_name}"
|
37
|
+
end
|
38
|
+
|
39
|
+
this.instance_method(method_name)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/traitee/dict.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Traitee
|
4
|
+
class Dict
|
5
|
+
def initialize
|
6
|
+
@methods = Set.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def <<(method)
|
10
|
+
@methods << method
|
11
|
+
end
|
12
|
+
|
13
|
+
def methods_hash(options = {})
|
14
|
+
except = Array(options[:except])
|
15
|
+
aliases = options.fetch :aliases, {}
|
16
|
+
|
17
|
+
methods_hash = Hash[
|
18
|
+
@methods.map { |method| traitee_module, name = method; [name, traitee_module.instance_method(name)] }
|
19
|
+
]
|
20
|
+
methods_hash = exclusions(methods_hash, except)
|
21
|
+
aliases(methods_hash, aliases)
|
22
|
+
end
|
23
|
+
|
24
|
+
# fetch only methods on included in except opts
|
25
|
+
def exclusions(methods, exclusions)
|
26
|
+
methods.select { |method_name, _| !exclusions.include?(method_name) }
|
27
|
+
end
|
28
|
+
|
29
|
+
# create aliases for selected methods as described in opts
|
30
|
+
def aliases(methods, aliases)
|
31
|
+
Hash[methods.map { |method_name, _method| [(aliases.include?(method_name) ? aliases[method_name] : method_name), _method] }]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'traitee/conflict_solver'
|
2
|
+
|
3
|
+
module Traitee
|
4
|
+
module Merger
|
5
|
+
|
6
|
+
#just check for conflicts, if there are any, we will raise an Error on call. Dont overwrite owners methods
|
7
|
+
def merge(*maps)
|
8
|
+
maps.map! { |map| Hash === map ? map : map.methods }
|
9
|
+
conflictless_map = ConflictSolver.new(maps).conflictless_method_map
|
10
|
+
conflictless_map.each do |method_name, method|
|
11
|
+
# do not run check for included super methods
|
12
|
+
send(:define_method, method_name, method) unless instance_methods(false).include?(method_name)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'traitee/merger'
|
3
|
+
require 'traitee/dict'
|
4
|
+
|
5
|
+
module Traitee
|
6
|
+
module Trait
|
7
|
+
extend Forwardable # we want some delegators in here, to delegate to the included trait
|
8
|
+
def_instance_delegators :this, :instance_methods, :send
|
9
|
+
alias_method :[], :methods
|
10
|
+
|
11
|
+
include Merger
|
12
|
+
|
13
|
+
def this
|
14
|
+
@this ||= Module.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def dict
|
18
|
+
@dict ||= Dict.new
|
19
|
+
end
|
20
|
+
|
21
|
+
# usable methods
|
22
|
+
def methods(options = {})
|
23
|
+
served_from(this, *this.instance_methods)
|
24
|
+
dict.methods_hash(options)
|
25
|
+
end
|
26
|
+
|
27
|
+
# helper for actual method definitions
|
28
|
+
def serves(&method_def)
|
29
|
+
this.module_eval(&method_def)
|
30
|
+
end
|
31
|
+
|
32
|
+
# store Module where method is defined (trait) and actual method name
|
33
|
+
def served_from(trait_module, *methods)
|
34
|
+
methods.each { |method_name| dict << [trait_module, method_name] }
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.subject_composition(*params, &block)
|
38
|
+
Class.new do
|
39
|
+
extend Trait
|
40
|
+
merge(*params) unless params.empty?
|
41
|
+
serves(&block) if block
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: traitee
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adam Lieskovsky
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: minitest
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: Traits for Ruby - more dynamic implementation of classic include/extend
|
28
|
+
feature.
|
29
|
+
email:
|
30
|
+
- adamliesko@gmail.com
|
31
|
+
executables: []
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- README.md
|
36
|
+
- lib/traitee.rb
|
37
|
+
- lib/traitee/conflict_solver.rb
|
38
|
+
- lib/traitee/dict.rb
|
39
|
+
- lib/traitee/merger.rb
|
40
|
+
- lib/traitee/trait.rb
|
41
|
+
- lib/traitee/version.rb
|
42
|
+
homepage: http://github.com/adamliesko/traitee
|
43
|
+
licenses:
|
44
|
+
- MIT
|
45
|
+
metadata: {}
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
requirements: []
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 2.4.5.1
|
63
|
+
signing_key:
|
64
|
+
specification_version: 4
|
65
|
+
summary: Mixins or so called traits for Ruby
|
66
|
+
test_files: []
|