genki-dsl_accessor 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 [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,209 @@
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
+ Install
10
+ =======
11
+
12
+ gem install dsl_accessor
13
+
14
+
15
+ Usage
16
+ =====
17
+
18
+ class Foo
19
+ dsl_accessor "<METHOD NAME>" (, default_value)
20
+ end
21
+
22
+
23
+ Example
24
+ =======
25
+
26
+ class Foo
27
+ dsl_accessor :greeting
28
+ end
29
+
30
+ This code gives 'greeting' class method to Foo class.
31
+
32
+ Foo.greeting # means getter, and the default value is nil.
33
+ => nil
34
+
35
+ Foo.greeting "I'm Foo." # means setter with given arguments
36
+ => "I'm Foo."
37
+
38
+ Foo.greeting
39
+ => "I'm Foo."
40
+
41
+
42
+ Difference
43
+ ==========
44
+
45
+ I am convinced that you want to propose me to use 'cattr_accessor'.
46
+ Although the difference is just whether we needs '=' operation or not,
47
+ it makes a large different on class definition especially subclass.
48
+
49
+ class Foo
50
+ cattr_accessor :greeting
51
+ end
52
+
53
+ class Bar < Foo
54
+ self.greeting = "I am bar."
55
+ end
56
+
57
+ We must write redundant code represented by "self." to distinguish
58
+ a local variable and a class method when we use 'cattr_accessor'.
59
+ This is ugly and boring work.
60
+
61
+ class Foo
62
+ dsl_accessor :greeting
63
+ end
64
+
65
+ class Bar < Foo
66
+ greeting "I am bar."
67
+ end
68
+
69
+ There are no longer redundant prefix code like "self." and "set_".
70
+ How about this dsl-like coding with simple declaration?
71
+
72
+
73
+ Special Options
74
+ ===============
75
+
76
+ 'dsl_accessor' method can take two options, those are :writer and :default.
77
+ "writer" option means callback method used when setter is executed.
78
+ "default" option means default static value or proc that creates some value.
79
+
80
+ class PseudoAR
81
+ dsl_accessor :primary_key, :default=>"id", :writer=>proc{|value| value.to_s}
82
+ dsl_accessor :table_name, :default=>proc{|klass| klass.name.demodulize.underscore.pluralize}
83
+ end
84
+
85
+ class Item < PseudoAR
86
+ end
87
+
88
+ class User < PseudoAR
89
+ primary_key :user_code
90
+ table_name :user_table
91
+ end
92
+
93
+ Item.primary_key # => "id"
94
+ Item.table_name # => "items"
95
+ User.primary_key # => "user_code"
96
+ User.table_name # => :user_table
97
+
98
+ Note that "User.primary_key" return a String by setter proc.
99
+
100
+
101
+ Instance Method
102
+ ===============
103
+
104
+ "instance" option automatically defines its instance method
105
+
106
+ class Search
107
+ dsl_accessor :url, :instance=>true, :default=>"http://localhost/"
108
+ end
109
+
110
+ Search.url # => "http://localhost/"
111
+ Search.new.url # => "http://localhost/"
112
+
113
+ and it uses @options instance variable with special value :options
114
+
115
+ class Window
116
+ dsl_accessor :width, :default=>640, :instance=>:options
117
+ def initialize(options = {})
118
+ @options = options
119
+ end
120
+ end
121
+
122
+ Window.width # => 640
123
+ Window.new.width # => 640
124
+
125
+ window = Window.new(:width=>320)
126
+ window.width # =>320
127
+
128
+
129
+ Auto declared mode
130
+ ==================
131
+
132
+ It was removed at version 0.4.
133
+ In 0.4.1 or higher, use dsl_accessor block instead.
134
+
135
+
136
+ with block
137
+ ==========
138
+
139
+ dsl_accessor method accepts block for auto declared mode.
140
+ In this mode, we can define methods like dsl.
141
+
142
+ [NOTE]
143
+ 1. This affects only methods with a block and no other args.
144
+
145
+ class Foo
146
+ dsl_accessor do
147
+ foo {1} # Foo.foo is defined
148
+ bar(a) # NoMethodError
149
+ baz(a) {2} # NoMethodError
150
+ end
151
+ end
152
+
153
+ 2. When :instance is passed with block, it affects instance methods.
154
+
155
+ class Foo
156
+ dsl_accessor :instance do
157
+ foo {1} # Foo#foo is defined
158
+ bar(a) # NoMethodError (same as class)
159
+ end
160
+ end
161
+
162
+ 3. This will damage on your class cause it easily updates existing methods.
163
+
164
+ Foo.name # => 'Foo'
165
+ class Foo
166
+ dsl_accessor do
167
+ name {1}
168
+ end
169
+ end
170
+ Foo.name # => 1
171
+
172
+
173
+ Although there is a risk on above, it helps you when many one-lined methods exist.
174
+
175
+ class Foo
176
+ def last
177
+ num_pages
178
+ end
179
+
180
+ def first?
181
+ page == 1
182
+ end
183
+
184
+ def offset
185
+ model.proxy_options[:offset]
186
+ end
187
+ end
188
+
189
+ Refactored with dsl_accessor
190
+
191
+ class Foo
192
+ dsl_accessor :instance do
193
+ last {num_pages}
194
+ first? {page == 1}
195
+ offset {model.proxy_options[:offset]}
196
+ end
197
+ end
198
+
199
+
200
+ Homepage
201
+ ========
202
+
203
+ http://github.com/maiha/dsl_accessor
204
+
205
+
206
+ Author
207
+ ======
208
+ Maiha <maiha@wota.jp>
209
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -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
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "dsl_accessor/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "genki-dsl_accessor"
7
+ s.version = DslAccessor::VERSION
8
+ s.authors = ["genki"]
9
+ s.email = ["genki@s21g.com"]
10
+ s.homepage = "https://github.com/genki/dsl_accessor"
11
+ s.summary = %q{This plugin gives hybrid accessor class methods to classes by DSL like definition}
12
+ s.description = %q{This plugin gives hybrid accessor class methods to classes by DSL like definition}
13
+
14
+ s.rubyforge_project = "dsl_accessor"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_dependency "optionize", ">= 0.1.0"
22
+
23
+ s.add_development_dependency "rspec"
24
+ end
@@ -0,0 +1,19 @@
1
+ unless Module.new.respond_to?(:delegate)
2
+ require File.dirname(__FILE__) + "/../core_ext/module/delegation"
3
+ end
4
+
5
+ require File.dirname(__FILE__) + '/dsl_accessor/version'
6
+ require File.dirname(__FILE__) + '/dsl_accessor/auto_declare'
7
+ require File.dirname(__FILE__) + '/dsl_accessor/accessor'
8
+ require File.dirname(__FILE__) + '/dsl_accessor/stores'
9
+
10
+ class Module
11
+ include DslAccessor
12
+ include DslAccessor::Stores::Basic
13
+ end
14
+
15
+ class Class
16
+ include DslAccessor
17
+ include DslAccessor::Stores::Inherit
18
+ end
19
+
@@ -0,0 +1,117 @@
1
+ require 'optionize'
2
+
3
+ module DslAccessor
4
+ def dsl_accessor_reader(key, *args, &block)
5
+ key = key.to_s
6
+ if !args.empty? or block_given?
7
+ # setter method
8
+ dsl_accessor_writer(key, *args, &block)
9
+ else
10
+ # getter method
11
+ if !dsl_accessor_key?(key)
12
+ # load default value
13
+ default = dsl_accessor_get("#{key}_default")
14
+ value = default ? default.call : nil
15
+ dsl_accessor_writer(key, value)
16
+ end
17
+ dsl_accessor_get(key)
18
+ end
19
+ end
20
+
21
+ def dsl_accessor_writer(key, *args, &block)
22
+ case args.size
23
+ when 0
24
+ unless block_given?
25
+ raise ArgumentError, "'#{key}=' expected one argument or block, but nothing passed"
26
+ end
27
+ writer = dsl_accessor_get("#{key}_writer")
28
+ value = writer ? writer.call(block) : block
29
+ dsl_accessor_set("#{key}", value)
30
+ when 1
31
+ if block_given?
32
+ raise ArgumentError, "'#{key}=' got both arg and block, specify only one of them"
33
+ end
34
+
35
+ writer = dsl_accessor_get("#{key}_writer")
36
+ value = writer ? writer.call(*args) : args.first
37
+ dsl_accessor_set("#{key}", value)
38
+ else
39
+ raise ArgumentError, "'#{key}=' expected one argument, but got #{args.size} args"
40
+ end
41
+ end
42
+
43
+ def dsl_accessor(*args, &block)
44
+ opts = Optionize.new(args, :name, :default)
45
+ name = opts.name
46
+
47
+ if block
48
+ case name
49
+ when :class, NilClass
50
+ AutoDeclare::DefineClassMethod.new(self, &block)
51
+ when :instance
52
+ AutoDeclare::DefineInstanceMethod.new(self, &block)
53
+ else
54
+ raise ArgumentError, "dsl_accessor block expects :class or :instance for arg, but got #{name.inspect}"
55
+ end
56
+ return
57
+ end
58
+
59
+ if !name
60
+ raise ArgumentError, "dsl_accessor expects at least one arg"
61
+ end
62
+
63
+ writer =
64
+ case opts.writer
65
+ when NilClass then Proc.new{|value| value}
66
+ when Symbol then Proc.new{|value| __send__(opts.writer, value)}
67
+ when Proc then opts.writer
68
+ else raise TypeError, "DSL Error: writer should be a symbol or proc. but got `#{opts.writer.class}'"
69
+ end
70
+ dsl_accessor_set("#{name}_writer", writer)
71
+
72
+ default =
73
+ case opts.default
74
+ when NilClass then nil
75
+ when [] then Proc.new{[]}
76
+ when {} then Proc.new{{}}
77
+ when Symbol then Proc.new{__send__(opts.default)}
78
+ when Proc then opts.default
79
+ else Proc.new{opts.default}
80
+ end
81
+ dsl_accessor_set("#{name}_default", default)
82
+
83
+ meta_class = (class << self; self; end)
84
+
85
+ if opts.instance and !is_a?(Class)
86
+ raise ArgumentError, ":instance option is implemented in only Class"
87
+ end
88
+
89
+ case opts.instance
90
+ when nil
91
+ # nop
92
+ when true
93
+ delegate name, :to=>"self.class"
94
+ when Symbol
95
+ module_eval(<<-EOS, "(__DSL_ACCESSOR__)", 1)
96
+ def #{ name }
97
+ @#{opts.instance} or
98
+ raise TypeError, "DSL Error: missing @#{opts.instance} for %s##{name}" % self.class.name
99
+ @#{opts.instance}.respond_to?(:[]) or
100
+ raise TypeError, "DSL Error: expected @#{opts.instance}[] is implemented (%s##{name})" % self.class.name
101
+ @#{opts.instance}[:#{ name }] || self.class.#{ name }
102
+ end
103
+ EOS
104
+ else
105
+ raise TypeError, "DSL Error: :instance should be true or Symbol, but got `%s' class" % opts.instance.class
106
+ end
107
+
108
+ instance_eval <<-EOS
109
+ def #{name}(*args, &block)
110
+ dsl_accessor_reader("#{name}", *args, &block)
111
+ end
112
+ def #{name}=(*args, &block)
113
+ dsl_accessor_writer("#{name}", *args, &block)
114
+ end
115
+ EOS
116
+ end
117
+ end
@@ -0,0 +1,41 @@
1
+ require 'blankslate'
2
+
3
+ module DslAccessor
4
+ module AutoDeclare
5
+ class DefineClassMethod < BasicObject
6
+ def initialize(context, &block)
7
+ @context = context
8
+ instance_eval(&block)
9
+ end
10
+
11
+ private
12
+ def method_missing(name, *args, &block)
13
+ if args.empty? and block
14
+ meta_class = (class << @context; self; end)
15
+ meta_class.class_eval{ define_method(name, &block) }
16
+ else
17
+ @context.__send__(name, *args, &block)
18
+ end
19
+ end
20
+ end
21
+
22
+ class DefineInstanceMethod < BasicObject
23
+ def initialize(klass, &block)
24
+ @klass = klass
25
+ instance_eval(&block)
26
+ end
27
+
28
+ private
29
+ def method_missing(name, *args, &block)
30
+ if args.empty? and block
31
+ @klass.class_eval{ define_method(name, &block) }
32
+ else
33
+ raise NameError, "undefined local variable or method `#{name}'"
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+
41
+ __END__
@@ -0,0 +1,60 @@
1
+ module DslAccessor
2
+ module Stores
3
+ module Basic
4
+ # testing
5
+ def dsl_accessor_attributes
6
+ @dsl_accessor_attributes ||= {}
7
+ end
8
+
9
+ def dsl_accessor_key?(key)
10
+ dsl_accessor_attributes.has_key?(key)
11
+ end
12
+
13
+ def dsl_accessor_get(key)
14
+ dsl_accessor_attributes[key]
15
+ end
16
+
17
+ def dsl_accessor_set(key, val)
18
+ dsl_accessor_attributes[key] = val
19
+ end
20
+ end
21
+
22
+ module Inherit
23
+ # testing
24
+ def dsl_accessor_attributes
25
+ @dsl_accessor_attributes ||= {}
26
+ end
27
+
28
+ def dsl_accessor_key?(key)
29
+ dsl_accessor_attributes.has_key?(key)
30
+ end
31
+
32
+ def dsl_accessor_get(key)
33
+ if dsl_accessor_key?(key)
34
+ dsl_accessor_attributes[key]
35
+ else
36
+ superclass ? superclass.dsl_accessor_get(key) : nil
37
+ end
38
+ end
39
+
40
+ def dsl_accessor_set(key, val)
41
+ dsl_accessor_attributes[key] = val
42
+ end
43
+ end
44
+
45
+ module InheritableAttributes
46
+ # testing
47
+ def dsl_accessor_key?(key)
48
+ inheritable_attributes.has_key?(key)
49
+ end
50
+
51
+ def dsl_accessor_get(key)
52
+ read_inheritable_attribute(key)
53
+ end
54
+
55
+ def dsl_accessor_set(key, val)
56
+ write_inheritable_attribute(key, val)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,4 @@
1
+ module DslAccessor
2
+ VERSION = "0.4.2"
3
+ end
4
+
@@ -0,0 +1,56 @@
1
+ require File.join( File.dirname(__FILE__), "spec_helper" )
2
+
3
+ describe DslAccessor do
4
+ it "class should provide 'dsl_accessor'" do
5
+ Class.new.should respond_to(:dsl_accessor)
6
+ end
7
+ end
8
+
9
+ describe "dsl_accessor(:foo)" do
10
+ before do
11
+ @klass = new_class { dsl_accessor :foo }
12
+ end
13
+
14
+ it "should provide 'foo' method" do
15
+ @klass.should respond_to(:foo)
16
+ end
17
+
18
+ it "should accept nil for default value" do
19
+ @klass.foo.should == nil
20
+ end
21
+
22
+ it "should provide 'foo=' method" do
23
+ @klass.should respond_to(:foo=)
24
+ end
25
+
26
+ it "#foo= should raise ArgumentError" do
27
+ lambda { @klass.send(:foo=) }.should raise_error(ArgumentError)
28
+ end
29
+
30
+ it "#foo=(1) should not raise ArgumentError" do
31
+ lambda { @klass.foo = 1 }.should_not raise_error(ArgumentError)
32
+ end
33
+
34
+ it "#foo=(1) should set :foo to 1" do
35
+ @klass.foo = 1
36
+ @klass.foo.should == 1
37
+ end
38
+
39
+ it "#foo=(1, 2) should raise ArgumentError" do
40
+ lambda { @klass.send(:foo=,1,2) }.should raise_error(ArgumentError)
41
+ end
42
+ end
43
+
44
+ describe "dsl_accessor(:foo, 1)" do
45
+ before do
46
+ @klass = new_class { dsl_accessor :foo, 1 }
47
+ end
48
+
49
+ it "should provide 'foo' method" do
50
+ @klass.should respond_to(:foo)
51
+ end
52
+
53
+ it "should accept 1 for default value" do
54
+ @klass.foo.should == 1
55
+ end
56
+ end
@@ -0,0 +1,123 @@
1
+ require File.join( File.dirname(__FILE__), "spec_helper" )
2
+
3
+ describe DslAccessor do
4
+ before do
5
+ Object.send(:remove_const, :Foo) if Object.const_defined?(:Foo)
6
+ Foo = Class.new
7
+ end
8
+
9
+ def dsl_accessor(*args, &block)
10
+ Foo.dsl_accessor(*args, &block)
11
+ end
12
+
13
+ ######################################################################
14
+ ### Class Methods
15
+
16
+ describe "dsl_accessor(&block)" do
17
+ context " should raise NameError when" do
18
+ def dsl_accessor(*args, &block)
19
+ lambda { super }.should raise_error(NameError)
20
+ end
21
+
22
+ it "foo" do
23
+ dsl_accessor { foo }
24
+ end
25
+
26
+ it "foo(1)" do
27
+ dsl_accessor { foo(1) }
28
+ end
29
+
30
+ it "foo(1,2)" do
31
+ dsl_accessor { foo(1,2) }
32
+ end
33
+
34
+ it "foo(1) {}" do
35
+ dsl_accessor { foo(1) {} }
36
+ end
37
+ end
38
+
39
+ context " should define class method 'foo' when" do
40
+ def dsl_accessor(*args, &block)
41
+ super
42
+ Foo.should respond_to(:foo)
43
+ end
44
+
45
+ it "foo {}" do
46
+ dsl_accessor { foo {} }
47
+ end
48
+ end
49
+
50
+ it "should overwrite existing class methods such as 'name'" do
51
+ Foo.dsl_accessor {
52
+ name { 1 }
53
+ }
54
+ Foo.name.should == 1
55
+ end
56
+
57
+ it "should invoke the method in valid context" do
58
+ Foo.should_receive(:bar) { 2 }
59
+ dsl_accessor { foo { bar } }
60
+ Foo.foo.should == 2
61
+ end
62
+ end
63
+
64
+ ######################################################################
65
+ ### Instance Methods
66
+
67
+ describe "dsl_accessor(:instance, &block)" do
68
+ context " should raise NameError when" do
69
+ def dsl_accessor(*args, &block)
70
+ lambda { super }.should raise_error(NameError)
71
+ end
72
+
73
+ it "foo" do
74
+ dsl_accessor(:instance) { foo }
75
+ end
76
+
77
+ it "foo(1)" do
78
+ dsl_accessor(:instance) { foo(1) }
79
+ end
80
+
81
+ it "foo(1,2)" do
82
+ dsl_accessor(:instance) { foo(1,2) }
83
+ end
84
+
85
+ it "foo(1) {}" do
86
+ dsl_accessor(:instance) { foo(1) {} }
87
+ end
88
+ end
89
+
90
+ context " should define instance method 'foo' when" do
91
+ def dsl_accessor(*args, &block)
92
+ super
93
+ Foo.new.should respond_to(:foo)
94
+ end
95
+
96
+ it "foo {}" do
97
+ dsl_accessor(:instance) { foo {} }
98
+ end
99
+ end
100
+
101
+ it "should define instance method" do
102
+ Foo.dsl_accessor(:instance) {
103
+ foo { 'xxx' }
104
+ }
105
+ Foo.new.foo.should == 'xxx'
106
+ end
107
+
108
+ it "should orverwrite existed instance methods even if those are important like 'object_id'" do
109
+ Foo.new.object_id.should be_kind_of(Integer)
110
+ Foo.dsl_accessor(:instance) {
111
+ object_id { 'xxx' }
112
+ }
113
+ Foo.new.object_id.should == 'xxx'
114
+ end
115
+
116
+ it "should invoke the method in valid context" do
117
+ Foo.any_instance.should_receive(:bar) { 2 }
118
+ dsl_accessor(:instance) { foo { bar } }
119
+ Foo.new.foo.should == 2
120
+ end
121
+ end
122
+ end
123
+
@@ -0,0 +1,39 @@
1
+ require File.join( File.dirname(__FILE__), "spec_helper" )
2
+
3
+ describe DslAccessor do
4
+ it "should duplicate blank array automatically" do
5
+ k1 = Class.new
6
+
7
+ array = []
8
+ k1.dsl_accessor :foo, array
9
+
10
+ k1.foo.should == array
11
+ k1.foo.should_not equal(array)
12
+ end
13
+
14
+ it "should duplicate blank hash automatically" do
15
+ k1 = Class.new
16
+
17
+ hash = {}
18
+ k1.dsl_accessor :foo, :default=>hash
19
+
20
+ k1.foo.should == hash
21
+ k1.foo.should_not equal(hash)
22
+ end
23
+
24
+ it "should call the method when symbol given" do
25
+ k1 = Class.new
26
+ def k1.construct
27
+ 1
28
+ end
29
+ k1.dsl_accessor :foo, :default=>:construct
30
+
31
+ k1.foo.should == 1
32
+ end
33
+
34
+ it "should call it when proc given" do
35
+ k1 = Class.new
36
+ k1.dsl_accessor :foo, :default=>proc{1}
37
+ k1.foo.should == 1
38
+ end
39
+ end
@@ -0,0 +1,48 @@
1
+ require File.join( File.dirname(__FILE__), "spec_helper" )
2
+
3
+ describe DslAccessor do
4
+ # | foo | bar | baz | qux | quux |
5
+ # Bottom | * | * | o | o | |
6
+ # Middle | | o | | + | o |
7
+ # Top | + | | + | o | o |
8
+ #
9
+ # *) dsl_accessor :foo
10
+ # o) dsl_accessor :foo, 'val'
11
+ # +) foo 'val'
12
+
13
+ class Bottom
14
+ dsl_accessor :foo
15
+ dsl_accessor :bar
16
+ dsl_accessor :baz, 'baz1'
17
+ dsl_accessor :qux, 'qux1'
18
+ end
19
+
20
+ class Middle < Bottom
21
+ dsl_accessor :bar, 'bar2'
22
+ qux 'qux2'
23
+ dsl_accessor :quux, 'quux2'
24
+ end
25
+
26
+ class Top < Middle
27
+ foo 'foo3'
28
+ baz 'baz3'
29
+ dsl_accessor :qux , 'qux3'
30
+ dsl_accessor :quux, 'quux3'
31
+ end
32
+
33
+ it "should define accessor methods" do
34
+ Bottom.foo.should == nil
35
+ Bottom.bar.should == nil
36
+ Bottom.baz.should == 'baz1'
37
+ Bottom.qux.should == 'qux1'
38
+ lambda { Bottom.quux }.should raise_error(NameError)
39
+ end
40
+
41
+ it "should inherit value" do
42
+ Middle.foo.should == nil
43
+ Middle.bar.should == 'bar2'
44
+ Middle.baz.should == 'baz1'
45
+ Middle.qux.should == 'qux2'
46
+ Middle.quux.should == 'quux2'
47
+ end
48
+ end
@@ -0,0 +1,51 @@
1
+ require File.join( File.dirname(__FILE__), "spec_helper" )
2
+
3
+ describe "dsl_accessor(:foo, :instance=>true)" do
4
+ before do
5
+ klass = Class.new
6
+ klass.dsl_accessor :foo, :instance=>true
7
+ @klass = klass
8
+ end
9
+
10
+ it "should provide instance method 'foo'" do
11
+ @klass.new.should respond_to(:foo)
12
+ end
13
+
14
+ it "should delegate instance method to class method about reader" do
15
+ @klass.foo 1
16
+ @klass.new.foo.should == 1
17
+ end
18
+ end
19
+
20
+ describe "dsl_accessor(:foo, :instance=>:opts)" do
21
+ before do
22
+ klass = Class.new
23
+ klass.dsl_accessor :foo, :instance=>:opts
24
+ @klass = klass
25
+ @obj = @klass.new
26
+ end
27
+
28
+ it "should raise error when @opts is not set" do
29
+ lambda {
30
+ @obj.foo
31
+ }.should raise_error(/missing @opts/)
32
+ end
33
+
34
+ it "should raise error when @opts is present but not responds to []" do
35
+ @obj.instance_eval "@opts = true"
36
+ lambda {
37
+ @obj.foo
38
+ }.should raise_error(/expected @opts\[\]/)
39
+ end
40
+
41
+ it "should read value from @opts first" do
42
+ @obj.instance_eval "@opts = {:foo=>2}"
43
+ @obj.foo.should == 2
44
+ end
45
+
46
+ it "should read value from class when @opts value is blank" do
47
+ @klass.foo 1
48
+ @obj.instance_eval "@opts = {}"
49
+ @obj.foo.should == 1
50
+ end
51
+ end
@@ -0,0 +1,22 @@
1
+ require File.join( File.dirname(__FILE__), "spec_helper" )
2
+
3
+ describe Module do
4
+ it "should provide 'dsl_accessor'" do
5
+ Module.new.should respond_to(:dsl_accessor)
6
+ end
7
+
8
+ describe "#dsl_accessor(:foo, 1)" do
9
+ subject {
10
+ mod = Module.new
11
+ mod.dsl_accessor :foo, 1
12
+ mod
13
+ }
14
+ # default value
15
+ its(:foo) { should == 1}
16
+
17
+ it "foo(2) should update value to 2" do
18
+ subject.foo 2
19
+ subject.foo.should == 2
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ require File.join( File.dirname(__FILE__), "spec_helper" )
2
+
3
+ describe "dsl_accessor :foo" do
4
+ before do
5
+ @klass = new_class { dsl_accessor :foo }
6
+ end
7
+
8
+ it "should accept foo(1)" do
9
+ @klass.foo 1
10
+ @klass.foo.should == 1
11
+ end
12
+
13
+ it "should reject foo(1, &block)" do
14
+ lambda {
15
+ @klass.foo(2) { 3 }
16
+ }.should raise_error(ArgumentError)
17
+ end
18
+
19
+ it "should accept foo(&block)" do
20
+ @klass.foo { 4 }
21
+ @klass.foo.should be_kind_of(Proc)
22
+ @klass.foo.call.should == 4
23
+ end
24
+ end
@@ -0,0 +1,11 @@
1
+ require "rubygems"
2
+ require "rspec"
3
+
4
+ require File.dirname(__FILE__) + "/../lib/dsl_accessor"
5
+
6
+ ######################################################################
7
+ ### Helper methods
8
+
9
+ def new_class(&block)
10
+ Class.new(&block)
11
+ end
@@ -0,0 +1,35 @@
1
+ require File.join( File.dirname(__FILE__), "spec_helper" )
2
+
3
+ describe DslAccessor do
4
+ it "should call writer" do
5
+ klass = new_class
6
+
7
+ klass.dsl_accessor :key, "bar", :writer=>proc{|value| "[#{value}]"}
8
+ klass.key.should == "[bar]"
9
+
10
+ klass.key 'foo'
11
+ klass.key.should == "[foo]"
12
+ end
13
+
14
+ it "should call writer even if no default values given" do
15
+ klass = new_class
16
+
17
+ klass.dsl_accessor :key, :writer=>proc{|value| "[#{value}]"}
18
+ klass.key.should == "[]"
19
+
20
+ klass.key 'foo'
21
+ klass.key.should == "[foo]"
22
+ end
23
+
24
+ it "should call the method when symbol given" do
25
+ klass = new_class
26
+
27
+ klass.dsl_accessor :key, :default=>"foo", :writer=>:labelize
28
+ def klass.labelize(val)
29
+ "[#{val}]"
30
+ end
31
+
32
+ klass.key.should == "[foo]"
33
+ end
34
+
35
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :dsl_accessor do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: genki-dsl_accessor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - genki
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: optionize
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.1.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.1.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: This plugin gives hybrid accessor class methods to classes by DSL like
47
+ definition
48
+ email:
49
+ - genki@s21g.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - Gemfile
55
+ - MIT-LICENSE
56
+ - README
57
+ - Rakefile
58
+ - core_ext/module/delegation.rb
59
+ - dsl_accessor.gemspec
60
+ - lib/dsl_accessor.rb
61
+ - lib/dsl_accessor/accessor.rb
62
+ - lib/dsl_accessor/auto_declare.rb
63
+ - lib/dsl_accessor/stores.rb
64
+ - lib/dsl_accessor/version.rb
65
+ - spec/accessor_spec.rb
66
+ - spec/auto_declared_spec.rb
67
+ - spec/default_spec.rb
68
+ - spec/inherit_spec.rb
69
+ - spec/instance_spec.rb
70
+ - spec/module_spec.rb
71
+ - spec/setter_spec.rb
72
+ - spec/spec_helper.rb
73
+ - spec/writer_spec.rb
74
+ - tasks/dsl_accessor_tasks.rake
75
+ homepage: https://github.com/genki/dsl_accessor
76
+ licenses: []
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project: dsl_accessor
95
+ rubygems_version: 1.8.24
96
+ signing_key:
97
+ specification_version: 3
98
+ summary: This plugin gives hybrid accessor class methods to classes by DSL like definition
99
+ test_files:
100
+ - spec/accessor_spec.rb
101
+ - spec/auto_declared_spec.rb
102
+ - spec/default_spec.rb
103
+ - spec/inherit_spec.rb
104
+ - spec/instance_spec.rb
105
+ - spec/module_spec.rb
106
+ - spec/setter_spec.rb
107
+ - spec/spec_helper.rb
108
+ - spec/writer_spec.rb