dsl_accessor 0.1.0 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 [maiha@wota.jp]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,175 @@
1
+ DslAccessor
2
+ ===========
3
+
4
+ This plugin gives hybrid accessor class methods to classes by DSL like definition,
5
+ here hybrid means getter and setter. The accessor method acts as getter method
6
+ if no argments given, otherwise it acts as setter one with the arguments.
7
+
8
+
9
+ Usage
10
+ =====
11
+
12
+ class Foo
13
+ dsl_accessor "<METHOD NAME>"
14
+ end
15
+
16
+
17
+ Example
18
+ =======
19
+
20
+ class Foo
21
+ dsl_accessor :greeting
22
+ end
23
+
24
+ This code gives 'greeting' class method to Foo class.
25
+
26
+ Foo.greeting # means getter, and the default value is nil.
27
+ => nil
28
+
29
+ Foo.greeting "I'm Foo." # means setter with given arguments
30
+ => "I'm Foo."
31
+
32
+ Foo.greeting
33
+ => "I'm Foo."
34
+
35
+
36
+ Difference
37
+ ==========
38
+
39
+ I'm convinced that you want to propose me to use 'cattr_accessor'.
40
+ Although the difference is just whether we needs '=' operation or not,
41
+ it makes a large different on class definition especially subclass.
42
+
43
+ class Foo
44
+ cattr_accessor :greeting
45
+ end
46
+
47
+ class Bar < Foo
48
+ self.greeting = "I'm bar."
49
+ end
50
+
51
+ We must write redundant code represented by "self." to distinguish
52
+ a local variable and a class method when we use 'cattr_accessor'.
53
+ This is ugly and boring work.
54
+
55
+ class Foo
56
+ dsl_accessor :greeting
57
+ end
58
+
59
+ class Bar < Foo
60
+ greeting "I'm bar."
61
+ end
62
+
63
+ There are no longer redundant prefix code like "self." and "set_".
64
+ Don't you like this dsl-like coding with simple declaration?
65
+
66
+
67
+ Special Options
68
+ ===============
69
+
70
+ 'dsl_accessor' method can take two options, those are :writer and :default.
71
+ "writer" option means callback method used when setter is executed.
72
+ "default" option means default static value or proc that creates some value.
73
+
74
+ class PseudoAR
75
+ dsl_accessor :primary_key, :default=>"id", :writer=>proc{|value| value.to_s}
76
+ dsl_accessor :table_name, :default=>proc{|klass| klass.name.demodulize.underscore.pluralize}
77
+ end
78
+
79
+ class Item < PseudoAR
80
+ end
81
+
82
+ class User < PseudoAR
83
+ primary_key :user_code
84
+ table_name :user_table
85
+ end
86
+
87
+ Item.primary_key # => "id"
88
+ Item.table_name # => "items"
89
+ User.primary_key # => "user_code"
90
+ User.table_name # => :user_table
91
+
92
+ Note that "User.primary_key" return a String by setter proc.
93
+
94
+
95
+ Instance Method
96
+ ===============
97
+
98
+ "instance" option automatically defines its instance method
99
+
100
+ class Search
101
+ dsl_accessor :url, :instance=>true, :default=>"http://localhost/"
102
+ end
103
+
104
+ Search.url # => "http://localhost/"
105
+ Search.new.url # => "http://localhost/"
106
+
107
+ and it uses @options instance variable with special value :options
108
+
109
+ class Window
110
+ dsl_accessor :width, :default=>640, :instance=>:options
111
+ def initialize(options = {})
112
+ @options = options
113
+ end
114
+ end
115
+
116
+ Window.width # => 640
117
+ Window.new.width # => 640
118
+
119
+ window = Window.new(:width=>320)
120
+ window.width # =>320
121
+
122
+
123
+ Install
124
+ =======
125
+
126
+ git://github.com/maiha/dsl_accessor.git
127
+
128
+
129
+ Auto declared mode
130
+ ==================
131
+
132
+ Calling dsl_accessor without args enters auto declared mode.
133
+ In this mode, a method missing means instance method creation.
134
+ This affects only methods with a block and no other args.
135
+
136
+ class Foo
137
+ dsl_accessor # auto declared mode
138
+ foo{1} # define :foo
139
+ bar(a) # NoMethodError
140
+ baz(a){2} # NoMethodError
141
+ end
142
+
143
+ Foo.new.foo # => 1
144
+
145
+ This is useful when you have many methods those are one lined methods.
146
+
147
+ [without auto delared mode]
148
+ class Foo
149
+ def last
150
+ num_pages
151
+ end
152
+
153
+ def first?
154
+ page == 1
155
+ end
156
+
157
+ def offset
158
+ model.proxy_options[:offset]
159
+ end
160
+ end
161
+
162
+ [with auto delared mode]
163
+ class Foo
164
+ dsl_accessor
165
+ last {num_pages}
166
+ first? {page == 1}
167
+ offset {model.proxy_options[:offset]}
168
+ end
169
+
170
+
171
+
172
+ Author
173
+ ======
174
+ Maiha <maiha@wota.jp>
175
+
data/Rakefile CHANGED
@@ -1,49 +1,74 @@
1
- require 'rubygems'
2
1
  require 'rake'
3
- require 'rake/clean'
4
2
  require 'rake/testtask'
5
- require 'rake/packagetask'
6
- require 'rake/gempackagetask'
7
3
  require 'rake/rdoctask'
8
- require 'rake/contrib/rubyforgepublisher'
9
- require 'fileutils'
10
- require 'hoe'
11
- include FileUtils
12
- require File.join(File.dirname(__FILE__), 'lib', 'dsl_accessor', 'version')
13
-
14
- AUTHOR = ['Maiha', 'Alex Wayne'] # can also be an array of Authors
15
- EMAIL = "anna@wota.jp"
16
- DESCRIPTION = "This gem gives hybrid accessor class methods to classes by DSL like definition."
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the dsl_accessor plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the dsl_accessor plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'DslAccessor'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
23
+
24
+
25
+ ######################################################################
26
+ ### for gem
27
+
28
+ require 'rubygems'
29
+ require 'rake/gempackagetask'
30
+
17
31
  GEM_NAME = "dsl_accessor"
18
- RUBYFORGE_PROJECT = "dsl-accessor"
19
- HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
20
- RELEASE_TYPES = %w( gem )
21
-
22
-
23
- NAME = "dsl_accessor"
24
- REV = nil # UNCOMMENT IF REQUIRED: File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
25
- VERS = ENV['VERSION'] || (DslAccessor::VERSION::STRING + (REV ? ".#{REV}" : ""))
26
- CLEAN.include ['**/.*.sw?', '*.gem', '.config']
27
- RDOC_OPTS = ['--quiet', '--title', "dsl_accessor documentation",
28
- "--opname", "index.html",
29
- "--line-numbers",
30
- "--main", "README",
31
- "--inline-source"]
32
-
33
- # Generate all the Rake tasks
34
- # Run 'rake -T' to see list of generated tasks (from gem root directory)
35
- hoe = Hoe.new(GEM_NAME, VERS) do |p|
36
- p.author = AUTHOR
37
- p.description = DESCRIPTION
38
- p.email = EMAIL
39
- p.summary = DESCRIPTION
40
- p.url = HOMEPATH
41
- p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
42
- p.test_globs = ["test/**/*_test.rb"]
43
- p.clean_globs = CLEAN #An array of file patterns to delete on clean.
44
-
45
- # == Optional
46
- #p.changes - A description of the release's latest changes.
47
- p.extra_deps = %w( activesupport )
48
- #p.spec_extras - A hash of extra values to set in the gemspec.
49
- end
32
+ AUTHOR = "maiha"
33
+ EMAIL = "maiha@wota.jp"
34
+ HOMEPAGE = "http://github.com/maiha/dsl_accessor"
35
+ SUMMARY = "This plugin gives hybrid accessor class methods to classes by DSL like definition"
36
+ GEM_VERSION = "0.3.3"
37
+
38
+ spec = Gem::Specification.new do |s|
39
+ # s.rubyforge_project = 'merb'
40
+ s.name = GEM_NAME
41
+ s.version = GEM_VERSION
42
+ s.platform = Gem::Platform::RUBY
43
+ s.has_rdoc = true
44
+ s.extra_rdoc_files = ["README", "LICENSE"]
45
+ s.summary = SUMMARY
46
+ s.description = s.summary
47
+ s.author = AUTHOR
48
+ s.email = EMAIL
49
+ s.homepage = HOMEPAGE
50
+ s.require_path = 'lib'
51
+ s.files = %w(LICENSE README Rakefile) + Dir.glob("{core_ext,lib,spec,tasks,test}/**/*")
52
+ end
53
+
54
+ Rake::GemPackageTask.new(spec) do |pkg|
55
+ pkg.gem_spec = spec
56
+ end
57
+
58
+ desc "Install the gem"
59
+ task :install do
60
+ Merb::RakeHelper.install(GEM_NAME, :version => GEM_VERSION)
61
+ end
62
+
63
+ desc "Uninstall the gem"
64
+ task :uninstall do
65
+ Merb::RakeHelper.uninstall(GEM_NAME, :version => GEM_VERSION)
66
+ end
67
+
68
+ desc "Create a gemspec file"
69
+ task :gemspec do
70
+ File.open("#{GEM_NAME}.gemspec", "w") do |file|
71
+ file.puts spec.to_ruby
72
+ end
73
+ end
74
+
@@ -0,0 +1,93 @@
1
+ module DslAccessor
2
+ def dsl_accessor(*args)
3
+ options = args.last.is_a?(Hash) ? args.pop : {}
4
+
5
+ # mark auto_declared
6
+ name = args.shift or
7
+ return @dsl_accessor_auto_declared = true
8
+
9
+ options[:default] = args.shift unless args.empty?
10
+
11
+ case options[:instance]
12
+ when nil
13
+ # nop
14
+ when :options
15
+ module_eval(<<-EOS, "(__DSL_ACCESSOR__)", 1)
16
+ def #{ name }
17
+ unless @options
18
+ raise TypeError, "DSL Error: missing @options for %s##{name}" % self.class.name
19
+ end
20
+ @options[:#{ name }] || self.class.#{ name }
21
+ end
22
+ EOS
23
+ when true
24
+ delegate name, :to=>"self.class"
25
+ else
26
+ raise TypeError, "DSL Error: :instance should be true or :instance, but got `%s' class" % options[:instance].class
27
+ end
28
+
29
+ raise TypeError, "DSL Error: options should be a hash. but got `#{options.class}'" unless options.is_a?(Hash)
30
+ writer = options[:writer] || options[:setter]
31
+ writer =
32
+ case writer
33
+ when NilClass then Proc.new{|value| value}
34
+ when Symbol then Proc.new{|value| __send__(writer, value)}
35
+ when Proc then writer
36
+ else raise TypeError, "DSL Error: writer should be a symbol or proc. but got `#{options[:writer].class}'"
37
+ end
38
+ write_inheritable_attribute(:"#{name}_writer", writer)
39
+
40
+ default =
41
+ case options[:default]
42
+ when NilClass then nil
43
+ when [] then Proc.new{[]}
44
+ when {} then Proc.new{{}}
45
+ when Symbol then Proc.new{__send__(options[:default])}
46
+ when Proc then options[:default]
47
+ else Proc.new{options[:default]}
48
+ end
49
+ write_inheritable_attribute(:"#{name}_default", default)
50
+
51
+ (class << self; self end).class_eval do
52
+ define_method("#{name}=") do |value|
53
+ writer = read_inheritable_attribute(:"#{name}_writer")
54
+ value = writer.call(value) if writer
55
+ write_inheritable_attribute(:"#{name}", value)
56
+ end
57
+
58
+ define_method(name) do |*values|
59
+ if values.empty?
60
+ # getter method
61
+ key = :"#{name}"
62
+ if !inheritable_attributes.has_key?(key)
63
+ default = read_inheritable_attribute(:"#{name}_default")
64
+ value = default ? default.call(self) : nil
65
+ __send__("#{name}=", value)
66
+ end
67
+ read_inheritable_attribute(key)
68
+ else
69
+ # setter method
70
+ __send__("#{name}=", *values)
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ private
77
+ def dsl_accessor_auto_declared?
78
+ !!@dsl_accessor_auto_declared
79
+ end
80
+
81
+ def method_missing(*args, &block)
82
+ if dsl_accessor_auto_declared? and args.size == 1 and block
83
+ define_method(*args, &block)
84
+ else
85
+ super
86
+ end
87
+ end
88
+
89
+ end
90
+
91
+ class Class
92
+ include DslAccessor
93
+ end
@@ -0,0 +1,140 @@
1
+ # Retain for backward compatibility. Methods are now included in Class.
2
+ module ClassInheritableAttributes # :nodoc:
3
+ end
4
+
5
+ # Allows attributes to be shared within an inheritance hierarchy, but where each descendant gets a copy of
6
+ # their parents' attributes, instead of just a pointer to the same. This means that the child can add elements
7
+ # to, for example, an array without those additions being shared with either their parent, siblings, or
8
+ # children, which is unlike the regular class-level attributes that are shared across the entire hierarchy.
9
+ class Class # :nodoc:
10
+ def class_inheritable_reader(*syms)
11
+ syms.each do |sym|
12
+ next if sym.is_a?(Hash)
13
+ class_eval <<-EOS
14
+ def self.#{sym}
15
+ read_inheritable_attribute(:#{sym})
16
+ end
17
+
18
+ def #{sym}
19
+ self.class.#{sym}
20
+ end
21
+ EOS
22
+ end
23
+ end
24
+
25
+ def class_inheritable_writer(*syms)
26
+ options = syms.last.is_a?(::Hash) ? syms.pop : {}
27
+ syms.each do |sym|
28
+ class_eval <<-EOS
29
+ def self.#{sym}=(obj)
30
+ write_inheritable_attribute(:#{sym}, obj)
31
+ end
32
+
33
+ #{"
34
+ def #{sym}=(obj)
35
+ self.class.#{sym} = obj
36
+ end
37
+ " unless options[:instance_writer] == false }
38
+ EOS
39
+ end
40
+ end
41
+
42
+ def class_inheritable_array_writer(*syms)
43
+ options = syms.last.is_a?(::Hash) ? syms.pop : {}
44
+ syms.each do |sym|
45
+ class_eval <<-EOS
46
+ def self.#{sym}=(obj)
47
+ write_inheritable_array(:#{sym}, obj)
48
+ end
49
+
50
+ #{"
51
+ def #{sym}=(obj)
52
+ self.class.#{sym} = obj
53
+ end
54
+ " unless options[:instance_writer] == false }
55
+ EOS
56
+ end
57
+ end
58
+
59
+ def class_inheritable_hash_writer(*syms)
60
+ options = syms.last.is_a?(::Hash) ? syms.pop : {}
61
+ syms.each do |sym|
62
+ class_eval <<-EOS
63
+ def self.#{sym}=(obj)
64
+ write_inheritable_hash(:#{sym}, obj)
65
+ end
66
+
67
+ #{"
68
+ def #{sym}=(obj)
69
+ self.class.#{sym} = obj
70
+ end
71
+ " unless options[:instance_writer] == false }
72
+ EOS
73
+ end
74
+ end
75
+
76
+ def class_inheritable_accessor(*syms)
77
+ class_inheritable_reader(*syms)
78
+ class_inheritable_writer(*syms)
79
+ end
80
+
81
+ def class_inheritable_array(*syms)
82
+ class_inheritable_reader(*syms)
83
+ class_inheritable_array_writer(*syms)
84
+ end
85
+
86
+ def class_inheritable_hash(*syms)
87
+ class_inheritable_reader(*syms)
88
+ class_inheritable_hash_writer(*syms)
89
+ end
90
+
91
+ def inheritable_attributes
92
+ @inheritable_attributes ||= EMPTY_INHERITABLE_ATTRIBUTES
93
+ end
94
+
95
+ def write_inheritable_attribute(key, value)
96
+ if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES)
97
+ @inheritable_attributes = {}
98
+ end
99
+ inheritable_attributes[key] = value
100
+ end
101
+
102
+ def write_inheritable_array(key, elements)
103
+ write_inheritable_attribute(key, []) if read_inheritable_attribute(key).nil?
104
+ write_inheritable_attribute(key, read_inheritable_attribute(key) + elements)
105
+ end
106
+
107
+ def write_inheritable_hash(key, hash)
108
+ write_inheritable_attribute(key, {}) if read_inheritable_attribute(key).nil?
109
+ write_inheritable_attribute(key, read_inheritable_attribute(key).merge(hash))
110
+ end
111
+
112
+ def read_inheritable_attribute(key)
113
+ inheritable_attributes[key]
114
+ end
115
+
116
+ def reset_inheritable_attributes
117
+ @inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
118
+ end
119
+
120
+ private
121
+ # Prevent this constant from being created multiple times
122
+ EMPTY_INHERITABLE_ATTRIBUTES = {}.freeze unless const_defined?(:EMPTY_INHERITABLE_ATTRIBUTES)
123
+
124
+ def inherited_with_inheritable_attributes(child)
125
+ inherited_without_inheritable_attributes(child) if respond_to?(:inherited_without_inheritable_attributes)
126
+
127
+ if inheritable_attributes.equal?(EMPTY_INHERITABLE_ATTRIBUTES)
128
+ new_inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES
129
+ else
130
+ new_inheritable_attributes = inheritable_attributes.inject({}) do |memo, (key, value)|
131
+ memo.update(key => value.duplicable? ? value.dup : value)
132
+ end
133
+ end
134
+
135
+ child.instance_variable_set('@inheritable_attributes', new_inheritable_attributes)
136
+ end
137
+
138
+ alias inherited_without_inheritable_attributes inherited
139
+ alias inherited inherited_with_inheritable_attributes
140
+ end
@@ -0,0 +1,43 @@
1
+ class Object
2
+ # Can you safely .dup this object?
3
+ # False for nil, false, true, symbols, and numbers; true otherwise.
4
+ def duplicable?
5
+ true
6
+ end
7
+ end
8
+
9
+ class NilClass #:nodoc:
10
+ def duplicable?
11
+ false
12
+ end
13
+ end
14
+
15
+ class FalseClass #:nodoc:
16
+ def duplicable?
17
+ false
18
+ end
19
+ end
20
+
21
+ class TrueClass #:nodoc:
22
+ def duplicable?
23
+ false
24
+ end
25
+ end
26
+
27
+ class Symbol #:nodoc:
28
+ def duplicable?
29
+ false
30
+ end
31
+ end
32
+
33
+ class Numeric #:nodoc:
34
+ def duplicable?
35
+ false
36
+ end
37
+ end
38
+
39
+ class Class #:nodoc:
40
+ def duplicable?
41
+ false
42
+ end
43
+ end
@@ -0,0 +1,95 @@
1
+ class Module
2
+ # Provides a delegate class method to easily expose contained objects' methods
3
+ # as your own. Pass one or more methods (specified as symbols or strings)
4
+ # and the name of the target object as the final <tt>:to</tt> option (also a symbol
5
+ # or string). At least one method and the <tt>:to</tt> option are required.
6
+ #
7
+ # Delegation is particularly useful with Active Record associations:
8
+ #
9
+ # class Greeter < ActiveRecord::Base
10
+ # def hello() "hello" end
11
+ # def goodbye() "goodbye" end
12
+ # end
13
+ #
14
+ # class Foo < ActiveRecord::Base
15
+ # belongs_to :greeter
16
+ # delegate :hello, :to => :greeter
17
+ # end
18
+ #
19
+ # Foo.new.hello # => "hello"
20
+ # Foo.new.goodbye # => NoMethodError: undefined method `goodbye' for #<Foo:0x1af30c>
21
+ #
22
+ # Multiple delegates to the same target are allowed:
23
+ #
24
+ # class Foo < ActiveRecord::Base
25
+ # belongs_to :greeter
26
+ # delegate :hello, :goodbye, :to => :greeter
27
+ # end
28
+ #
29
+ # Foo.new.goodbye # => "goodbye"
30
+ #
31
+ # Methods can be delegated to instance variables, class variables, or constants
32
+ # by providing them as a symbols:
33
+ #
34
+ # class Foo
35
+ # CONSTANT_ARRAY = [0,1,2,3]
36
+ # @@class_array = [4,5,6,7]
37
+ #
38
+ # def initialize
39
+ # @instance_array = [8,9,10,11]
40
+ # end
41
+ # delegate :sum, :to => :CONSTANT_ARRAY
42
+ # delegate :min, :to => :@@class_array
43
+ # delegate :max, :to => :@instance_array
44
+ # end
45
+ #
46
+ # Foo.new.sum # => 6
47
+ # Foo.new.min # => 4
48
+ # Foo.new.max # => 11
49
+ #
50
+ # Delegates can optionally be prefixed using the <tt>:prefix</tt> option. If the value
51
+ # is <tt>true</tt>, the delegate methods are prefixed with the name of the object being
52
+ # delegated to.
53
+ #
54
+ # Person = Struct.new(:name, :address)
55
+ #
56
+ # class Invoice < Struct.new(:client)
57
+ # delegate :name, :address, :to => :client, :prefix => true
58
+ # end
59
+ #
60
+ # john_doe = Person.new("John Doe", "Vimmersvej 13")
61
+ # invoice = Invoice.new(john_doe)
62
+ # invoice.client_name # => "John Doe"
63
+ # invoice.client_address # => "Vimmersvej 13"
64
+ #
65
+ # It is also possible to supply a custom prefix.
66
+ #
67
+ # class Invoice < Struct.new(:client)
68
+ # delegate :name, :address, :to => :client, :prefix => :customer
69
+ # end
70
+ #
71
+ # invoice = Invoice.new(john_doe)
72
+ # invoice.customer_name # => "John Doe"
73
+ # invoice.customer_address # => "Vimmersvej 13"
74
+ #
75
+ def delegate(*methods)
76
+ options = methods.pop
77
+ unless options.is_a?(Hash) && to = options[:to]
78
+ raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, :to => :greeter)."
79
+ end
80
+
81
+ if options[:prefix] == true && options[:to].to_s =~ /^[^a-z_]/
82
+ raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method."
83
+ end
84
+
85
+ prefix = options[:prefix] && "#{options[:prefix] == true ? to : options[:prefix]}_"
86
+
87
+ methods.each do |method|
88
+ module_eval(<<-EOS, "(__DELEGATION__)", 1)
89
+ def #{prefix}#{method}(*args, &block)
90
+ #{to}.__send__(#{method.inspect}, *args, &block)
91
+ end
92
+ EOS
93
+ end
94
+ end
95
+ end