selective_binding 1.0.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/.autotest ADDED
@@ -0,0 +1,23 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'autotest/restart'
4
+
5
+ # Autotest.add_hook :initialize do |at|
6
+ # at.extra_files << "../some/external/dependency.rb"
7
+ #
8
+ # at.libs << ":../some/external"
9
+ #
10
+ # at.add_exception 'vendor'
11
+ #
12
+ # at.add_mapping(/dependency.rb/) do |f, _|
13
+ # at.files_matching(/test_.*rb$/)
14
+ # end
15
+ #
16
+ # %w(TestA TestB).each do |klass|
17
+ # at.extra_class_map[klass] = "test/test_misc.rb"
18
+ # end
19
+ # end
20
+
21
+ # Autotest.add_hook :run_command do |at|
22
+ # system "rake build"
23
+ # end
data/History.txt ADDED
@@ -0,0 +1,6 @@
1
+ === 1.0.0 / 2010-10-18
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
data/Manifest.txt ADDED
@@ -0,0 +1,8 @@
1
+ .autotest
2
+ History.txt
3
+ Manifest.txt
4
+ README.rdoc
5
+ Rakefile
6
+ bin/selective_binding
7
+ lib/selective_binding.rb
8
+ test/test_selective_binding.rb
data/README.rdoc ADDED
@@ -0,0 +1,67 @@
1
+ = selective_binding
2
+
3
+ * http://github.com/yaksnrainbows/selective_binding
4
+
5
+ == DESCRIPTION:
6
+
7
+ Create Bindings with selective mappings to an object's methods and attributes.
8
+
9
+ == SYNOPSIS:
10
+
11
+ Creates a selective binding instance for self and returns
12
+ the newly created binding:
13
+
14
+ selective_binding :attr1, :method1
15
+ #=> <#Binding>
16
+
17
+ Passing a hash as the last argument allows for setting custom attributes.
18
+ These override any previously defined forwarded methods:
19
+
20
+ selective_binding :attr1 => "custom value"
21
+ #=> <#Binding>
22
+
23
+ Passing a block is also supported to set the default value for undefined
24
+ attributes or methods:
25
+
26
+ selective_binding do
27
+ "default value"
28
+ end
29
+ #=> <#Binding>
30
+
31
+ == INSTALL:
32
+
33
+ * sudo gem install selective_binding
34
+
35
+ == DEVELOPERS:
36
+
37
+ After checking out the source, run:
38
+
39
+ $ rake newb
40
+
41
+ This task will install any missing dependencies, run the tests/specs,
42
+ and generate the RDoc.
43
+
44
+ == LICENSE:
45
+
46
+ (The MIT License)
47
+
48
+ Copyright (c) 2010 Jeremie Castagna
49
+
50
+ Permission is hereby granted, free of charge, to any person obtaining
51
+ a copy of this software and associated documentation files (the
52
+ 'Software'), to deal in the Software without restriction, including
53
+ without limitation the rights to use, copy, modify, merge, publish,
54
+ distribute, sublicense, and/or sell copies of the Software, and to
55
+ permit persons to whom the Software is furnished to do so, subject to
56
+ the following conditions:
57
+
58
+ The above copyright notice and this permission notice shall be
59
+ included in all copies or substantial portions of the Software.
60
+
61
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
62
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
63
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
64
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
65
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
66
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
67
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+
6
+ Hoe.spec 'selective_binding' do
7
+ developer 'Jeremie Castagna', 'yaksnrainbows@gmail.com'
8
+ self.summary =
9
+ "Bindings with selective mappings to object methods and attributes."
10
+ end
11
+
12
+ # vim: syntax=ruby
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ abort "you need to write me"
@@ -0,0 +1,150 @@
1
+ ##
2
+ # Create a selective binding. Useful for controlling ERB builds.
3
+ # The following will allow MyObj instances to provide a binding that will only
4
+ # expose MyObj#my_attr and MyObj#get_some_value:
5
+ #
6
+ # require 'selective_binding'
7
+ #
8
+ # class MyObj
9
+ # attr_accessor :my_attr
10
+ #
11
+ # def modify_something
12
+ # # Don't want this exposed in binding!
13
+ # end
14
+ #
15
+ # def get_some_value
16
+ # # Want this exposed in binding.
17
+ # "some value"
18
+ # end
19
+ #
20
+ # def get_binding
21
+ # selective_binding :my_attr, :get_some_value
22
+ # end
23
+ # end
24
+ #
25
+ # my_obj = MyObj.new
26
+ #
27
+ # eval "get_some_value", my_obj.get_binding
28
+ # #=> "some value"
29
+ #
30
+ # eval "modify_something", my_obj.get_binding
31
+ # #=> NameError: undefined local variable or method `modify_something'
32
+ #
33
+ # Additionally, a block can be passed to selective bindings to fill the role of
34
+ # a default value, or method_missing.
35
+
36
+ class SelectiveBinding
37
+
38
+ # Gem Version
39
+ VERSION = '1.0.0'
40
+
41
+ ##
42
+ # Creates a new selective binding with the target object to
43
+ # create a binding to.
44
+
45
+ def initialize target
46
+ @target = target
47
+ end
48
+
49
+
50
+ ##
51
+ # Set the binding instance variable and accessor method.
52
+ # selective_binding.set :server_name, "blah.com"
53
+
54
+ def set key, value=nil, &block
55
+ value ||= block if block_given?
56
+
57
+ instance_variable_set("@#{key}", value)
58
+
59
+ eval_str = <<-STR
60
+ undef #{key} if defined?(#{key})
61
+ def #{key}(*args, &block)
62
+ if Proc === @#{key}
63
+ @#{key}.call(*args, &block)
64
+ else
65
+ @#{key}
66
+ end
67
+ end
68
+ STR
69
+
70
+ instance_eval eval_str, __FILE__, __LINE__ + 1
71
+ end
72
+
73
+
74
+ ##
75
+ # Takes a hash and assign each hash key/value as an attribute:
76
+ # selective_binding.import_hash :attr1 => "value1",
77
+ # :attr2 => "value2"
78
+
79
+ def import_hash hash
80
+ hash.each{|k, v| self.set(k, v)}
81
+ end
82
+
83
+
84
+ ##
85
+ # Forward a method to the server instance.
86
+ # binder.forward :method1, :method2, ...
87
+
88
+ def forward *method_names
89
+ method_names.each do |method_name|
90
+ instance_eval <<-STR, __FILE__, __LINE__ + 1
91
+ undef #{method_name} if defined?(#{method_name})
92
+ def #{method_name}(*args, &block)
93
+ @target.send(#{method_name.to_sym.inspect}, *args, &block)
94
+ end
95
+ STR
96
+ end
97
+ end
98
+
99
+
100
+ ##
101
+ # Sets the default value for undefined attributes or methods.
102
+
103
+ def set_default value=nil, &block
104
+ set :method_missing, value, &block if value || block_given?
105
+ end
106
+
107
+
108
+ ##
109
+ # Retrieve the object's binding.
110
+
111
+ def get_binding
112
+ binding
113
+ end
114
+ end
115
+
116
+
117
+ class Object
118
+
119
+ ##
120
+ # Creates a selective binding instance for self and returns
121
+ # the newly created binding:
122
+ #
123
+ # selective_binding :attr1, :method1
124
+ # #=> <#Binding>
125
+ #
126
+ # Passing a hash as the last argument allows for setting custom attributes.
127
+ # These override any previously defined forwarded methods:
128
+ #
129
+ # selective_binding :attr1 => "custom value"
130
+ # #=> <#Binding>
131
+ #
132
+ # Passing a block is also supported to set the default value for undefined
133
+ # attributes or methods:
134
+ #
135
+ # selective_binding do
136
+ # "default value"
137
+ # end
138
+ # #=> <#Binding>
139
+
140
+ def selective_binding *methods, &block
141
+ hash_attrib = methods.delete_at(-1) if Hash === methods.last
142
+
143
+ binder = SelectiveBinding.new self
144
+
145
+ binder.forward(*methods) unless methods.empty?
146
+ binder.import_hash hash_attrib if hash_attrib
147
+ binder.set_default(&block) if block_given?
148
+ binder.get_binding
149
+ end
150
+ end
@@ -0,0 +1,142 @@
1
+ require "test/unit"
2
+ require "selective_binding"
3
+
4
+ class TestSelectiveBinding < Test::Unit::TestCase
5
+
6
+ class MockObj
7
+ attr_accessor :obj_attr1, :obj_attr2, :obj_attr3
8
+ end
9
+
10
+
11
+ def setup
12
+ @obj = MockObj.new
13
+ @obj.obj_attr1 = "value1"
14
+ @obj.obj_attr2 = "value2"
15
+ @obj.obj_attr3 = "value3"
16
+ @binder = SelectiveBinding.new @obj
17
+ end
18
+
19
+
20
+ def test_set
21
+ @binder.set :other_attr, "my_value"
22
+ assert_binding_value @binder, :other_attr => "my_value"
23
+ end
24
+
25
+
26
+ def test_set_block
27
+ @binder.set :other_attr do
28
+ "something else"
29
+ end
30
+
31
+ assert_binding_value @binder, :other_attr => "something else"
32
+ end
33
+
34
+
35
+ def test_set_value_block
36
+ @binder.set :other_attr, "thing" do
37
+ "block value"
38
+ end
39
+
40
+ assert_binding_value @binder, :other_attr => "thing"
41
+ end
42
+
43
+
44
+ def test_import_hash
45
+ @binder.import_hash :attr1 => "val1",
46
+ :attr2 => "val2"
47
+
48
+ assert_binding_value @binder, :attr1 => "val1",
49
+ :attr2 => "val2"
50
+ end
51
+
52
+
53
+ def test_forward
54
+ @binder.forward :obj_attr1, :obj_attr2
55
+
56
+ assert_binding_value @binder, :obj_attr1 => @obj.obj_attr1,
57
+ :obj_attr2 => @obj.obj_attr2
58
+
59
+ assert_not_binding_value @binder, :obj_attr3
60
+
61
+ @binder.forward :obj_attr3
62
+ assert_binding_value @binder, :obj_attr3 => @obj.obj_attr3
63
+ end
64
+
65
+
66
+ def test_set_default
67
+ @binder.forward :obj_attr1, :obj_attr2
68
+ @binder.set_default "DEFAULT VALUE!"
69
+
70
+ assert_binding_value @binder, :undefined => "DEFAULT VALUE!",
71
+ :obj_attr1 => @obj.obj_attr1,
72
+ :obj_attr2 => @obj.obj_attr2
73
+ end
74
+
75
+
76
+ def test_set_default_block
77
+ @binder.forward :obj_attr1, :obj_attr2
78
+
79
+ @binder.set_default do
80
+ "NEW DEFAULT VALUE!"
81
+ end
82
+
83
+ assert_binding_value @binder, :undefined => "NEW DEFAULT VALUE!",
84
+ :obj_attr1 => @obj.obj_attr1,
85
+ :obj_attr2 => @obj.obj_attr2
86
+ end
87
+
88
+
89
+ def test_obj_selective_binding
90
+ b = selective_binding :forwarded_method
91
+ assert_binding_value b, :forwarded_method => forwarded_method
92
+ assert_not_binding_value b, :not_forwarded
93
+ end
94
+
95
+
96
+ def test_obj_selective_binding_hash
97
+ b = selective_binding :forwarded_method, :forwarded_method => "custom attr"
98
+
99
+ assert_binding_value b, :forwarded_method => "custom attr"
100
+
101
+ assert_not_binding_value b, :not_forwarded
102
+ end
103
+
104
+
105
+ def test_obj_selective_binding_block
106
+ b = selective_binding do
107
+ "DEFAULT VALUE!"
108
+ end
109
+
110
+ assert_binding_value b, :forwarded_method => "DEFAULT VALUE!"
111
+ end
112
+
113
+
114
+ private
115
+
116
+ def not_forwarded
117
+ raise "This method should not be accessible from the binding"
118
+ end
119
+
120
+
121
+ def forwarded_method
122
+ "FORWARDED METHOD"
123
+ end
124
+
125
+
126
+ def assert_binding_value binding, hash
127
+ binding = binding.get_binding if SelectiveBinding === binding
128
+ hash.each do |key, value|
129
+ assert_equal eval("#{key}", binding), value
130
+ end
131
+ end
132
+
133
+
134
+ def assert_not_binding_value binding, *keys
135
+ binding = binding.get_binding if SelectiveBinding === binding
136
+ keys.each do |key|
137
+ assert_raises NameError do
138
+ eval("#{key}", binding)
139
+ end
140
+ end
141
+ end
142
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: selective_binding
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Jeremie Castagna
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-10-18 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rubyforge
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 7
30
+ segments:
31
+ - 2
32
+ - 0
33
+ - 4
34
+ version: 2.0.4
35
+ type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: hoe
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 19
46
+ segments:
47
+ - 2
48
+ - 6
49
+ - 2
50
+ version: 2.6.2
51
+ type: :development
52
+ version_requirements: *id002
53
+ description: ""
54
+ email:
55
+ - yaksnrainbows@gmail.com
56
+ executables:
57
+ - selective_binding
58
+ extensions: []
59
+
60
+ extra_rdoc_files:
61
+ - History.txt
62
+ - Manifest.txt
63
+ files:
64
+ - .autotest
65
+ - History.txt
66
+ - Manifest.txt
67
+ - README.rdoc
68
+ - Rakefile
69
+ - bin/selective_binding
70
+ - lib/selective_binding.rb
71
+ - test/test_selective_binding.rb
72
+ has_rdoc: true
73
+ homepage:
74
+ licenses: []
75
+
76
+ post_install_message:
77
+ rdoc_options:
78
+ - --main
79
+ - README.txt
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ hash: 3
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ hash: 3
97
+ segments:
98
+ - 0
99
+ version: "0"
100
+ requirements: []
101
+
102
+ rubyforge_project: selective_binding
103
+ rubygems_version: 1.3.7
104
+ signing_key:
105
+ specification_version: 3
106
+ summary: Bindings with selective mappings to object methods and attributes.
107
+ test_files:
108
+ - test/test_selective_binding.rb