elliottcable-refinery 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/.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
|