genki-dsl_accessor 0.4.2
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/Gemfile +3 -0
- data/MIT-LICENSE +20 -0
- data/README +209 -0
- data/Rakefile +1 -0
- data/core_ext/module/delegation.rb +95 -0
- data/dsl_accessor.gemspec +24 -0
- data/lib/dsl_accessor.rb +19 -0
- data/lib/dsl_accessor/accessor.rb +117 -0
- data/lib/dsl_accessor/auto_declare.rb +41 -0
- data/lib/dsl_accessor/stores.rb +60 -0
- data/lib/dsl_accessor/version.rb +4 -0
- data/spec/accessor_spec.rb +56 -0
- data/spec/auto_declared_spec.rb +123 -0
- data/spec/default_spec.rb +39 -0
- data/spec/inherit_spec.rb +48 -0
- data/spec/instance_spec.rb +51 -0
- data/spec/module_spec.rb +22 -0
- data/spec/setter_spec.rb +24 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/writer_spec.rb +35 -0
- data/tasks/dsl_accessor_tasks.rake +4 -0
- metadata +108 -0
data/Gemfile
ADDED
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
|
data/lib/dsl_accessor.rb
ADDED
@@ -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,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
|
data/spec/module_spec.rb
ADDED
@@ -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
|
data/spec/setter_spec.rb
ADDED
@@ -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
|
data/spec/spec_helper.rb
ADDED
data/spec/writer_spec.rb
ADDED
@@ -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
|
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
|