concern 0.2.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.
- data/Rakefile.rb +19 -0
- data/Readme.md +74 -0
- data/VERSION +1 -0
- data/concern.gemspec +63 -0
- data/init.rb +2 -0
- data/lib/concern.rb +59 -0
- data/spec/concern_spec.rb +33 -0
- data/spec/examples/a/b.rb +9 -0
- data/spec/examples/a/bc_def_gh.rb +5 -0
- data/spec/examples/adding.rb +29 -0
- data/spec/examples/complex_inline.rb +15 -0
- data/spec/examples/complex_require.rb +8 -0
- data/spec/examples/delegate.rb +12 -0
- data/spec/examples/inline.rb +13 -0
- data/spec/examples/load.rb +8 -0
- data/spec/examples/parent_warning.rb +15 -0
- data/spec/examples/picky_delegate.rb +14 -0
- metadata +88 -0
data/Rakefile.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
task :default => :spec
|
2
|
+
require 'spec/rake/spectask'
|
3
|
+
Spec::Rake::SpecTask.new {|t| t.spec_opts = ['--color']}
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
project_name = 'concern'
|
8
|
+
Jeweler::Tasks.new do |gem|
|
9
|
+
gem.name = project_name
|
10
|
+
gem.description = gem.summary = "Seperation of concerns without meta-madness and namespace pollution"
|
11
|
+
gem.email = "grosser.michael@gmail.com"
|
12
|
+
gem.homepage = "http://github.com/grosser/#{project_name}"
|
13
|
+
gem.authors = ["Michael Grosser"]
|
14
|
+
end
|
15
|
+
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
19
|
+
end
|
data/Readme.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
Seperation of concerns with clean namespaces.
|
2
|
+
|
3
|
+
Normal includes and extensions pollute the namespace and share private/protected.
|
4
|
+
With concern, everything stays in the Concern, can access the concerned and keep namespaced+private.
|
5
|
+
|
6
|
+
Install
|
7
|
+
=======
|
8
|
+
- As Rails plugin: `rails plugin install git://github.com/grosser/concern.git `
|
9
|
+
- As gem: ` gem install concern `
|
10
|
+
|
11
|
+
Usage
|
12
|
+
=====
|
13
|
+
Simple:
|
14
|
+
# a.rb
|
15
|
+
require 'concern'
|
16
|
+
class A
|
17
|
+
concern 'a/acl'
|
18
|
+
|
19
|
+
def admin? ...
|
20
|
+
end
|
21
|
+
|
22
|
+
# a/acl.rb
|
23
|
+
# can access concerned methods like `admin?`
|
24
|
+
class A::ACL < Concern
|
25
|
+
def can_access?(vault)
|
26
|
+
admin? and secret
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def secrect ...
|
32
|
+
end
|
33
|
+
|
34
|
+
A.new.acl.can_access?(BankAccount)
|
35
|
+
|
36
|
+
Let no outsider know, and use delegate:
|
37
|
+
|
38
|
+
class A
|
39
|
+
class Messages
|
40
|
+
def write ...
|
41
|
+
def read ...
|
42
|
+
end
|
43
|
+
|
44
|
+
concern 'a/acl', :delegate => true # delegate all public methods
|
45
|
+
concern 'a/messages', :delegate => [:write]
|
46
|
+
end
|
47
|
+
|
48
|
+
A.new.can_access?(BankAccount) # no more `.acl` needed
|
49
|
+
A.new.write
|
50
|
+
A.new.messages.read
|
51
|
+
|
52
|
+
Adding to the concerned, e.g. validations/associations/scopes etc.
|
53
|
+
class User < ActiveRecord::Base
|
54
|
+
concern 'user/validator', :delegate => true
|
55
|
+
end
|
56
|
+
|
57
|
+
# user/validator.rb
|
58
|
+
class User::Validator < Concern
|
59
|
+
def self.included(concerned)
|
60
|
+
concerned.class_eval do
|
61
|
+
validates_presence_of :name, :if => :name_seems_legit?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def name_seems_legit? ..
|
66
|
+
end
|
67
|
+
|
68
|
+
More examples can be found in [spec/examples](http://github.com/grosser/concern/tree/master/spec/examples)
|
69
|
+
|
70
|
+
Author
|
71
|
+
======
|
72
|
+
[Michael Grosser](http://grosser.it)
|
73
|
+
grosser.michael@gmail.com
|
74
|
+
Hereby placed under public domain, do what you want, just do not hold me accountable...
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.1
|
data/concern.gemspec
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile.rb, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{concern}
|
8
|
+
s.version = "0.2.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Michael Grosser"]
|
12
|
+
s.date = %q{2010-10-19}
|
13
|
+
s.description = %q{Seperation of concerns without meta-madness and namespace pollution}
|
14
|
+
s.email = %q{grosser.michael@gmail.com}
|
15
|
+
s.files = [
|
16
|
+
"Rakefile.rb",
|
17
|
+
"Readme.md",
|
18
|
+
"VERSION",
|
19
|
+
"concern.gemspec",
|
20
|
+
"init.rb",
|
21
|
+
"lib/concern.rb",
|
22
|
+
"spec/concern_spec.rb",
|
23
|
+
"spec/examples/a/b.rb",
|
24
|
+
"spec/examples/a/bc_def_gh.rb",
|
25
|
+
"spec/examples/adding.rb",
|
26
|
+
"spec/examples/complex_inline.rb",
|
27
|
+
"spec/examples/complex_require.rb",
|
28
|
+
"spec/examples/delegate.rb",
|
29
|
+
"spec/examples/inline.rb",
|
30
|
+
"spec/examples/load.rb",
|
31
|
+
"spec/examples/parent_warning.rb",
|
32
|
+
"spec/examples/picky_delegate.rb"
|
33
|
+
]
|
34
|
+
s.homepage = %q{http://github.com/grosser/concern}
|
35
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
36
|
+
s.require_paths = ["lib"]
|
37
|
+
s.rubygems_version = %q{1.3.6}
|
38
|
+
s.summary = %q{Seperation of concerns without meta-madness and namespace pollution}
|
39
|
+
s.test_files = [
|
40
|
+
"spec/concern_spec.rb",
|
41
|
+
"spec/examples/picky_delegate.rb",
|
42
|
+
"spec/examples/complex_inline.rb",
|
43
|
+
"spec/examples/parent_warning.rb",
|
44
|
+
"spec/examples/adding.rb",
|
45
|
+
"spec/examples/complex_require.rb",
|
46
|
+
"spec/examples/load.rb",
|
47
|
+
"spec/examples/a/b.rb",
|
48
|
+
"spec/examples/a/bc_def_gh.rb",
|
49
|
+
"spec/examples/delegate.rb",
|
50
|
+
"spec/examples/inline.rb"
|
51
|
+
]
|
52
|
+
|
53
|
+
if s.respond_to? :specification_version then
|
54
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
55
|
+
s.specification_version = 3
|
56
|
+
|
57
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
58
|
+
else
|
59
|
+
end
|
60
|
+
else
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
data/init.rb
ADDED
data/lib/concern.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
class Concern
|
2
|
+
VERSION = File.read(File.join(File.dirname(__FILE__), '..', 'VERSION'))
|
3
|
+
|
4
|
+
attr_accessor :concerned
|
5
|
+
|
6
|
+
def self.classify(lib)
|
7
|
+
lib.split('/').map{|part| part.gsub(/(?:^|_)(.)/){ $1.upcase } }.join('::')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Object
|
12
|
+
def self.concern(lib, options={})
|
13
|
+
# load delegate
|
14
|
+
lib = lib.to_s
|
15
|
+
klass = Concern.classify(lib)
|
16
|
+
begin
|
17
|
+
klass = eval(klass)
|
18
|
+
rescue
|
19
|
+
require lib
|
20
|
+
klass = eval(klass)
|
21
|
+
end
|
22
|
+
|
23
|
+
unless klass.instance_methods.map{|x|x.to_s}.include?('concerned=')
|
24
|
+
raise "A concern must always extend Concern"
|
25
|
+
end
|
26
|
+
|
27
|
+
# make accessor
|
28
|
+
accessor = lib.split('/').last.to_sym
|
29
|
+
eval <<-EOF
|
30
|
+
def #{accessor}
|
31
|
+
return @#{accessor} if @#{accessor}
|
32
|
+
@#{accessor} = #{klass}.new
|
33
|
+
@#{accessor}.concerned = self
|
34
|
+
@#{accessor}
|
35
|
+
end
|
36
|
+
EOF
|
37
|
+
|
38
|
+
# call included
|
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
|
41
|
+
|
42
|
+
# delegate methods
|
43
|
+
if options[:delegate]
|
44
|
+
methods = if options[:delegate].is_a?(Array)
|
45
|
+
options[:delegate]
|
46
|
+
else
|
47
|
+
klass.public_instance_methods(false)
|
48
|
+
end
|
49
|
+
|
50
|
+
methods.each do |method|
|
51
|
+
eval <<-EOF
|
52
|
+
def #{method}(*args)
|
53
|
+
#{accessor}.#{method}(*args)
|
54
|
+
end
|
55
|
+
EOF
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
describe "Concern" do
|
2
|
+
it "loads a simple file" do
|
3
|
+
`ruby spec/examples/load.rb`.should == "hello"
|
4
|
+
end
|
5
|
+
|
6
|
+
it "requires a complex file" do
|
7
|
+
`ruby spec/examples/complex_require.rb`.should == "SUCCESS"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "can use already present class" do
|
11
|
+
`ruby spec/examples/inline.rb`.should == "inline"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "can use complex present class" do
|
15
|
+
`ruby spec/examples/complex_inline.rb`.should == "SUCCESS"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "can delegate" do
|
19
|
+
`ruby spec/examples/delegate.rb`.should == "hello"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "can delegate some" do
|
23
|
+
`ruby spec/examples/picky_delegate.rb`.should == "hello"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "add to parent" do
|
27
|
+
`ruby spec/examples/adding.rb`.should == "yepworld"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "warns when parent is not Concern" do
|
31
|
+
`ruby spec/examples/parent_warning.rb`.should == "SUCCESS"
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
$LOAD_PATH << 'lib' << 'spec/examples'
|
2
|
+
require 'concern'
|
3
|
+
|
4
|
+
class A
|
5
|
+
class B < Concern
|
6
|
+
def initialize
|
7
|
+
super
|
8
|
+
@hello = 'world'
|
9
|
+
end
|
10
|
+
|
11
|
+
def hello
|
12
|
+
@hello
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.included(base)
|
16
|
+
base.class_eval do
|
17
|
+
test
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.test
|
23
|
+
print "yep"
|
24
|
+
end
|
25
|
+
|
26
|
+
concern 'a/b'
|
27
|
+
end
|
28
|
+
|
29
|
+
print A.new.b.hello
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: concern
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 1
|
9
|
+
version: 0.2.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Michael Grosser
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-10-19 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: Seperation of concerns without meta-madness and namespace pollution
|
22
|
+
email: grosser.michael@gmail.com
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- Rakefile.rb
|
31
|
+
- Readme.md
|
32
|
+
- VERSION
|
33
|
+
- concern.gemspec
|
34
|
+
- init.rb
|
35
|
+
- lib/concern.rb
|
36
|
+
- spec/concern_spec.rb
|
37
|
+
- spec/examples/a/b.rb
|
38
|
+
- spec/examples/a/bc_def_gh.rb
|
39
|
+
- spec/examples/adding.rb
|
40
|
+
- spec/examples/complex_inline.rb
|
41
|
+
- spec/examples/complex_require.rb
|
42
|
+
- spec/examples/delegate.rb
|
43
|
+
- spec/examples/inline.rb
|
44
|
+
- spec/examples/load.rb
|
45
|
+
- spec/examples/parent_warning.rb
|
46
|
+
- spec/examples/picky_delegate.rb
|
47
|
+
has_rdoc: true
|
48
|
+
homepage: http://github.com/grosser/concern
|
49
|
+
licenses: []
|
50
|
+
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options:
|
53
|
+
- --charset=UTF-8
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
segments:
|
68
|
+
- 0
|
69
|
+
version: "0"
|
70
|
+
requirements: []
|
71
|
+
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.3.6
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: Seperation of concerns without meta-madness and namespace pollution
|
77
|
+
test_files:
|
78
|
+
- spec/concern_spec.rb
|
79
|
+
- spec/examples/picky_delegate.rb
|
80
|
+
- spec/examples/complex_inline.rb
|
81
|
+
- spec/examples/parent_warning.rb
|
82
|
+
- spec/examples/adding.rb
|
83
|
+
- spec/examples/complex_require.rb
|
84
|
+
- spec/examples/load.rb
|
85
|
+
- spec/examples/a/b.rb
|
86
|
+
- spec/examples/a/bc_def_gh.rb
|
87
|
+
- spec/examples/delegate.rb
|
88
|
+
- spec/examples/inline.rb
|