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.
@@ -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
+