tweak 0.1.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/README.markdown +101 -0
- data/Rakefile +59 -0
- data/lib/tweak.rb +70 -0
- data/lib/tweak/version.rb +3 -0
- data/lib/tweak/version_flymake.rb +3 -0
- data/test/test.rb +53 -0
- metadata +98 -0
data/README.markdown
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
Tweak
|
2
|
+
=============
|
3
|
+
|
4
|
+
(C) John Mair (banisterfiend) 2010
|
5
|
+
|
6
|
+
_Scoped modification of core classes_
|
7
|
+
|
8
|
+
Add temporary functionality to core classes.
|
9
|
+
|
10
|
+
Based on some ideas found in this [Ruby-Forum thread](http://www.ruby-forum.com/topic/179060)
|
11
|
+
|
12
|
+
`Tweak` provides the `using` method.
|
13
|
+
|
14
|
+
* Install the [gem](https://rubygems.org/gems/tweak): `gem install tweak`
|
15
|
+
* Read the [documentation](http://rdoc.info/github/banister/tweak/master/file/README.markdown)
|
16
|
+
* See the [source code](http://github.com/banister/tweak)
|
17
|
+
|
18
|
+
example: using
|
19
|
+
-------------------------
|
20
|
+
|
21
|
+
With the `using` method we can enhance a core class for the duration
|
22
|
+
of a block:
|
23
|
+
|
24
|
+
module Tweaks
|
25
|
+
|
26
|
+
class String
|
27
|
+
def hello
|
28
|
+
:hello
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Fixnum
|
33
|
+
Hello = :hello
|
34
|
+
|
35
|
+
def bye
|
36
|
+
:bye
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
using Tweaks do
|
43
|
+
"john".hello #=> :hello
|
44
|
+
5.bye #=> :bye
|
45
|
+
Fixnum::Hello #=> :hello
|
46
|
+
end
|
47
|
+
|
48
|
+
"john".hello #=> NameError
|
49
|
+
|
50
|
+
How it works
|
51
|
+
--------------
|
52
|
+
|
53
|
+
Makes use of the `Remix` and `Object2module` libraries. Note that `Tweak`
|
54
|
+
modifies core classes by what is effectively a module inclusion, this
|
55
|
+
means you cannot use `Tweak` to override existing functionality but
|
56
|
+
more to augment and supplement that functionality.
|
57
|
+
|
58
|
+
`Tweak` works by doing the following:
|
59
|
+
|
60
|
+
* Looks for top-level classes and modules with the same name as those
|
61
|
+
defined under the using-module.
|
62
|
+
* Uses `Object2module` to include the corresponding class/module
|
63
|
+
defined under the using-module into the top-level class/module of the
|
64
|
+
same name.
|
65
|
+
* Uses `Remix` to uninclude that functionality at the end of the `using` block.
|
66
|
+
|
67
|
+
Thread Safety
|
68
|
+
--------------
|
69
|
+
|
70
|
+
`Tweak` is not threadsafe.
|
71
|
+
|
72
|
+
Limitations
|
73
|
+
-----------
|
74
|
+
|
75
|
+
Does not work with nested modules, e.g `class String::SomethingElse`
|
76
|
+
|
77
|
+
This is not intended to be a robust or serious solution, it's just a
|
78
|
+
little experiment. :)
|
79
|
+
|
80
|
+
Companion Libraries
|
81
|
+
--------------------
|
82
|
+
|
83
|
+
Tweak is one of a series of experimental libraries that mess with
|
84
|
+
the internals of Ruby to bring new and interesting functionality to
|
85
|
+
the language, see also:
|
86
|
+
|
87
|
+
* [Remix](http://github.com/banister/remix) - Makes ancestor chains read/write
|
88
|
+
* [Object2module](http://github.com/banister/object2module) - Enables you to include/extend Object/Classes.
|
89
|
+
* [Include Complete](http://github.com/banister/include_complete) - Brings in
|
90
|
+
module singleton classes during an include. No more ugly ClassMethods and included() hook hacks.
|
91
|
+
* [Prepend](http://github.com/banister/prepend) - Prepends modules in front of a class; so method lookup starts with the module
|
92
|
+
* [GenEval](http://github.com/banister/gen_eval) - A strange new breed of instance_eval
|
93
|
+
* [LocalEval](http://github.com/banister/local_eval) - instance_eval without changing self
|
94
|
+
|
95
|
+
Contact
|
96
|
+
-------
|
97
|
+
|
98
|
+
Problems or questions contact me at [github](http://github.com/banister)
|
99
|
+
|
100
|
+
|
101
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
dlext = Config::CONFIG['DLEXT']
|
2
|
+
direc = File.dirname(__FILE__)
|
3
|
+
|
4
|
+
require 'rake/clean'
|
5
|
+
require 'rake/gempackagetask'
|
6
|
+
require "#{direc}/lib/tweak/version"
|
7
|
+
|
8
|
+
CLOBBER.include("**/*.#{dlext}", "**/*~", "**/*#*", "**/*.log", "**/*.o")
|
9
|
+
CLEAN.include("ext/**/*.#{dlext}", "ext/**/*.log", "ext/**/*.o",
|
10
|
+
"ext/**/*~", "ext/**/*#*", "ext/**/*.obj",
|
11
|
+
"ext/**/*.def", "ext/**/*.pdb", "**/*_flymake*.*", "**/*_flymake")
|
12
|
+
|
13
|
+
def apply_spec_defaults(s)
|
14
|
+
s.name = "tweak"
|
15
|
+
s.summary = "basic selector namespace implementation"
|
16
|
+
s.version = Tweak::VERSION
|
17
|
+
s.date = Time.now.strftime '%Y-%m-%d'
|
18
|
+
s.author = "John Mair (banisterfiend)"
|
19
|
+
s.email = 'jrmair@gmail.com'
|
20
|
+
s.description = s.summary
|
21
|
+
s.require_path = 'lib'
|
22
|
+
s.add_dependency("remix",">=0.4.9")
|
23
|
+
s.add_dependency("object2module",">=0.5.0")
|
24
|
+
s.homepage = "http://banisterfiend.wordpress.com"
|
25
|
+
s.has_rdoc = 'yard'
|
26
|
+
s.files = Dir["ext/**/extconf.rb", "ext/**/*.h", "ext/**/*.c", "lib/**/*.rb",
|
27
|
+
"test/*.rb", "CHANGELOG", "README.markdown", "Rakefile"]
|
28
|
+
end
|
29
|
+
|
30
|
+
task :test do
|
31
|
+
sh "bacon -k #{direc}/test/test.rb"
|
32
|
+
end
|
33
|
+
|
34
|
+
namespace :ruby do
|
35
|
+
spec = Gem::Specification.new do |s|
|
36
|
+
apply_spec_defaults(s)
|
37
|
+
s.platform = Gem::Platform::RUBY
|
38
|
+
end
|
39
|
+
|
40
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
41
|
+
pkg.need_zip = false
|
42
|
+
pkg.need_tar = false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "build all platform gems at once"
|
47
|
+
task :gems => [:rmgems, "ruby:gem"]
|
48
|
+
|
49
|
+
desc "remove all platform gems"
|
50
|
+
task :rmgems => ["ruby:clobber_package"]
|
51
|
+
|
52
|
+
desc "build and push latest gems"
|
53
|
+
task :pushgems => :gems do
|
54
|
+
chdir("#{direc}/pkg") do
|
55
|
+
Dir["*.gem"].each do |gemfile|
|
56
|
+
sh "gem push #{gemfile}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/tweak.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
direc = File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require "#{direc}/tweak/version.rb"
|
4
|
+
require 'object2module'
|
5
|
+
require 'remix'
|
6
|
+
|
7
|
+
module Tweak
|
8
|
+
module ObjectExtensions
|
9
|
+
|
10
|
+
# Temporarily augment the top-level classes/modules of the same
|
11
|
+
# name as those defined in the using-module for the duration of
|
12
|
+
# the block.
|
13
|
+
# @yield The block where the functionality shall be available.
|
14
|
+
# @return The value of the block
|
15
|
+
# @param [Module, Symbol] name The using-module, may either be the
|
16
|
+
# name of the using-module as a Symbol or the actual Module itself
|
17
|
+
# @example
|
18
|
+
# module Tweaks
|
19
|
+
# class String
|
20
|
+
# def hello() :hello end
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# using Tweaks do
|
25
|
+
# "john".hello #=> :hello
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# "john".hello #=> NoMethodError
|
29
|
+
def using(name, &block)
|
30
|
+
mod = name
|
31
|
+
if name.instance_of?(Symbol)
|
32
|
+
mod = Object.const_get(name)
|
33
|
+
end
|
34
|
+
|
35
|
+
raise "name is not a Module or a Symbol" if !mod.instance_of?(Module)
|
36
|
+
|
37
|
+
tweaks = {}
|
38
|
+
begin
|
39
|
+
mod.constants.each do |v|
|
40
|
+
tweaked_source = mod.const_get(v)
|
41
|
+
|
42
|
+
# Only include the class/module from the using-module if:
|
43
|
+
# 1. The class/module in the using-module is a module (or class)
|
44
|
+
# 2. A corresponding module (or class) is found at top-level
|
45
|
+
next if !tweaked_source.instance_of?(Module) && !Object.const_defined?(v) &&
|
46
|
+
!Object.const_get(v).instance_of?(Module)
|
47
|
+
|
48
|
+
tweak_dest = Object.const_get(v)
|
49
|
+
tweak_source = mod.const_get(v)
|
50
|
+
tweak_dest.gen_include(tweak_source)
|
51
|
+
tweaks[tweak_dest] = tweaked_source
|
52
|
+
end
|
53
|
+
|
54
|
+
yield
|
55
|
+
|
56
|
+
ensure
|
57
|
+
|
58
|
+
# Uninclude all the using-module classes/modules
|
59
|
+
tweaks.each do |tweak_dest, tweak_source|
|
60
|
+
tweak_dest.uninclude(tweak_source, true)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class Object
|
68
|
+
include Tweak::ObjectExtensions
|
69
|
+
end
|
70
|
+
|
data/test/test.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
direc = File.dirname(__FILE__)
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bacon'
|
4
|
+
require "#{direc}/../lib/tweak"
|
5
|
+
|
6
|
+
class Module
|
7
|
+
public :include, :remove_const
|
8
|
+
end
|
9
|
+
|
10
|
+
puts "testing Tweak version #{Tweak::VERSION}..."
|
11
|
+
|
12
|
+
describe Object2module do
|
13
|
+
before do
|
14
|
+
module Tweaks
|
15
|
+
|
16
|
+
class String
|
17
|
+
def hello
|
18
|
+
:hello
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Fixnum
|
23
|
+
Hello = :hello
|
24
|
+
|
25
|
+
def bye
|
26
|
+
:bye
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
after do
|
34
|
+
Object.remove_const(:Tweaks)
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'using' do
|
38
|
+
it 'tweaks functionality of String and Fixnum classes for duration of block' do
|
39
|
+
lambda { "john".hello }.should.raise NoMethodError
|
40
|
+
lambda { 5.bye }.should.raise NoMethodError
|
41
|
+
|
42
|
+
using Tweaks do
|
43
|
+
"john".hello.should == :hello
|
44
|
+
5.bye.should == :bye
|
45
|
+
Fixnum::Hello.should == :hello
|
46
|
+
end
|
47
|
+
|
48
|
+
lambda { "john".hello }.should.raise NoMethodError
|
49
|
+
lambda { 5.bye }.should.raise NoMethodError
|
50
|
+
Fixnum.const_defined?(:Hello).should == false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tweak
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 1
|
9
|
+
version: 0.1.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- John Mair (banisterfiend)
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-11-17 00:00:00 +13:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: remix
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
- 4
|
31
|
+
- 9
|
32
|
+
version: 0.4.9
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: object2module
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
- 5
|
46
|
+
- 0
|
47
|
+
version: 0.5.0
|
48
|
+
type: :runtime
|
49
|
+
version_requirements: *id002
|
50
|
+
description: basic selector namespace implementation
|
51
|
+
email: jrmair@gmail.com
|
52
|
+
executables: []
|
53
|
+
|
54
|
+
extensions: []
|
55
|
+
|
56
|
+
extra_rdoc_files: []
|
57
|
+
|
58
|
+
files:
|
59
|
+
- lib/tweak/version.rb
|
60
|
+
- lib/tweak/version_flymake.rb
|
61
|
+
- lib/tweak.rb
|
62
|
+
- test/test.rb
|
63
|
+
- README.markdown
|
64
|
+
- Rakefile
|
65
|
+
has_rdoc: yard
|
66
|
+
homepage: http://banisterfiend.wordpress.com
|
67
|
+
licenses: []
|
68
|
+
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
segments:
|
80
|
+
- 0
|
81
|
+
version: "0"
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
segments:
|
88
|
+
- 0
|
89
|
+
version: "0"
|
90
|
+
requirements: []
|
91
|
+
|
92
|
+
rubyforge_project:
|
93
|
+
rubygems_version: 1.3.7
|
94
|
+
signing_key:
|
95
|
+
specification_version: 3
|
96
|
+
summary: basic selector namespace implementation
|
97
|
+
test_files: []
|
98
|
+
|