magic_options 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README.rdoc +79 -0
- data/Rakefile +19 -0
- data/lib/magic_options.rb +74 -2
- data/lib/magic_options/version.rb +2 -1
- data/magic_options.gemspec +3 -1
- data/spec/magic_options/class_method_spec.rb +23 -187
- data/spec/magic_options/instance_method_spec.rb +74 -145
- metadata +55 -52
- data/README.md +0 -118
data/.gitignore
CHANGED
data/README.rdoc
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
= magic_options
|
2
|
+
|
3
|
+
MagicOptions is a ruby module that provides mechanisms for splatting
|
4
|
+
an options hash into an object's instance variables, typically during
|
5
|
+
object initialization. Each key is taken as the name of an instance
|
6
|
+
variable, to which the associated value is assigned.
|
7
|
+
|
8
|
+
Version 1.0.0 broke compatibility with previous versions, in the
|
9
|
+
interests of being useful in subclasses and in initializers that take
|
10
|
+
more than just an options hash.
|
11
|
+
|
12
|
+
== Examples
|
13
|
+
|
14
|
+
The simplest approach is to use MagicOptions::ClassMethods#magic_initialize:
|
15
|
+
|
16
|
+
require 'rubygems'
|
17
|
+
require 'magic_options'
|
18
|
+
|
19
|
+
class Gullible
|
20
|
+
|
21
|
+
include MagicOptions
|
22
|
+
|
23
|
+
magic_initialize
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
Gullible.new :accepts => "anything"
|
28
|
+
# => #<Gullible:0x7f77e407fdb0 @accepts="anything">
|
29
|
+
|
30
|
+
If you want an +ArgumentError+ for options that don't have accessors:
|
31
|
+
|
32
|
+
class Cow
|
33
|
+
|
34
|
+
include MagicOptions
|
35
|
+
|
36
|
+
magic_initialize :only => :respond_to?
|
37
|
+
|
38
|
+
attr_accessor :color, :gender
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
Cow.new :color => "brown", :gender => "female"
|
43
|
+
# => #<Cow:0x7f77e409a6d8 @gender="female", @color="brown">
|
44
|
+
Cow.new :color => "brown", :gender => "female", :wheels => 4
|
45
|
+
# => ArgumentError: Unknown option wheels for new Cow
|
46
|
+
|
47
|
+
If your object initializer must do more than apply the magic options pattern,
|
48
|
+
you can use MagicOptions#magic_options inside your +initialize+ method. This
|
49
|
+
example also illustrates a more explicit method of specifying which options
|
50
|
+
are allowed:
|
51
|
+
|
52
|
+
class Professor < Staff
|
53
|
+
|
54
|
+
include MagicOptions
|
55
|
+
|
56
|
+
def initialize(name, options = {})
|
57
|
+
magic_options options, :only => [:iq, :hairstyle]
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
Professor.new :hair_style => :einsteinian
|
63
|
+
# => #<Professor:0x7f77e406d980 @hair_style=:einsteinian>
|
64
|
+
Professor.new :does_not_take => :anything
|
65
|
+
# => ArgumentError: Unknown option does_not_take for new Professor
|
66
|
+
|
67
|
+
== Obtaining
|
68
|
+
|
69
|
+
To install from rubygems.org:
|
70
|
+
|
71
|
+
gem install magic_options
|
72
|
+
|
73
|
+
To fetch the source from github.com:
|
74
|
+
|
75
|
+
git clone git://github.com/sheldonh/magic_options.git
|
76
|
+
|
77
|
+
== Credits
|
78
|
+
|
79
|
+
Written in colaboration with @rorymckinley[http://twitter.com/#!/rorymckinley]
|
data/Rakefile
CHANGED
@@ -1 +1,20 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'rdoc/task'
|
4
|
+
|
5
|
+
desc 'Generate rdoc documentation'
|
6
|
+
RDoc::Task.new do |t|
|
7
|
+
t.main = 'README.rdoc'
|
8
|
+
t.rdoc_dir = 'rdoc'
|
9
|
+
t.rdoc_files.include %w{ README.rdoc lib/**/*.rb }
|
10
|
+
end
|
11
|
+
|
12
|
+
desc 'Run all rspec examples'
|
13
|
+
RSpec::Core::RakeTask.new(:spec)
|
14
|
+
|
15
|
+
namespace :spec do
|
16
|
+
desc 'Run all rspec examples with pretty output'
|
17
|
+
RSpec::Core::RakeTask.new(:doc) do |t|
|
18
|
+
t.rspec_opts = '--color --format=doc'
|
19
|
+
end
|
20
|
+
end
|
data/lib/magic_options.rb
CHANGED
@@ -1,7 +1,58 @@
|
|
1
1
|
require "magic_options/version"
|
2
2
|
|
3
|
+
# MagicOptions is a ruby module that provides mechanisms for splatting
|
4
|
+
# an options hash into an object's instance variables, typically during
|
5
|
+
# object initialization. Each key is taken as the name of an instance
|
6
|
+
# variable, to which the associated value is assigned.
|
7
|
+
#
|
8
|
+
# For example:
|
9
|
+
#
|
10
|
+
# <tt>
|
11
|
+
# class Cow
|
12
|
+
# def initialize(name, options = {})
|
13
|
+
# @name = name.capitalize
|
14
|
+
# @color = color
|
15
|
+
# @gender = gender
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# Cow.new('Daisy', :color => 'brown', :gender => 'female')
|
20
|
+
# # => #<Cow:0x000000015d02b8 @color="brown", @gender="female", @name="Daisy">
|
21
|
+
# </tt>
|
22
|
+
#
|
23
|
+
# Here's how the same object initializer might be defined with MagicOptions:
|
24
|
+
#
|
25
|
+
# <tt>
|
26
|
+
# class Cow
|
27
|
+
# include MagicOptions
|
28
|
+
#
|
29
|
+
# def initialize(name, options = {})
|
30
|
+
# @name = name.capitalize
|
31
|
+
# magic_options(options, :only => [:color, :gender])
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
# </tt>
|
35
|
+
#
|
36
|
+
# If your initialize method does nothing other than implement the magic options pattern,
|
37
|
+
# you can let MagicOptions::ClassMethods#magic_initialize define it for you instead.
|
38
|
+
#
|
3
39
|
module MagicOptions
|
4
40
|
|
41
|
+
# Assign every value from the options hash into an instance variable named after the associated key.
|
42
|
+
# The optional config hash may impose constraints on this behaviour as follows:
|
43
|
+
#
|
44
|
+
# [+:only+]
|
45
|
+
# Specify the only options that are allowed. The special value +:respond_to?+ specifies that options
|
46
|
+
# are allowed if they name a method on the instance.
|
47
|
+
#
|
48
|
+
# [+:require+]
|
49
|
+
# Specify options that must be passed. Options specified in +:require+ do not also need to be
|
50
|
+
# specified in +:only+.
|
51
|
+
#
|
52
|
+
# Raises:
|
53
|
+
#
|
54
|
+
# [ArgumentError] when +:only+ is specified and an option is passed that is not in +:only+ or +:require+
|
55
|
+
# [ArgumentError] when +:require+ specifies one or more options that are not passed
|
5
56
|
def magic_options(options, config = {})
|
6
57
|
magic_options_validate(options, config)
|
7
58
|
options.each do |option, value|
|
@@ -9,14 +60,35 @@ module MagicOptions
|
|
9
60
|
end
|
10
61
|
end
|
11
62
|
|
12
|
-
def self.included(base)
|
63
|
+
def self.included(base) # :nodoc:
|
13
64
|
base.extend(ClassMethods)
|
14
65
|
end
|
15
66
|
|
67
|
+
# When an object initializer need do nothing more than implement the magic options pattern,
|
68
|
+
# it can be defined in terms of its magic options as follows:
|
69
|
+
#
|
70
|
+
# <tt>
|
71
|
+
# class Cow
|
72
|
+
# include MagicOptions
|
73
|
+
# magic_initialize(:require => :name, :only => [:color, :gender])
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# Cow.new(:name => 'Daisy', :color => 'brown', :gender => 'female')
|
77
|
+
# # => #<Cow:0x000000015d02b8 @color="brown", @gender="female", @name="Daisy">
|
78
|
+
# </tt>
|
79
|
+
#
|
80
|
+
# When the object initializer must do more than this (for example, if it must call +super+),
|
81
|
+
# you can define it yourself in terms of MagicOptions#magic_options.
|
82
|
+
#
|
16
83
|
module ClassMethods
|
17
84
|
|
85
|
+
# Class accessor used by #magic_initialize to store the +config+ hash it receives, to be
|
86
|
+
# passed into MagicOptions#magic_options in the object initializer that #magic_initialize
|
87
|
+
# defines.
|
18
88
|
attr_accessor :magic_options_config
|
19
89
|
|
90
|
+
# Defines an object initializer that takes an options hash and passes it to
|
91
|
+
# MagicOptions#magic_options, along with the optional +config+ hash.
|
20
92
|
def magic_initialize(config = {})
|
21
93
|
self.magic_options_config = config
|
22
94
|
class_eval %{
|
@@ -30,7 +102,7 @@ module MagicOptions
|
|
30
102
|
|
31
103
|
private
|
32
104
|
|
33
|
-
def magic_options_validate(options, config)
|
105
|
+
def magic_options_validate(options, config) # :nodoc:
|
34
106
|
if config[:only] == :respond_to?
|
35
107
|
if unknown = options.keys.detect { |option| !respond_to?(option) }
|
36
108
|
raise ArgumentError, "Unknown option #{unknown} in new #{self.class}"
|
data/magic_options.gemspec
CHANGED
@@ -17,5 +17,7 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
18
|
s.require_paths = ["lib"]
|
19
19
|
|
20
|
-
s.add_development_dependency('
|
20
|
+
s.add_development_dependency('rake', '~> 0.9.2')
|
21
|
+
s.add_development_dependency('rdoc', '~> 2.5.8')
|
22
|
+
s.add_development_dependency('rspec', '~> 2.6.0')
|
21
23
|
end
|
@@ -1,205 +1,41 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
require 'magic_options'
|
2
3
|
|
3
|
-
describe "MagicOptions::ClassMethods#magic_initialize" do
|
4
|
-
|
5
|
-
context "Given class Cow mixes in MagicOptions" do
|
6
|
-
|
7
|
-
before(:each) do
|
8
|
-
require 'magic_options'
|
9
|
-
class Cow
|
10
|
-
include MagicOptions
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
context "When it calls magic_initialize" do
|
15
|
-
|
16
|
-
before(:each) do
|
17
|
-
class Cow
|
18
|
-
magic_initialize
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
context "Then Cow.new(:name => 'Daisy', :color => :brown)" do
|
23
|
-
|
24
|
-
before(:each) do
|
25
|
-
@cow = Cow.new(:name => 'Daisy', :color => :brown)
|
26
|
-
end
|
27
|
-
|
28
|
-
it "sets @name to 'Daisy'" do
|
29
|
-
@cow.instance_variable_get('@name').should == 'Daisy'
|
30
|
-
end
|
31
|
-
|
32
|
-
it "sets @color to :brown" do
|
33
|
-
@cow.instance_variable_get('@color').should == :brown
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
4
|
+
describe "MagicOptions::ClassMethods#magic_initialize(config = {})" do
|
37
5
|
|
6
|
+
before(:each) do
|
7
|
+
begin; Object.send(:remove_const, :Cow); rescue; end
|
8
|
+
class Cow
|
9
|
+
include MagicOptions
|
38
10
|
end
|
11
|
+
end
|
39
12
|
|
40
|
-
|
41
|
-
|
42
|
-
before(:each) do
|
43
|
-
class Cow
|
44
|
-
magic_initialize :only => [:name, :color]
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
context "Then Cow.new(:name => 'Daisy', :color => :brown)" do
|
49
|
-
|
50
|
-
before(:each) do
|
51
|
-
@cow = Cow.new(:name => 'Daisy', :color => :brown)
|
52
|
-
end
|
53
|
-
|
54
|
-
it "sets @name to 'Daisy'" do
|
55
|
-
@cow.instance_variable_get('@name').should == 'Daisy'
|
56
|
-
end
|
57
|
-
|
58
|
-
it "sets @color to :brown" do
|
59
|
-
@cow.instance_variable_get('@color').should == :brown
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
context "Then Cow.new(:name => 'Daisy', :gender => :female)" do
|
65
|
-
|
66
|
-
it "raises an ArgumentError" do
|
67
|
-
lambda {
|
68
|
-
Cow.new(:name => 'Daisy', :gender => :female)
|
69
|
-
}.should raise_error(ArgumentError)
|
70
|
-
end
|
71
|
-
|
72
|
-
it "reports the offending class and the unknown option" do
|
73
|
-
lambda {
|
74
|
-
Cow.new(:name => 'Daisy', :gender => :female)
|
75
|
-
}.should raise_error("Unknown option gender in new Cow")
|
76
|
-
end
|
77
|
-
|
78
|
-
end
|
13
|
+
it "creates an initialize(options = {}) instance method" do
|
14
|
+
Cow.should_receive(:method_added).with(:initialize)
|
79
15
|
|
16
|
+
class Cow
|
17
|
+
magic_initialize
|
80
18
|
end
|
19
|
+
end
|
81
20
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
class Cow
|
86
|
-
magic_initialize :require => :name
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
context "Then Cow.new(:name => 'Daisy', :color => :brown)" do
|
91
|
-
|
92
|
-
before(:each) do
|
93
|
-
@cow = Cow.new(:name => 'Daisy', :color => :brown)
|
94
|
-
end
|
95
|
-
|
96
|
-
it "sets @name to 'Daisy'" do
|
97
|
-
@cow.instance_variable_get('@name').should == 'Daisy'
|
98
|
-
end
|
99
|
-
|
100
|
-
it "sets @color to :brown" do
|
101
|
-
@cow.instance_variable_get('@color').should == :brown
|
102
|
-
end
|
103
|
-
|
104
|
-
end
|
105
|
-
|
106
|
-
context "Then Cow.new(:color => :brown)" do
|
107
|
-
|
108
|
-
it "raises an ArgumentError" do
|
109
|
-
lambda { @cow = Cow.new(:color => :brown) }.should raise_error(ArgumentError)
|
110
|
-
end
|
111
|
-
|
112
|
-
it "reports the offending class and the missing option" do
|
113
|
-
lambda { @cow = Cow.new(:color => 'Daisy') }.should raise_error("Missing option name in new Cow")
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
21
|
+
it "sets up initialize to pass through its options as magic_options' first argument" do
|
22
|
+
class Cow
|
23
|
+
magic_initialize
|
117
24
|
end
|
118
25
|
|
119
|
-
|
120
|
-
|
121
|
-
before(:each) do
|
122
|
-
class Cow
|
123
|
-
magic_initialize :only => :color, :require => :name
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
context "Then Cow.new(:name => 'Daisy', :color => :brown)" do
|
128
|
-
|
129
|
-
before(:each) do
|
130
|
-
@cow = Cow.new(:name => 'Daisy', :color => :brown)
|
131
|
-
end
|
132
|
-
|
133
|
-
it "sets @name to 'Daisy'" do
|
134
|
-
@cow.instance_variable_get('@name').should == 'Daisy'
|
135
|
-
end
|
26
|
+
Cow.any_instance.should_receive(:magic_options).with({:name => "Daisy"}, {})
|
136
27
|
|
137
|
-
|
138
|
-
|
139
|
-
end
|
140
|
-
|
141
|
-
end
|
142
|
-
|
143
|
-
context "Then Cow.new(:color => :brown)" do
|
144
|
-
|
145
|
-
it "raises an ArgumentError" do
|
146
|
-
lambda { @cow = Cow.new(:color => :brown) }.should raise_error(ArgumentError)
|
147
|
-
end
|
148
|
-
|
149
|
-
it "reports the offending class and the missing option" do
|
150
|
-
lambda { @cow = Cow.new(:color => 'Daisy') }.should raise_error("Missing option name in new Cow")
|
151
|
-
end
|
152
|
-
|
153
|
-
end
|
28
|
+
cow = Cow.new(:name => 'Daisy')
|
29
|
+
end
|
154
30
|
|
31
|
+
it "sets up initialize to pass the given config as magic_options's second argument" do
|
32
|
+
class Cow
|
33
|
+
magic_initialize :only => :name
|
155
34
|
end
|
156
35
|
|
157
|
-
|
158
|
-
|
159
|
-
before(:each) do
|
160
|
-
class Cow
|
161
|
-
attr_accessor :name
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
context "When it calls magic_initialize(:only => :respond_to?)" do
|
166
|
-
|
167
|
-
before(:each) do
|
168
|
-
class Cow
|
169
|
-
magic_initialize :only => :respond_to?
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
context "Then Cow.new(:name => 'Daisy')" do
|
174
|
-
|
175
|
-
it "sets @name to 'Daisy'" do
|
176
|
-
@cow = Cow.new(:name => 'Daisy')
|
177
|
-
@cow.instance_variable_get('@name').should == 'Daisy'
|
178
|
-
end
|
179
|
-
|
180
|
-
end
|
181
|
-
|
182
|
-
context "Then Cow.new(:name => 'Daisy', :gender => :female)" do
|
183
|
-
|
184
|
-
it "raises an ArgumentError" do
|
185
|
-
lambda {
|
186
|
-
Cow.new(:name => 'Daisy', :gender => :female)
|
187
|
-
}.should raise_error(ArgumentError)
|
188
|
-
end
|
189
|
-
|
190
|
-
it "reports the offending class and the unknown option" do
|
191
|
-
lambda {
|
192
|
-
Cow.new(:name => 'Daisy', :gender => :female)
|
193
|
-
}.should raise_error("Unknown option gender in new Cow")
|
194
|
-
end
|
195
|
-
|
196
|
-
end
|
197
|
-
|
198
|
-
end
|
199
|
-
|
200
|
-
end
|
36
|
+
Cow.any_instance.should_receive(:magic_options).with({}, { :only => :name })
|
201
37
|
|
38
|
+
cow = Cow.new
|
202
39
|
end
|
203
40
|
|
204
41
|
end
|
205
|
-
|
@@ -1,167 +1,96 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
require 'magic_options'
|
2
3
|
|
3
|
-
describe "MagicOptions#magic_options" do
|
4
|
+
describe "MagicOptions#magic_options(options, config = {})" do
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
class Cow
|
10
|
-
include MagicOptions
|
11
|
-
end
|
6
|
+
before(:each) do
|
7
|
+
begin; Object.send(:remove_const, :Cow); rescue; end
|
8
|
+
class Cow
|
9
|
+
include MagicOptions
|
12
10
|
end
|
11
|
+
end
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
class Cow
|
18
|
-
def initialize(options = {})
|
19
|
-
magic_options options
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context "Then Cow.new(:name => 'Daisy', :color => :brown)" do
|
25
|
-
|
26
|
-
before(:each) do
|
27
|
-
@cow = Cow.new(:name => 'Daisy', :color => :brown)
|
28
|
-
end
|
29
|
-
|
30
|
-
it "sets @name to 'Daisy'" do
|
31
|
-
@cow.instance_variable_get('@name').should == 'Daisy'
|
32
|
-
end
|
33
|
-
|
34
|
-
it "sets @color to :brown" do
|
35
|
-
@cow.instance_variable_get('@color').should == :brown
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
|
13
|
+
it "sets instance variables named after keys in the options hash" do
|
14
|
+
class Cow
|
15
|
+
def initialize(options = {}); magic_options(options); end
|
40
16
|
end
|
17
|
+
@cow = Cow.new(:name => 'Daisy', :color => :brown)
|
18
|
+
@cow.should be_instance_variable_defined('@name')
|
19
|
+
@cow.should be_instance_variable_defined('@color')
|
20
|
+
end
|
41
21
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
class Cow
|
46
|
-
def initialize(options)
|
47
|
-
magic_options(options, :only => [:name, :color])
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
context "Then Cow.new(:name => 'Daisy', :color => :brown)" do
|
53
|
-
|
54
|
-
before(:each) do
|
55
|
-
@cow = Cow.new(:name => 'Daisy', :color => :brown)
|
56
|
-
end
|
57
|
-
|
58
|
-
it "sets @name to 'Daisy'" do
|
59
|
-
@cow.instance_variable_get('@name').should == 'Daisy'
|
60
|
-
end
|
61
|
-
|
62
|
-
it "sets @color to :brown" do
|
63
|
-
@cow.instance_variable_get('@color').should == :brown
|
64
|
-
end
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
context "Then Cow.new(:name => 'Daisy', :gender => :female)" do
|
69
|
-
|
70
|
-
it "raises an ArgumentError" do
|
71
|
-
lambda {
|
72
|
-
Cow.new(:name => 'Daisy', :gender => :female)
|
73
|
-
}.should raise_error(ArgumentError)
|
74
|
-
end
|
75
|
-
|
76
|
-
it "reports the offending class and the unknown option" do
|
77
|
-
lambda {
|
78
|
-
Cow.new(:name => 'Daisy', :gender => :female)
|
79
|
-
}.should raise_error("Unknown option gender in new Cow")
|
80
|
-
end
|
81
|
-
|
82
|
-
end
|
83
|
-
|
22
|
+
it "sets instance variable values to the values in the options hash" do
|
23
|
+
class Cow
|
24
|
+
def initialize(options = {}); magic_options(options); end
|
84
25
|
end
|
26
|
+
@cow = Cow.new(:name => 'Daisy', :color => :brown)
|
27
|
+
@cow.instance_variable_get('@name').should == 'Daisy'
|
28
|
+
@cow.instance_variable_get('@color').should == :brown
|
29
|
+
end
|
85
30
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
class Cow
|
90
|
-
def initialize(options)
|
91
|
-
magic_options(options, :require => :name)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
context "Then Cow.new(:name => 'Daisy', :color => :brown)" do
|
97
|
-
|
98
|
-
before(:each) do
|
99
|
-
@cow = Cow.new(:name => 'Daisy', :color => :brown)
|
100
|
-
end
|
101
|
-
|
102
|
-
it "sets @name to 'Daisy'" do
|
103
|
-
@cow.instance_variable_get('@name').should == 'Daisy'
|
104
|
-
end
|
105
|
-
|
106
|
-
it "sets @color to :brown" do
|
107
|
-
@cow.instance_variable_get('@color').should == :brown
|
108
|
-
end
|
109
|
-
|
110
|
-
end
|
111
|
-
|
112
|
-
context "Then Cow.new(:color => :brown)" do
|
113
|
-
|
114
|
-
it "raises an ArgumentError" do
|
115
|
-
lambda { @cow = Cow.new(:color => :brown) }.should raise_error(ArgumentError)
|
116
|
-
end
|
117
|
-
|
118
|
-
it "reports the offending class and the missing option" do
|
119
|
-
lambda { @cow = Cow.new(:color => 'Daisy') }.should raise_error("Missing option name in new Cow")
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
31
|
+
it "accepts any option names without config[:only]" do
|
32
|
+
class Cow
|
33
|
+
def initialize(options = {}); magic_options(options); end
|
123
34
|
end
|
35
|
+
lambda { @cow = Cow.new(:name => 'Daisy', :color => :brown, :gender => :female) }.should_not raise_error
|
36
|
+
end
|
124
37
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
context "Then Cow.new(:name => 'Daisy', :color => :brown)" do
|
136
|
-
|
137
|
-
before(:each) do
|
138
|
-
@cow = Cow.new(:name => 'Daisy', :color => :brown)
|
139
|
-
end
|
140
|
-
|
141
|
-
it "sets @name to 'Daisy'" do
|
142
|
-
@cow.instance_variable_get('@name').should == 'Daisy'
|
143
|
-
end
|
144
|
-
|
145
|
-
it "sets @color to :brown" do
|
146
|
-
@cow.instance_variable_get('@color').should == :brown
|
147
|
-
end
|
38
|
+
it "accepts option names included in config[:only]" do
|
39
|
+
class Cow
|
40
|
+
def initialize(options = {}); magic_options(options, :only => [:name, :color]); end
|
41
|
+
end
|
42
|
+
lambda { @cow = Cow.new(:name => 'Daisy', :color => :brown) }.should_not raise_error
|
43
|
+
end
|
148
44
|
|
149
|
-
|
45
|
+
it "raises ArgumentError for option names not included in config[:only]" do
|
46
|
+
class Cow
|
47
|
+
def initialize(options = {}); magic_options(options, :only => [:name, :color]); end
|
48
|
+
end
|
49
|
+
lambda { @cow = Cow.new(:name => 'Daisy', :color => :brown, :gender => :female) }.should raise_error(ArgumentError)
|
50
|
+
end
|
150
51
|
|
151
|
-
|
52
|
+
it "accepts the absence of options without config[:require]" do
|
53
|
+
class Cow
|
54
|
+
def initialize(options = {}); magic_options(options); end
|
55
|
+
end
|
56
|
+
lambda { @cow = Cow.new }.should_not raise_error
|
57
|
+
end
|
152
58
|
|
153
|
-
|
154
|
-
|
155
|
-
|
59
|
+
it "raises ArgumentError for absent option names in config[:require]" do
|
60
|
+
class Cow
|
61
|
+
def initialize(options = {}); magic_options(options, :require => [:name, :color]); end
|
62
|
+
end
|
63
|
+
lambda { @cow = Cow.new(:name => 'Daisy') }.should raise_error(ArgumentError)
|
64
|
+
end
|
156
65
|
|
157
|
-
|
158
|
-
|
159
|
-
|
66
|
+
it "accepts option names in config[:require] even when they are not in config[:only]" do
|
67
|
+
class Cow
|
68
|
+
def initialize(options = {}); magic_options(options, :require => :name, :only => :color); end
|
69
|
+
end
|
70
|
+
lambda { @cow = Cow.new(:name => 'Daisy', :color => :brown) }.should_not raise_error
|
71
|
+
end
|
160
72
|
|
161
|
-
|
73
|
+
it "raises ArgumentError for option names absent from both config[:only] and config[:require]" do
|
74
|
+
class Cow
|
75
|
+
def initialize(options = {}); magic_options(options, :require => :name, :only => :color); end
|
76
|
+
end
|
77
|
+
lambda { @cow = Cow.new(:name => 'Daisy', :color => :brown, :gender => :female) }.should raise_error(ArgumentError)
|
78
|
+
end
|
162
79
|
|
80
|
+
it "accepts option names that match instance method names if config[:only] is :respond_to?" do
|
81
|
+
class Cow
|
82
|
+
attr_accessor :name, :color
|
83
|
+
def initialize(options = {}); magic_options(options, :only => :respond_to?); end
|
163
84
|
end
|
85
|
+
lambda { @cow = Cow.new(:name => 'Daisy', :color => :brown) }.should_not raise_error
|
86
|
+
end
|
164
87
|
|
88
|
+
it "raises ArgumentError for option names that match no instance method names if config[:only] is :respond_to?" do
|
89
|
+
class Cow
|
90
|
+
attr_accessor :name, :color
|
91
|
+
def initialize(options = {}); magic_options(options, :only => :respond_to?); end
|
92
|
+
end
|
93
|
+
lambda { @cow = Cow.new(:name => 'Daisy', :color => :brown, :gender => :female) }.should raise_error(ArgumentError)
|
165
94
|
end
|
166
95
|
|
167
96
|
end
|
metadata
CHANGED
@@ -1,51 +1,61 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: magic_options
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 0
|
9
|
-
- 0
|
10
|
-
version: 1.0.0
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Sheldon Hearn
|
14
9
|
- Rory McKinley
|
15
10
|
autorequire:
|
16
11
|
bindir: bin
|
17
12
|
cert_chain: []
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
13
|
+
date: 2011-10-01 00:00:00.000000000Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rake
|
17
|
+
requirement: &10414280 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.9.2
|
23
|
+
type: :development
|
23
24
|
prerelease: false
|
24
|
-
|
25
|
+
version_requirements: *10414280
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rdoc
|
28
|
+
requirement: &10413780 !ruby/object:Gem::Requirement
|
25
29
|
none: false
|
26
|
-
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 0
|
32
|
-
version: "0"
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.5.8
|
33
34
|
type: :development
|
34
|
-
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *10413780
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rspec
|
39
|
+
requirement: &10413320 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 2.6.0
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *10413320
|
35
48
|
description:
|
36
|
-
email:
|
49
|
+
email:
|
37
50
|
- sheldonh@starjuice.net
|
38
51
|
- rorymckinley@gmail.com
|
39
52
|
executables: []
|
40
|
-
|
41
53
|
extensions: []
|
42
|
-
|
43
54
|
extra_rdoc_files: []
|
44
|
-
|
45
|
-
files:
|
55
|
+
files:
|
46
56
|
- .gitignore
|
47
57
|
- Gemfile
|
48
|
-
- README.
|
58
|
+
- README.rdoc
|
49
59
|
- Rakefile
|
50
60
|
- lib/magic_options.rb
|
51
61
|
- lib/magic_options/version.rb
|
@@ -55,36 +65,29 @@ files:
|
|
55
65
|
- spec/spec_helper.rb
|
56
66
|
homepage: http://github.com/sheldonh/magic_options
|
57
67
|
licenses: []
|
58
|
-
|
59
68
|
post_install_message:
|
60
69
|
rdoc_options: []
|
61
|
-
|
62
|
-
require_paths:
|
70
|
+
require_paths:
|
63
71
|
- lib
|
64
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
73
|
none: false
|
66
|
-
requirements:
|
67
|
-
- -
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
|
70
|
-
|
71
|
-
- 0
|
72
|
-
version: "0"
|
73
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
79
|
none: false
|
75
|
-
requirements:
|
76
|
-
- -
|
77
|
-
- !ruby/object:Gem::Version
|
78
|
-
|
79
|
-
segments:
|
80
|
-
- 0
|
81
|
-
version: "0"
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
82
84
|
requirements: []
|
83
|
-
|
84
85
|
rubyforge_project: magic_options
|
85
|
-
rubygems_version: 1.8.
|
86
|
+
rubygems_version: 1.8.10
|
86
87
|
signing_key:
|
87
88
|
specification_version: 3
|
88
89
|
summary: Ruby module to provide initialize with magic options
|
89
|
-
test_files:
|
90
|
-
|
90
|
+
test_files:
|
91
|
+
- spec/magic_options/class_method_spec.rb
|
92
|
+
- spec/magic_options/instance_method_spec.rb
|
93
|
+
- spec/spec_helper.rb
|
data/README.md
DELETED
@@ -1,118 +0,0 @@
|
|
1
|
-
magic_options
|
2
|
-
-------------
|
3
|
-
|
4
|
-
MagicOptions is a ruby module that provides mechanisms for splatting
|
5
|
-
an options hash into an object's instance variables. Each key is taken
|
6
|
-
as the name of an instance variable, to which the associated value is
|
7
|
-
assigned.
|
8
|
-
|
9
|
-
This is version 1.0.0. It is not backward compatible with previous
|
10
|
-
versions at all. This version will be uploaded to rubygems.org within
|
11
|
-
the next few days.
|
12
|
-
|
13
|
-
Examples
|
14
|
-
--------
|
15
|
-
|
16
|
-
```ruby
|
17
|
-
require 'rubygems'
|
18
|
-
require 'magic_options'
|
19
|
-
|
20
|
-
class Gullible
|
21
|
-
|
22
|
-
include MagicOptions
|
23
|
-
|
24
|
-
magic_initialize
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
Gullible.new :accepts => "anything"
|
29
|
-
=> #<Gullible:0x7f77e407fdb0 @accepts="anything">
|
30
|
-
|
31
|
-
class Cow
|
32
|
-
|
33
|
-
include MagicOptions
|
34
|
-
|
35
|
-
magic_initialize :only => :respond_to?
|
36
|
-
|
37
|
-
attr_accessor :color, :gender
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
Cow.new :color => "brown", :gender => "female"
|
42
|
-
=> #<Cow:0x7f77e409a6d8 @gender="female", @color="brown">
|
43
|
-
Cow.new :color => "brown", :gender => "female", :wheels => 4
|
44
|
-
=> ArgumentError: Unknown option wheels for new Cow
|
45
|
-
|
46
|
-
class Professor
|
47
|
-
|
48
|
-
include MagicOptions
|
49
|
-
|
50
|
-
def initialize(name, options = {})
|
51
|
-
magic_options options, :only => [:iq, :hairstyle]
|
52
|
-
end
|
53
|
-
|
54
|
-
end
|
55
|
-
|
56
|
-
Professor.new :hair_style => :einsteinian
|
57
|
-
=> #<Professor:0x7f77e406d980 @hair_style=:einsteinian>
|
58
|
-
Professor.new :does_not_take => :anything
|
59
|
-
=> ArgumentError: Unknown option does_not_take for new Professor
|
60
|
-
```
|
61
|
-
|
62
|
-
Documentation
|
63
|
-
-------------
|
64
|
-
|
65
|
-
Working code first. For now, here are the specs for the magic_options
|
66
|
-
method:
|
67
|
-
|
68
|
-
```
|
69
|
-
MagicOptions#magic_options(options, config = {})
|
70
|
-
Given class Cow mixes in MagicOptions
|
71
|
-
When Cow#initialize(options) calls magic_options(options)
|
72
|
-
Then Cow.new(:name => 'Daisy', :color => :brown)
|
73
|
-
sets @name to 'Daisy'
|
74
|
-
sets @color to :brown
|
75
|
-
When Cow#initialize(options) calls magic_options(options, :only => [:name, :color])
|
76
|
-
Then Cow.new(:name => 'Daisy', :color => :brown)
|
77
|
-
sets @name to 'Daisy'
|
78
|
-
sets @color to :brown
|
79
|
-
Then Cow.new(:name => 'Daisy', :gender => :female)
|
80
|
-
raises an ArgumentError
|
81
|
-
reports the offending class and the unknown option
|
82
|
-
When Cow#initialize(options) calls magic_options(options, :require => :name)
|
83
|
-
Then Cow.new(:name => 'Daisy', :color => :brown)
|
84
|
-
sets @name to 'Daisy'
|
85
|
-
sets @color to :brown
|
86
|
-
Then Cow.new(:color => :brown)
|
87
|
-
raises an ArgumentError
|
88
|
-
reports the offending class and the missing option
|
89
|
-
When Cow#initialize(options) calls magic_options(options, :only => :color, :require => :name)
|
90
|
-
Then Cow.new(:name => 'Daisy', :color => :brown)
|
91
|
-
sets @name to 'Daisy'
|
92
|
-
sets @color to :brown
|
93
|
-
Then Cow.new(:color => :brown)
|
94
|
-
raises an ArgumentError
|
95
|
-
reports the offending class and the missing option
|
96
|
-
```
|
97
|
-
|
98
|
-
MagicOptions::ClassMethods#magic_initialize(config = {}) creates an
|
99
|
-
initialize method that works like this:
|
100
|
-
|
101
|
-
```ruby
|
102
|
-
def initialize(options = {})
|
103
|
-
magic_options(options, config)
|
104
|
-
end
|
105
|
-
```
|
106
|
-
|
107
|
-
Obtaining
|
108
|
-
---------
|
109
|
-
|
110
|
-
<https://github.com/sheldonh/magic_options>
|
111
|
-
|
112
|
-
Credits
|
113
|
-
-------
|
114
|
-
|
115
|
-
Pair programmed with [@rorymckinley][c1]
|
116
|
-
|
117
|
-
[c1]: http://twitter.com/#!/rorymckinley
|
118
|
-
|