concern 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Readme.md +7 -3
- data/VERSION +1 -1
- data/concern.gemspec +7 -3
- data/lib/concern.rb +34 -25
- data/spec/concern_spec.rb +8 -0
- data/spec/examples/blocks.rb +13 -0
- data/spec/examples/pollution.rb +24 -0
- metadata +7 -3
data/Readme.md
CHANGED
@@ -67,8 +67,12 @@ Adding to the concerned, e.g. validations/associations/scopes etc.
|
|
67
67
|
|
68
68
|
More examples can be found in [spec/examples](http://github.com/grosser/concern/tree/master/spec/examples)
|
69
69
|
|
70
|
-
|
71
|
-
|
70
|
+
Authors
|
71
|
+
=======
|
72
|
+
|
73
|
+
### [Contributors](http://github.com/grosser/concern/contributors)
|
74
|
+
- [Colin Curtin](http://github.com/perplexes)
|
75
|
+
|
72
76
|
[Michael Grosser](http://grosser.it)
|
73
77
|
grosser.michael@gmail.com
|
74
|
-
Hereby placed under public domain, do what you want, just do not hold me accountable...
|
78
|
+
Hereby placed under public domain, do what you want, just do not hold me accountable...
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.2
|
data/concern.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{concern}
|
8
|
-
s.version = "0.2.
|
8
|
+
s.version = "0.2.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Michael Grosser"]
|
12
|
-
s.date = %q{2010-10-
|
12
|
+
s.date = %q{2010-10-29}
|
13
13
|
s.description = %q{Seperation of concerns without meta-madness and namespace pollution}
|
14
14
|
s.email = %q{grosser.michael@gmail.com}
|
15
15
|
s.files = [
|
@@ -23,13 +23,15 @@ Gem::Specification.new do |s|
|
|
23
23
|
"spec/examples/a/b.rb",
|
24
24
|
"spec/examples/a/bc_def_gh.rb",
|
25
25
|
"spec/examples/adding.rb",
|
26
|
+
"spec/examples/blocks.rb",
|
26
27
|
"spec/examples/complex_inline.rb",
|
27
28
|
"spec/examples/complex_require.rb",
|
28
29
|
"spec/examples/delegate.rb",
|
29
30
|
"spec/examples/inline.rb",
|
30
31
|
"spec/examples/load.rb",
|
31
32
|
"spec/examples/parent_warning.rb",
|
32
|
-
"spec/examples/picky_delegate.rb"
|
33
|
+
"spec/examples/picky_delegate.rb",
|
34
|
+
"spec/examples/pollution.rb"
|
33
35
|
]
|
34
36
|
s.homepage = %q{http://github.com/grosser/concern}
|
35
37
|
s.rdoc_options = ["--charset=UTF-8"]
|
@@ -42,10 +44,12 @@ Gem::Specification.new do |s|
|
|
42
44
|
"spec/examples/complex_inline.rb",
|
43
45
|
"spec/examples/parent_warning.rb",
|
44
46
|
"spec/examples/adding.rb",
|
47
|
+
"spec/examples/pollution.rb",
|
45
48
|
"spec/examples/complex_require.rb",
|
46
49
|
"spec/examples/load.rb",
|
47
50
|
"spec/examples/a/b.rb",
|
48
51
|
"spec/examples/a/bc_def_gh.rb",
|
52
|
+
"spec/examples/blocks.rb",
|
49
53
|
"spec/examples/delegate.rb",
|
50
54
|
"spec/examples/inline.rb"
|
51
55
|
]
|
data/lib/concern.rb
CHANGED
@@ -6,11 +6,8 @@ class Concern
|
|
6
6
|
def self.classify(lib)
|
7
7
|
lib.split('/').map{|part| part.gsub(/(?:^|_)(.)/){ $1.upcase } }.join('::')
|
8
8
|
end
|
9
|
-
end
|
10
9
|
|
11
|
-
|
12
|
-
def self.concern(lib, options={})
|
13
|
-
# load delegate
|
10
|
+
def self.class_from_lib(lib)
|
14
11
|
lib = lib.to_s
|
15
12
|
klass = Concern.classify(lib)
|
16
13
|
begin
|
@@ -23,37 +20,49 @@ class Object
|
|
23
20
|
unless klass.instance_methods.map{|x|x.to_s}.include?('concerned=')
|
24
21
|
raise "A concern must always extend Concern"
|
25
22
|
end
|
23
|
+
klass
|
24
|
+
end
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
eval <<-EOF
|
26
|
+
def self.add_accessor_for_concern(concerned, accessor, concern)
|
27
|
+
concerned.class_eval <<-EOF, __FILE__, __LINE__
|
30
28
|
def #{accessor}
|
31
29
|
return @#{accessor} if @#{accessor}
|
32
|
-
@#{accessor} = #{
|
30
|
+
@#{accessor} = #{concern}.new
|
33
31
|
@#{accessor}.concerned = self
|
34
32
|
@#{accessor}
|
35
33
|
end
|
36
34
|
EOF
|
35
|
+
end
|
36
|
+
|
37
|
+
module ClassMethods
|
38
|
+
def concern(lib, options={})
|
39
|
+
concern = Concern.class_from_lib(lib)
|
40
|
+
accessor = lib.split('/').last.to_sym
|
37
41
|
|
38
|
-
|
39
|
-
base = eval(name) #self.class is always Class, but name is class that called concern
|
40
|
-
klass.included(base) if klass.respond_to? :included
|
42
|
+
Concern.add_accessor_for_concern(self, accessor, concern)
|
41
43
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
options[:delegate]
|
46
|
-
else
|
47
|
-
klass.public_instance_methods(false)
|
48
|
-
end
|
44
|
+
# tell the concern it was included
|
45
|
+
concerned = eval(name) #self.class is always Class, but name is class that called concern
|
46
|
+
concern.included(concerned) if concern.respond_to? :included
|
49
47
|
|
50
|
-
methods
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
48
|
+
# delegate methods calls to the concern
|
49
|
+
if options[:delegate]
|
50
|
+
methods_to_delegate = if options[:delegate].is_a?(Array)
|
51
|
+
options[:delegate]
|
52
|
+
else
|
53
|
+
concern.public_instance_methods(false)
|
54
|
+
end
|
55
|
+
|
56
|
+
methods_to_delegate.each do |method|
|
57
|
+
class_eval <<-EOF, __FILE__, __LINE__
|
58
|
+
def #{method}(*args, &block)
|
59
|
+
#{accessor}.send(:#{method}, *args, &block)
|
60
|
+
end
|
61
|
+
EOF
|
62
|
+
end
|
56
63
|
end
|
57
64
|
end
|
58
65
|
end
|
59
|
-
end
|
66
|
+
end
|
67
|
+
|
68
|
+
Object.send(:extend, Concern::ClassMethods)
|
data/spec/concern_spec.rb
CHANGED
@@ -30,4 +30,12 @@ describe "Concern" do
|
|
30
30
|
it "warns when parent is not Concern" do
|
31
31
|
`ruby spec/examples/parent_warning.rb`.should == "SUCCESS"
|
32
32
|
end
|
33
|
+
|
34
|
+
it "shouldn't pollute the global namespace" do
|
35
|
+
`ruby spec/examples/pollution.rb`.should == "SUCCESS"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should delegate blocks" do
|
39
|
+
`ruby spec/examples/blocks.rb`.should == "SUCCESS"
|
40
|
+
end
|
33
41
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
$LOAD_PATH << 'lib'
|
2
|
+
require 'concern'
|
3
|
+
|
4
|
+
class A
|
5
|
+
class B < Concern
|
6
|
+
def random_method_name
|
7
|
+
end
|
8
|
+
end
|
9
|
+
concern 'a/b', :delegate => [:random_method_name]
|
10
|
+
end
|
11
|
+
|
12
|
+
class C
|
13
|
+
class D < Concern
|
14
|
+
def random_method_name2
|
15
|
+
end
|
16
|
+
end
|
17
|
+
concern 'c/d', :delegate => true
|
18
|
+
end
|
19
|
+
|
20
|
+
if Object.instance_methods.include?("random_method_name") && Object.instance_methods.include?("random_method_name2")
|
21
|
+
print "FAIL"
|
22
|
+
else
|
23
|
+
print "SUCCESS"
|
24
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
8
|
+
- 2
|
9
|
+
version: 0.2.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Michael Grosser
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-10-
|
17
|
+
date: 2010-10-29 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -37,6 +37,7 @@ files:
|
|
37
37
|
- spec/examples/a/b.rb
|
38
38
|
- spec/examples/a/bc_def_gh.rb
|
39
39
|
- spec/examples/adding.rb
|
40
|
+
- spec/examples/blocks.rb
|
40
41
|
- spec/examples/complex_inline.rb
|
41
42
|
- spec/examples/complex_require.rb
|
42
43
|
- spec/examples/delegate.rb
|
@@ -44,6 +45,7 @@ files:
|
|
44
45
|
- spec/examples/load.rb
|
45
46
|
- spec/examples/parent_warning.rb
|
46
47
|
- spec/examples/picky_delegate.rb
|
48
|
+
- spec/examples/pollution.rb
|
47
49
|
has_rdoc: true
|
48
50
|
homepage: http://github.com/grosser/concern
|
49
51
|
licenses: []
|
@@ -80,9 +82,11 @@ test_files:
|
|
80
82
|
- spec/examples/complex_inline.rb
|
81
83
|
- spec/examples/parent_warning.rb
|
82
84
|
- spec/examples/adding.rb
|
85
|
+
- spec/examples/pollution.rb
|
83
86
|
- spec/examples/complex_require.rb
|
84
87
|
- spec/examples/load.rb
|
85
88
|
- spec/examples/a/b.rb
|
86
89
|
- spec/examples/a/bc_def_gh.rb
|
90
|
+
- spec/examples/blocks.rb
|
87
91
|
- spec/examples/delegate.rb
|
88
92
|
- spec/examples/inline.rb
|