tweak 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+
@@ -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
@@ -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
+
@@ -0,0 +1,3 @@
1
+ module Tweak
2
+ VERSION = "0.1.1"
3
+ end
@@ -0,0 +1,3 @@
1
+ module Tweak
2
+ VERSION = "0.1.1"
3
+ end
@@ -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
+