traited 1.0.0
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.
- data/LICENSE +20 -0
- data/README.md +40 -0
- data/lib/traited.rb +88 -0
- data/spec/traited_spec.rb +55 -0
- metadata +86 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Lee Jarvis, Michael Fellinger
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
Traited
|
2
|
+
=======
|
3
|
+
|
4
|
+
Traited allows you to add traits to your classes allowing you to create
|
5
|
+
a configuration similar to using class variables. Traited is based on a
|
6
|
+
simple Hash where keys are objects and values are whatever you set.
|
7
|
+
|
8
|
+
Traited also allows you to get all traits across an ancestral chain,
|
9
|
+
where keys later in the ancestors will take precedence.
|
10
|
+
|
11
|
+
This class was taken directly out of the core of the
|
12
|
+
[Innate](https://github.com/Ramaze/innate), but I found it to be useful
|
13
|
+
so I'm extracting it and maintaining it myself. It was written by
|
14
|
+
[Michael Fellinger](https://github.com/manveru).
|
15
|
+
|
16
|
+
Example
|
17
|
+
-------
|
18
|
+
|
19
|
+
class Foo
|
20
|
+
include Traited
|
21
|
+
trait :hello => 'Hello'
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
trait :hello => 'World!'
|
25
|
+
end
|
26
|
+
|
27
|
+
def show
|
28
|
+
[class_trait[:hello], trait[:hello], ancestral_trait[:hello]]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Foo.trait[:hello] # => "Hello"
|
33
|
+
foo = Foo.new
|
34
|
+
foo.trait[:hello] # => "World!"
|
35
|
+
foo.show # => ["Hello", "World!", "World!"]
|
36
|
+
|
37
|
+
Installation
|
38
|
+
------------
|
39
|
+
|
40
|
+
gem install traited
|
data/lib/traited.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
# Traited helps you doing configuration similar to class variables.
|
2
|
+
#
|
3
|
+
# It's built on a simple Hash, where keys are objects and the values the
|
4
|
+
# configuration.
|
5
|
+
# By using {Traited#ancestral_trait} you will get nicely inherited
|
6
|
+
# configuration, where keys later in the ancestors will take precedence.
|
7
|
+
#
|
8
|
+
# @example usage
|
9
|
+
#
|
10
|
+
# class Foo
|
11
|
+
# include Traited
|
12
|
+
# trait :hello => 'Hello'
|
13
|
+
#
|
14
|
+
# def initialize
|
15
|
+
# trait :hello => 'World!'
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# def show
|
19
|
+
# [class_trait[:hello], trait[:hello], ancestral_trait[:hello]]
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# Foo.trait[:hello] # => "Hello"
|
24
|
+
# foo = Foo.new
|
25
|
+
# foo.trait[:hello] # => "World!"
|
26
|
+
# foo.show # => ["Hello", "World!", "World!"]
|
27
|
+
module Traited
|
28
|
+
TRAITS, ANCESTRAL_TRAITS, ANCESTRAL_VALUES = {}, {}, {}
|
29
|
+
|
30
|
+
def self.included(into)
|
31
|
+
into.extend(self)
|
32
|
+
end
|
33
|
+
|
34
|
+
def trait(hash = nil)
|
35
|
+
if hash
|
36
|
+
TRAITS[self] ||= {}
|
37
|
+
result = TRAITS[self].merge!(hash)
|
38
|
+
ANCESTRAL_VALUES.clear
|
39
|
+
ANCESTRAL_TRAITS.clear
|
40
|
+
result
|
41
|
+
else
|
42
|
+
TRAITS[self] || {}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Builds a trait from all the ancestors, closer ancestors overwrite distant
|
47
|
+
# ancestors
|
48
|
+
#
|
49
|
+
# class Foo
|
50
|
+
# include Innate::Traited
|
51
|
+
# trait :one => :eins, :first => :erstes
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# class Bar < Foo
|
55
|
+
# trait :two => :zwei
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# class Foobar < Bar
|
59
|
+
# trait :three => :drei, :first => :overwritten
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# Foobar.ancestral_trait
|
63
|
+
# # => {:three => :drei, :two => :zwei, :one => :eins, :first => :overwritten}
|
64
|
+
def ancestral_trait
|
65
|
+
klass = self.kind_of?(Module) ? self : self.class
|
66
|
+
ANCESTRAL_TRAITS[klass] ||=
|
67
|
+
each_ancestral_trait({}){|hash, trait| hash.update(trait) }
|
68
|
+
end
|
69
|
+
|
70
|
+
def ancestral_trait_values(key)
|
71
|
+
klass = self.kind_of?(Module) ? self : self.class
|
72
|
+
cache = ANCESTRAL_VALUES[klass] ||= {}
|
73
|
+
cache[key] ||= each_ancestral_trait([]){|array, trait|
|
74
|
+
array << trait[key] if trait.key?(key) }
|
75
|
+
end
|
76
|
+
|
77
|
+
def each_ancestral_trait(obj)
|
78
|
+
ancs = respond_to?(:ancestors) ? ancestors : self.class.ancestors
|
79
|
+
ancs.unshift(self)
|
80
|
+
ancs.reverse_each{|anc| yield(obj, TRAITS[anc]) if TRAITS.key?(anc) }
|
81
|
+
obj
|
82
|
+
end
|
83
|
+
|
84
|
+
# trait for self.class if we are an instance
|
85
|
+
def class_trait
|
86
|
+
respond_to?(:ancestors) ? trait : self.class.trait
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require File.expand_path('../../lib/traited', __FILE__)
|
2
|
+
|
3
|
+
class Animal
|
4
|
+
include Traited
|
5
|
+
end
|
6
|
+
|
7
|
+
class Cat < Animal
|
8
|
+
end
|
9
|
+
|
10
|
+
class Tiger < Animal
|
11
|
+
end
|
12
|
+
|
13
|
+
describe Traited do
|
14
|
+
should 'set trait on superclass' do
|
15
|
+
Animal.trait :wild => :depends
|
16
|
+
Animal.trait[:wild].should == :depends
|
17
|
+
end
|
18
|
+
|
19
|
+
should 'reset trait on superclass' do
|
20
|
+
Animal.trait :wild => :naturally
|
21
|
+
Animal.trait[:wild].should == :naturally
|
22
|
+
end
|
23
|
+
|
24
|
+
should 'set trait on instance' do
|
25
|
+
animal = Animal.new
|
26
|
+
animal.trait[:wild].should == nil
|
27
|
+
animal.trait :wild => :depends
|
28
|
+
animal.trait[:wild].should == :depends
|
29
|
+
end
|
30
|
+
|
31
|
+
should 'get ancestral trait from instance' do
|
32
|
+
animal = Animal.new
|
33
|
+
animal.ancestral_trait[:wild].should == :naturally
|
34
|
+
animal.trait :wild => :depends
|
35
|
+
animal.ancestral_trait[:wild].should == :depends
|
36
|
+
end
|
37
|
+
|
38
|
+
should 'set trait on subclass' do
|
39
|
+
Cat.trait :sound => :meow
|
40
|
+
Cat.trait[:sound].should == :meow
|
41
|
+
end
|
42
|
+
|
43
|
+
should 'not modify traits of other classes' do
|
44
|
+
Animal.trait[:sound].should == nil
|
45
|
+
Tiger.trait[:sound].should == nil
|
46
|
+
end
|
47
|
+
|
48
|
+
should 'get ancestral trait from class in superclass' do
|
49
|
+
Cat.ancestral_trait[:wild].should == :naturally
|
50
|
+
end
|
51
|
+
|
52
|
+
should 'get ancestral trait from instance in superclass' do
|
53
|
+
Cat.new.ancestral_trait[:wild].should == :naturally
|
54
|
+
end
|
55
|
+
end
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: traited
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 1.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Lee Jarvis
|
13
|
+
- Michael Fellinger
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-11-19 00:00:00 +00:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: bacon
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
segments:
|
30
|
+
- 1
|
31
|
+
- 1
|
32
|
+
- 0
|
33
|
+
version: 1.1.0
|
34
|
+
type: :development
|
35
|
+
version_requirements: *id001
|
36
|
+
description: Add traits to your classes and access them from children/ancestors
|
37
|
+
email:
|
38
|
+
- lee@jarvis.co
|
39
|
+
- m.fellinger@gmail.com
|
40
|
+
executables: []
|
41
|
+
|
42
|
+
extensions: []
|
43
|
+
|
44
|
+
extra_rdoc_files: []
|
45
|
+
|
46
|
+
files:
|
47
|
+
- LICENSE
|
48
|
+
- README.md
|
49
|
+
- lib/traited.rb
|
50
|
+
- spec/traited_spec.rb
|
51
|
+
has_rdoc: true
|
52
|
+
homepage: ""
|
53
|
+
licenses: []
|
54
|
+
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
segments:
|
66
|
+
- 1
|
67
|
+
- 8
|
68
|
+
- 6
|
69
|
+
version: 1.8.6
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
version: "0"
|
78
|
+
requirements: []
|
79
|
+
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 1.3.7
|
82
|
+
signing_key:
|
83
|
+
specification_version: 3
|
84
|
+
summary: Add traits to your classes and access them from children/ancestors
|
85
|
+
test_files: []
|
86
|
+
|