elliottcable-refinery 0
Sign up to get free protection for your applications and to get access to all the features.
- data/.manifest +12 -0
- data/LICENSE.text +674 -0
- data/README.markdown +126 -0
- data/Rakefile.rb +134 -0
- data/ext/sing/extconf.rb +3 -0
- data/ext/sing/sing.c +13 -0
- data/lib/refinery.rb +10 -0
- data/lib/refinery/core_ext/class.rb +12 -0
- data/lib/refinery/core_ext/object.rb +7 -0
- data/refinery.gemspec +128 -0
- data/spec/refinery/core_ext/class_spec.rb +18 -0
- data/spec/refinery_spec.rb +167 -0
- data/spec/spec_helper.rb +6 -0
- metadata +126 -0
data/README.markdown
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
Refinery
|
2
|
+
========
|
3
|
+
Refinery stemmed from a very specific need that arose while writing
|
4
|
+
[attr_*][] — to be able to utilize the Ruby hooks (for example, the
|
5
|
+
`method_added` and `method_missing` methods) without “gobbling them up” so to
|
6
|
+
speak. Normally, had I used those methods (especially if my particular
|
7
|
+
implementation was very dependent on these methods operating in a specific
|
8
|
+
way), the person using my library would be precluded from using the same
|
9
|
+
methods in whatever class they included/extended my library into; if they used
|
10
|
+
one of those methods for some purpose, their definition would ‘overwrite’ mine,
|
11
|
+
thus quite possibly making my library (or their code using my library) cease
|
12
|
+
to function correctly.
|
13
|
+
|
14
|
+
The simple, singular purpose of Refinery is to ‘refine’ methods in such a way
|
15
|
+
that your important functionality can be assigned safely to these methods.
|
16
|
+
Any attempts to re-define a ‘refined’ method after the refining process will
|
17
|
+
simply ‘stack’ with your own implementation — your method code will execute
|
18
|
+
first, with further re-definitions each being executed in turn when the method
|
19
|
+
is called.
|
20
|
+
|
21
|
+
[attr_*]: <http://by.elliottcable.name/attr_splat.xhtml> "elliottcable's attr_splat project"
|
22
|
+
|
23
|
+
Usage
|
24
|
+
-----
|
25
|
+
Using Refinery is very simple - extend it into your class (or include it into
|
26
|
+
the Class class if you use it often), and then pass a method's name (as a
|
27
|
+
symbol) to the refine_method singleton method. A short example:
|
28
|
+
|
29
|
+
class Something
|
30
|
+
extend Refinery
|
31
|
+
|
32
|
+
def method_missing meth, *args
|
33
|
+
# Do some magic!
|
34
|
+
puts 'abc'
|
35
|
+
end
|
36
|
+
|
37
|
+
refine_method :method_missing
|
38
|
+
end
|
39
|
+
|
40
|
+
# Later, somewhere else…
|
41
|
+
|
42
|
+
class Nothing < Something
|
43
|
+
def method_missing meth, *args
|
44
|
+
# Do other magic, not knowing about the former magic!
|
45
|
+
puts 'def'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
nothing = Nothing.new
|
50
|
+
nothing.nonexistant_method
|
51
|
+
|
52
|
+
Once refined, any further re-openings of your class (or a descendant) and
|
53
|
+
re-definitions of the refined method will simply result in the implementations
|
54
|
+
'stacking' with eachother.
|
55
|
+
|
56
|
+
Care must obviously still be taken to ensure your code will 'stack' in a
|
57
|
+
friendly way with the other implementations — be sure to programmatically
|
58
|
+
check whatever may be necessary before executing your method's code!
|
59
|
+
|
60
|
+
Installation
|
61
|
+
------------
|
62
|
+
You can install Refinery as a pre-built gem, or as a gem generated directly
|
63
|
+
from the source.
|
64
|
+
|
65
|
+
The easiest way to install Refinery is to use [RubyGems][] to acquire the
|
66
|
+
latest 'release' version from [RubyForge][], using the `gem` command line tool:
|
67
|
+
|
68
|
+
sudo gem install refinery # You'll be asked for your account password.
|
69
|
+
|
70
|
+
Alternatively, you can acquire it (possibly slightly more up-to-date,
|
71
|
+
depending on how often I update the gemspec) from GitHub as follows:
|
72
|
+
|
73
|
+
# If you've ever done this before, you don't need to do it now - see http://gems.github.com
|
74
|
+
gem sources -a http://gems.github.com
|
75
|
+
sudo gem install elliottcable-refinery # You'll be asked for your account password.
|
76
|
+
|
77
|
+
Finally, you can build a gem from the latest source yourself. You need [git][],
|
78
|
+
as well as [rake][]:
|
79
|
+
|
80
|
+
git clone git://github.com/elliottcable/refinery.git
|
81
|
+
cd refinery
|
82
|
+
# If you've ever done this before, you don't need to do it now - see http://gems.github.com
|
83
|
+
gem sources -a http://gems.github.com
|
84
|
+
sudo gem install elliottcable-echoe # You'll be asked for your account password.
|
85
|
+
rake install # You'll be asked for your account password.
|
86
|
+
|
87
|
+
[RubyGems]: <http://rubyforge.org/projects/rubygems/> "RubyGems - Ruby package manager"
|
88
|
+
[RubyForge]: <http://rubyforge.org/projects/refinery/> "Refinery on RubyForge"
|
89
|
+
[git]: <http://git-scm.com/> "git - Fast Version Control System"
|
90
|
+
|
91
|
+
Contributing
|
92
|
+
------------
|
93
|
+
You can contribute bug fixes or new features to Refinery by forking the project
|
94
|
+
on GitHub (you'll need to register for an account first), and sending me a
|
95
|
+
pull request once you've committed your changes.
|
96
|
+
|
97
|
+
Links
|
98
|
+
-----
|
99
|
+
- [GitHub](http://github.com/elliottcable/refinery "Refinery on GitHub") is the
|
100
|
+
project's primary repository host, and currently also the project's home
|
101
|
+
page
|
102
|
+
- [RubyForge](http://rubyforge.org/projects/refinery "Refinery on RubyForge") is
|
103
|
+
out primary RubyGem host, as well as an alternative repository host
|
104
|
+
- [integrity](http://integrit.yreality.net/refinery "Refinery on yreality's integrity server")
|
105
|
+
is out continuous integration server - if the top build on that page is
|
106
|
+
green, you can assume the latest git HEAD is safe to run/install/utilize.
|
107
|
+
- [Gitorious](http://gitorious.org/projects/refinery "Refinery on Gitorious") is
|
108
|
+
an alternative repository host
|
109
|
+
- [repo.or.cz](http://repo.or.cz/w/refinery.git "Refinery on repo.or.cz") is
|
110
|
+
an alternative repository host
|
111
|
+
|
112
|
+
Attribution
|
113
|
+
-----------
|
114
|
+
The Sing extension was contributed by [John Mair][banisterfiend].
|
115
|
+
|
116
|
+
[banisterfiend]: <http://banisterfiend.wordpress.com/> "Banisterfiend (John Mair)'s Weblog"
|
117
|
+
|
118
|
+
License
|
119
|
+
-------
|
120
|
+
Refinery is copyright 2008 by elliott cable.
|
121
|
+
|
122
|
+
Refinery is released under the [GNU General Public License v3.0][gpl], which
|
123
|
+
allows you to freely utilize, modify, and distribute all Refinery's source code
|
124
|
+
(subject to the terms of the aforementioned license).
|
125
|
+
|
126
|
+
[gpl]: <http://www.gnu.org/licenses/gpl.txt> "The GNU General Public License v3.0"
|
data/Rakefile.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
($:.unshift File.expand_path(File.join( File.dirname(__FILE__), 'lib' ))).uniq!
|
2
|
+
begin
|
3
|
+
require 'refinery'
|
4
|
+
rescue LoadError
|
5
|
+
module Refinery; Version = -1; end
|
6
|
+
end
|
7
|
+
|
8
|
+
# =======================
|
9
|
+
# = Gem packaging tasks =
|
10
|
+
# =======================
|
11
|
+
begin
|
12
|
+
require 'echoe'
|
13
|
+
|
14
|
+
task :package => :'package:install'
|
15
|
+
task :manifest => :'package:manifest'
|
16
|
+
namespace :package do
|
17
|
+
Echoe.new('refinery', Refinery::Version) do |g|; g.name = 'Refinery'
|
18
|
+
g.project = 'refinery'
|
19
|
+
g.author = ['elliottcable']
|
20
|
+
g.email = ['Refinery@elliottcable.com']
|
21
|
+
g.summary = 'Mmmmagic'
|
22
|
+
g.url = 'http://github.com/elliottcable/refinery'
|
23
|
+
g.development_dependencies = ['elliottcable-echoe >= 3.0.2', 'rspec', 'rcov', 'yard', 'stringray']
|
24
|
+
g.manifest_name = '.manifest'
|
25
|
+
g.retain_gemspec = true
|
26
|
+
g.rakefile_name = 'Rakefile.rb'
|
27
|
+
g.ignore_pattern = /^\.git\/|^meta\/|\.gemspec/
|
28
|
+
end
|
29
|
+
|
30
|
+
desc 'tests packaged files to ensure they are all present'
|
31
|
+
task :verify => :package do
|
32
|
+
# An error message will be displayed if files are missing
|
33
|
+
if system %(ruby -e "require 'rubygems'; require 'pkg/refinery-#{Refinery::Version}/lib/refinery'")
|
34
|
+
puts "\nThe library files are present"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
rescue LoadError
|
40
|
+
desc 'You need the `elliottcable-echoe` gem to package Refinery'
|
41
|
+
task :package
|
42
|
+
end
|
43
|
+
|
44
|
+
# =======================
|
45
|
+
# = Spec/Coverage tasks =
|
46
|
+
# =======================
|
47
|
+
begin
|
48
|
+
require 'spec'
|
49
|
+
require 'rcov'
|
50
|
+
require 'spec/rake/spectask'
|
51
|
+
|
52
|
+
task :default => :'coverage:run'
|
53
|
+
task :coverage => :'coverage:run'
|
54
|
+
namespace :coverage do
|
55
|
+
Spec::Rake::SpecTask.new(:run) do |t|
|
56
|
+
t.spec_opts = ["--format", "specdoc"]
|
57
|
+
t.spec_opts << "--colour" unless ENV['CI']
|
58
|
+
t.spec_files = Dir['spec/**/*_spec.rb'].sort
|
59
|
+
t.libs = ['lib']
|
60
|
+
t.rcov = true
|
61
|
+
t.rcov_opts = [ '--include-file', '"^lib"', '--exclude-only', '".*"']
|
62
|
+
t.rcov_dir = File.join('meta', 'coverage')
|
63
|
+
end
|
64
|
+
|
65
|
+
begin
|
66
|
+
require 'spec/rake/verify_rcov'
|
67
|
+
# For the moment, this is the only way I know of to fix RCov. I may
|
68
|
+
# release the fix as it's own gem at some point in the near future.
|
69
|
+
require 'stringray/core_ext/spec/rake/verify_rcov'
|
70
|
+
RCov::VerifyTask.new(:verify) do |t|
|
71
|
+
t.threshold = 95.0
|
72
|
+
t.index_html = File.join('meta', 'coverage', 'index.html')
|
73
|
+
t.require_exact_threshold = false
|
74
|
+
end
|
75
|
+
rescue LoadError
|
76
|
+
desc 'You need the `stringray` gem to verify coverage'
|
77
|
+
task :verify
|
78
|
+
end
|
79
|
+
|
80
|
+
task :open do
|
81
|
+
system 'open ' + File.join('meta', 'coverage', 'index.html') if PLATFORM['darwin']
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
rescue LoadError
|
86
|
+
desc 'You need the `rcov` and `rspec` gems to run specs/coverage'
|
87
|
+
task :coverage
|
88
|
+
end
|
89
|
+
|
90
|
+
# =======================
|
91
|
+
# = Documentation tasks =
|
92
|
+
# =======================
|
93
|
+
begin
|
94
|
+
require 'yard'
|
95
|
+
require 'yard/rake/yardoc_task'
|
96
|
+
|
97
|
+
task :documentation => :'documentation:generate'
|
98
|
+
namespace :documentation do
|
99
|
+
YARD::Rake::YardocTask.new :generate do |t|
|
100
|
+
t.files = ['lib/**/*.rb']
|
101
|
+
t.options = ['--output-dir', File.join('meta', 'documentation'),
|
102
|
+
'--readme', 'README.markdown']
|
103
|
+
end
|
104
|
+
|
105
|
+
YARD::Rake::YardocTask.new :dotyardoc do |t|
|
106
|
+
t.files = ['lib/**/*.rb']
|
107
|
+
t.options = ['--no-output',
|
108
|
+
'--readme', 'README.markdown']
|
109
|
+
end
|
110
|
+
|
111
|
+
task :open do
|
112
|
+
system 'open ' + File.join('meta', 'documentation', 'index.html') if PLATFORM['darwin']
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
rescue LoadError
|
117
|
+
desc 'You need the `yard` gem to generate documentation'
|
118
|
+
task :documentation
|
119
|
+
end
|
120
|
+
|
121
|
+
# =========
|
122
|
+
# = Other =
|
123
|
+
# =========
|
124
|
+
desc 'Removes all meta producs'
|
125
|
+
task :clobber do
|
126
|
+
`rm -rf #{File.expand_path(File.join( File.dirname(__FILE__), 'meta' ))}`
|
127
|
+
end
|
128
|
+
|
129
|
+
desc 'Check everything over before commiting'
|
130
|
+
task :aok => [:'documentation:generate', :'documentation:open',
|
131
|
+
:'package:manifest', :'package:package', :'package:compile',
|
132
|
+
:'coverage:run', :'coverage:open', :'coverage:verify']
|
133
|
+
|
134
|
+
task :ci => [:'documentation:generate', :'coverage:run', :'coverage:verify']
|
data/ext/sing/extconf.rb
ADDED
data/ext/sing/sing.c
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <stdio.h>
|
3
|
+
|
4
|
+
VALUE jm_Module;
|
5
|
+
VALUE singleton(VALUE self) {
|
6
|
+
if(FL_TEST(self, FL_SINGLETON)) return Qtrue;
|
7
|
+
else return Qfalse;
|
8
|
+
}
|
9
|
+
|
10
|
+
void Init_sing() {
|
11
|
+
jm_Module = rb_define_module("Sing");
|
12
|
+
rb_define_method(jm_Module,"singleton?",singleton,0);
|
13
|
+
}
|
data/lib/refinery.rb
ADDED
data/refinery.gemspec
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
|
2
|
+
# Gem::Specification for Refinery-0
|
3
|
+
# Originally generated by Echoe
|
4
|
+
|
5
|
+
--- !ruby/object:Gem::Specification
|
6
|
+
name: refinery
|
7
|
+
version: !ruby/object:Gem::Version
|
8
|
+
version: "0"
|
9
|
+
platform: ruby
|
10
|
+
authors:
|
11
|
+
- elliottcable
|
12
|
+
autorequire:
|
13
|
+
bindir: bin
|
14
|
+
|
15
|
+
date: 2008-10-12 00:00:00 -08:00
|
16
|
+
default_executable:
|
17
|
+
dependencies:
|
18
|
+
- !ruby/object:Gem::Dependency
|
19
|
+
name: echoe
|
20
|
+
type: :development
|
21
|
+
version_requirement:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.0.1
|
27
|
+
version:
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rspec
|
30
|
+
type: :development
|
31
|
+
version_requirement:
|
32
|
+
version_requirements: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: "0"
|
37
|
+
version:
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: rcov
|
40
|
+
type: :development
|
41
|
+
version_requirement:
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "0"
|
47
|
+
version:
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: yard
|
50
|
+
type: :development
|
51
|
+
version_requirement:
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
version:
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: stringray
|
60
|
+
type: :development
|
61
|
+
version_requirement:
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: "0"
|
67
|
+
version:
|
68
|
+
description: Mmmmagic
|
69
|
+
email:
|
70
|
+
- Refinery@elliottcable.com
|
71
|
+
executables: []
|
72
|
+
|
73
|
+
extensions:
|
74
|
+
- ext/sing/extconf.rb
|
75
|
+
extra_rdoc_files:
|
76
|
+
- ext/sing/extconf.rb
|
77
|
+
- ext/sing/sing.c
|
78
|
+
- lib/refinery/core_ext/class.rb
|
79
|
+
- lib/refinery/core_ext/object.rb
|
80
|
+
- lib/refinery.rb
|
81
|
+
- LICENSE.text
|
82
|
+
- README.markdown
|
83
|
+
files:
|
84
|
+
- ext/sing/extconf.rb
|
85
|
+
- ext/sing/sing.c
|
86
|
+
- lib/refinery/core_ext/class.rb
|
87
|
+
- lib/refinery/core_ext/object.rb
|
88
|
+
- lib/refinery.rb
|
89
|
+
- LICENSE.text
|
90
|
+
- Rakefile.rb
|
91
|
+
- README.markdown
|
92
|
+
- spec/refinery/core_ext/class_spec.rb
|
93
|
+
- spec/refinery_spec.rb
|
94
|
+
- spec/spec_helper.rb
|
95
|
+
- .manifest
|
96
|
+
- refinery.gemspec
|
97
|
+
has_rdoc: true
|
98
|
+
homepage: http://github.com/elliottcable/refinery
|
99
|
+
post_install_message:
|
100
|
+
rdoc_options:
|
101
|
+
- --line-numbers
|
102
|
+
- --inline-source
|
103
|
+
- --title
|
104
|
+
- Refinery
|
105
|
+
- --main
|
106
|
+
- README.markdown
|
107
|
+
require_paths:
|
108
|
+
- lib
|
109
|
+
- ext
|
110
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: "0"
|
115
|
+
version:
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: "1.2"
|
121
|
+
version:
|
122
|
+
requirements: []
|
123
|
+
|
124
|
+
rubyforge_project: refinery
|
125
|
+
rubygems_version: 1.3.0
|
126
|
+
specification_version: 2
|
127
|
+
summary: Mmmmagic
|
128
|
+
test_files: []
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe Class do
|
4
|
+
describe '#is_singleton?' do
|
5
|
+
|
6
|
+
it 'should return false for a normal class' do
|
7
|
+
klass = Class.new
|
8
|
+
klass.should_not be_singleton
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should return true for a singleton class' do
|
12
|
+
klass = Class.new
|
13
|
+
sing = klass.class_eval { class << self; self; end }
|
14
|
+
sing.should be_singleton
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|