spiceinit 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/LICENSE +20 -0
- data/README.rdoc +220 -0
- data/Rakefile +16 -0
- data/examples/inspice.rb +80 -0
- data/examples/modspice.rb +76 -0
- data/lib/spice_init.rb +1 -0
- data/lib/spiceinit/extend.rb +9 -0
- data/lib/spiceinit/extract_options.rb +36 -0
- data/lib/spiceinit/instance.rb +52 -0
- data/lib/spiceinit/module.rb +53 -0
- data/lib/spiceinit/version.rb +3 -0
- data/lib/spiceinit.rb +4 -0
- data/spec/insinit_spec.rb +58 -0
- data/spec/modinit_spec.rb +42 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/spiced/instance.rb +82 -0
- data/spec/spiced/module.rb +23 -0
- data/spiceinit.gemspec +27 -0
- metadata +108 -0
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Luciano Altube
|
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.rdoc
ADDED
@@ -0,0 +1,220 @@
|
|
1
|
+
=SpiceInit
|
2
|
+
Sometimes I want a simple way of initializing an object or setting class/module methods from a hash.
|
3
|
+
|
4
|
+
==Instances
|
5
|
+
With <tt>SpiceInit</tt> to initialize an instance of some class you can use <tt>inspice</tt> instead of <tt>new</tt>
|
6
|
+
|
7
|
+
For example:
|
8
|
+
|
9
|
+
class Person;end
|
10
|
+
|
11
|
+
person = Person.inspice(:name => "Lucky", :last_name => "Luke", :is_cool? => true)
|
12
|
+
p person
|
13
|
+
# => #<Person:0xb93c @name="Lucky", @last_name="Luke", @is_cool=true>
|
14
|
+
p person.name
|
15
|
+
# => "Lucky"
|
16
|
+
p person.last_name
|
17
|
+
# => "Luke"
|
18
|
+
p person.is_cool?
|
19
|
+
# => true
|
20
|
+
|
21
|
+
If you want to track the spices added without going through <tt>methods</tt> you can pass <tt>true</tt> to the <tt>:track_spices</tt> option.
|
22
|
+
person = Person.inspice(:name => "Lucky", :last_name => "Luke",
|
23
|
+
:is_cool? => true, :track_spices => true)
|
24
|
+
p person.spices_added
|
25
|
+
# => ["is_cool?", "is_cool=", "last_name=", "name", "name=", "last_name"]
|
26
|
+
|
27
|
+
You can also have some atributtes defined already so if a block is given the new object will be in scope.
|
28
|
+
class Person
|
29
|
+
attr_accessor :smokes
|
30
|
+
end
|
31
|
+
|
32
|
+
person = Person.inspice(:name => "Lucky", :last_name => "Luke", :is_cool? => true) do |ll|
|
33
|
+
ll.smokes = 'cigarettes'
|
34
|
+
end
|
35
|
+
|
36
|
+
p person
|
37
|
+
# => #<Person:0x9eac @is_cool=true, @smokes="cigarettes", @name="Lucky", @last_name="Luke">
|
38
|
+
p person.smokes
|
39
|
+
# => "cigarettes"
|
40
|
+
person.smokes = 'cigars'
|
41
|
+
p person.smokes
|
42
|
+
# => "cigars"
|
43
|
+
|
44
|
+
You can also have an <tt>initialize</tt> method with required arguments. In that case, you should provide them before the hash.
|
45
|
+
class Person
|
46
|
+
attr_accessor :smokes, :kind
|
47
|
+
def initialize(kind)
|
48
|
+
@kind = kind
|
49
|
+
|
50
|
+
# this will not run if you passed a block to :inspace
|
51
|
+
if block_given?
|
52
|
+
yield(self)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
person = Person.inspice('comic',:name => "Lucky", :last_name => "Luke", :is_cool? => true) do |ll|
|
58
|
+
ll.smokes = 'cigarettes'
|
59
|
+
end
|
60
|
+
|
61
|
+
p person
|
62
|
+
# => <Person:0x9128 @kind="comic", @smokes="cigarettes", @name="Lucky", @last_name="Luke", @is_cool=true>
|
63
|
+
Note: <tt>initialize</tt> is called before the block (if given to <tt>inspice</tt>) so block variable assignments will override any other assignment you are doing at <tt>initialize</tt>.
|
64
|
+
class Person
|
65
|
+
attr_accessor :smokes, :kind
|
66
|
+
def initialize(kind=nil)
|
67
|
+
@kind = kind
|
68
|
+
@smokes = 'cigars'
|
69
|
+
# this will not run if you passed a block to :inspace
|
70
|
+
if block_given?
|
71
|
+
yield(self)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
person = Person.inspice('drama',:name => "Lucky", :last_name => "Luke", :is_cool? => true) do |ll|
|
77
|
+
ll.smokes = 'cigarettes'
|
78
|
+
ll.kind = 'comic'
|
79
|
+
end
|
80
|
+
|
81
|
+
p person
|
82
|
+
# => #<Person:0xb4dc @last_name="Luke", @name="Lucky", @is_cool=true, @smokes="cigarettes", @kind="comic">
|
83
|
+
|
84
|
+
person = Person.inspice('comic',:name => "Lucky", :last_name => "Luke", :is_cool? => true)
|
85
|
+
|
86
|
+
p person
|
87
|
+
# => #<Person:0xad5c @last_name="Luke", @name="Lucky", @is_cool=true, @smokes="cigars", @kind="comic">
|
88
|
+
|
89
|
+
Sure, you can still instantiate with <tt>new</tt>
|
90
|
+
person = Person.new('friendly') do |f|
|
91
|
+
f.smokes = false
|
92
|
+
end
|
93
|
+
|
94
|
+
p person.kind
|
95
|
+
# => "friendly"
|
96
|
+
p person.smokes
|
97
|
+
# => false
|
98
|
+
p person
|
99
|
+
# => #<Person:0x88e0 @smokes=false, @kind="friendly">
|
100
|
+
|
101
|
+
When you pass a <tt>proc</tt> as a value you must call the key method as a <tt>proc</tt> also.
|
102
|
+
person = Person.inspice('comic',:name => "Lucky", :last_name => "Luke",
|
103
|
+
:says => Proc.new {|obj,str| "#{obj.name} says #{str}"})
|
104
|
+
|
105
|
+
p person.says[person,'hi there'] # or person.says.call(person,'hi there')
|
106
|
+
# => "Lucky says hi there"
|
107
|
+
|
108
|
+
Another way of using <tt>inspice</tt> is with factory methods.
|
109
|
+
class Person
|
110
|
+
def self.new
|
111
|
+
inspice :name => 'Tintin'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
person = Person.new
|
116
|
+
p person
|
117
|
+
# => #<Person:0xb374 @name="Tintin">
|
118
|
+
p person.name
|
119
|
+
# => "Tintin"
|
120
|
+
person.name = 'Lucky'
|
121
|
+
p person.name
|
122
|
+
# => "Lucky"
|
123
|
+
p person
|
124
|
+
# => #<Person:0xb374 @name="Lucky">
|
125
|
+
person = Person.new do |c|
|
126
|
+
person.name = 'Tintin'
|
127
|
+
end
|
128
|
+
p person
|
129
|
+
# => #<Person:0xb180 @name="Tintin">
|
130
|
+
p person.name
|
131
|
+
# => "Tintin"
|
132
|
+
person.name = 'Lucky'
|
133
|
+
p person
|
134
|
+
#<Person:0xb180 @name="Lucky">
|
135
|
+
p person.name
|
136
|
+
# => "Lucky"
|
137
|
+
|
138
|
+
==Modules and Classes
|
139
|
+
For Clasess and Modules you can use <tt>claspice</tt> or <tt>clasinit</tt> and <tt>modspice</tt> (they are method aliases for <tt>modinit</tt>) and
|
140
|
+
the usage is simillar to <tt>inspice</tt> but keyes are defined as class methods and values as class variables.
|
141
|
+
|
142
|
+
module LCD
|
143
|
+
modspice :core_image => "Hardware Accelerated", :main_display => true,
|
144
|
+
:mirror => "off", :online => true
|
145
|
+
|
146
|
+
class Display
|
147
|
+
claspice :resolution => "1440x960", :colors => "Millions", :brightness => 50,
|
148
|
+
:auto_adjust => true, :show_in_menu => true, :refresh_rate => "n/a"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
p LCD.core_image
|
153
|
+
# => "Hardware Accelerated"
|
154
|
+
p LCD.main_display
|
155
|
+
# => true
|
156
|
+
p LCD.mirror
|
157
|
+
# => "off"
|
158
|
+
p LCD.online
|
159
|
+
# => true
|
160
|
+
p LCD.class_variables
|
161
|
+
# => ["@@mirror", "@@online", "@@main_display", "@@core_image"]
|
162
|
+
p LCD::Display.resolution
|
163
|
+
# => "1440x960"
|
164
|
+
p LCD::Display.colors
|
165
|
+
# => "Millions"
|
166
|
+
p LCD::Display.brightness
|
167
|
+
# => 50
|
168
|
+
p LCD::Display.auto_adjust
|
169
|
+
# => true
|
170
|
+
p LCD::Display.show_in_menu
|
171
|
+
# => true
|
172
|
+
p LCD::Display.refresh_rate
|
173
|
+
# => "n/a"
|
174
|
+
p LCD::Display.class_variables
|
175
|
+
# => ["@@brightness", "@@refresh_rate", "@@show_in_menu", "@@colors", "@@auto_adjust", "@@resolution"]
|
176
|
+
|
177
|
+
module LCD
|
178
|
+
modspice :core_image => "Hardware Accelerated", :main_display => true,
|
179
|
+
:mirror => "off", :online => true, :track_spices => true
|
180
|
+
|
181
|
+
class Display
|
182
|
+
claspice :resolution => "1440x960", :colors => "Millions", :brightness => 50,
|
183
|
+
:auto_adjust => true, :show_in_menu => true, :refresh_rate => "n/a",
|
184
|
+
:track_spices => true
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
p LCD.spices_added
|
189
|
+
# => ["online=", "online", "core_image=", "core_image", "main_display=", "main_display", "mirror=", "mirror"]
|
190
|
+
p LCD::Display.spices_added
|
191
|
+
# => ["brightness=", "brightness", "auto_adjust=", "auto_adjust", "show_in_menu=", "show_in_menu",
|
192
|
+
# "refresh_rate=", "refresh_rate", "resolution=", "resolution", "colors=", "colors"]
|
193
|
+
|
194
|
+
# can also be inline
|
195
|
+
M = Module.new
|
196
|
+
M.modspice :core_image => "Hardware Accelerated", :main_display => true,
|
197
|
+
:mirror => "off", :online => true,
|
198
|
+
:track_spices => true
|
199
|
+
|
200
|
+
p M.spices_added
|
201
|
+
# => ["online=", "online", "core_image=", "core_image", "main_display=", "main_display", "mirror=", "mirror"]
|
202
|
+
p M.class_variables
|
203
|
+
# => ["@@main_display", "@@spices_added", "@@core_image", "@@mirror", "@@online"]
|
204
|
+
|
205
|
+
With clasess and modules key methods with <tt>proc</tt> values are defined with optional arguments making the method call more natural.
|
206
|
+
module Tiempo
|
207
|
+
FORMATS = {:short => "%m/%d/%y", :long => "%A, %B %d, %Y"}
|
208
|
+
modspice :fecha => Proc.new {|time,key| time.strftime(FORMATS[key.to_sym])},
|
209
|
+
:ahora => Proc.new {Time.now}
|
210
|
+
end
|
211
|
+
|
212
|
+
p Tiempo.fecha(Time.now,:short)
|
213
|
+
# => "11/14/10"
|
214
|
+
p Tiempo.fecha(Time.now,:long)
|
215
|
+
# => "Sunday, November 14, 2010"
|
216
|
+
p Tiempo.ahora
|
217
|
+
# => Sun Nov 14 02:56:19 -0200 2010
|
218
|
+
|
219
|
+
==License
|
220
|
+
Read LICENSE
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require File.expand_path("../lib/spiceinit/version", __FILE__)
|
3
|
+
|
4
|
+
require 'spec/rake/spectask'
|
5
|
+
Spec::Rake::SpecTask.new(:specs) do |t|
|
6
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
7
|
+
t.spec_opts = ["--colour","--format nested"]
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'rake/rdoctask'
|
11
|
+
Rake::RDocTask.new do |rdoc|
|
12
|
+
rdoc.rdoc_dir = 'rdoc'
|
13
|
+
rdoc.title = "SpiceInit #{SpiceInit::VERSION}"
|
14
|
+
rdoc.rdoc_files.include('README*')
|
15
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
16
|
+
end
|
data/examples/inspice.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spice_init'
|
3
|
+
|
4
|
+
class Person;end
|
5
|
+
|
6
|
+
person = Person.inspice(:name => "Lucky", :last_name => "Luke", :is_cool? => true)
|
7
|
+
p person
|
8
|
+
# => #<Person:0xb93c @name="Lucky", @last_name="Luke", @is_cool=true>
|
9
|
+
p person.name
|
10
|
+
# => "Lucky"
|
11
|
+
p person.last_name
|
12
|
+
# => "Luke"
|
13
|
+
p person.is_cool?
|
14
|
+
# => true
|
15
|
+
|
16
|
+
person = Person.inspice(:name => "Lucky", :last_name => "Luke",
|
17
|
+
:is_cool? => true, :track_spices => true)
|
18
|
+
p person.spices_added
|
19
|
+
# => ["is_cool?", "is_cool=", "last_name=", "name", "name=", "last_name"]
|
20
|
+
|
21
|
+
class Person
|
22
|
+
attr_accessor :smokes
|
23
|
+
end
|
24
|
+
|
25
|
+
person = Person.inspice(:name => "Lucky", :last_name => "Luke", :is_cool? => true) do |ll|
|
26
|
+
ll.smokes = 'cigarettes'
|
27
|
+
end
|
28
|
+
|
29
|
+
p person
|
30
|
+
# => #<Person:0x9eac @is_cool=true, @smokes="cigarettes", @name="Lucky", @last_name="Luke">
|
31
|
+
p person.smokes
|
32
|
+
# => "cigarettes"
|
33
|
+
person.smokes = 'cigars'
|
34
|
+
p person.smokes
|
35
|
+
# => "cigars"
|
36
|
+
|
37
|
+
class Person
|
38
|
+
attr_accessor :smokes, :kind
|
39
|
+
def initialize(kind)
|
40
|
+
@kind = kind
|
41
|
+
if block_given?
|
42
|
+
yield(self)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
person = Person.inspice('comic',:name => "Lucky", :last_name => "Luke", :is_cool? => true) do |ll|
|
48
|
+
ll.smokes = 'cigarettes'
|
49
|
+
end
|
50
|
+
|
51
|
+
p person
|
52
|
+
# => <Person:0x9128 @kind="comic", @smokes="cigarettes", @name="Lucky", @last_name="Luke", @is_cool=true>
|
53
|
+
|
54
|
+
person = Person.inspice('drama',:name => "Lucky", :last_name => "Luke", :is_cool? => true) do |ll|
|
55
|
+
ll.smokes = 'cigarettes'
|
56
|
+
ll.kind = 'comic'
|
57
|
+
end
|
58
|
+
|
59
|
+
p person
|
60
|
+
# => #<Person:0xb4dc @last_name="Luke", @name="Lucky", @is_cool=true, @smokes="cigarettes", @kind="comic">
|
61
|
+
|
62
|
+
person = Person.inspice('comic',:name => "Lucky", :last_name => "Luke", :is_cool? => true)
|
63
|
+
|
64
|
+
p person
|
65
|
+
# => #<Person:0xad5c @last_name="Luke", @name="Lucky", @is_cool=true, @smokes="cigars", @kind="comic">
|
66
|
+
|
67
|
+
person = Person.new('friendly') do |f|
|
68
|
+
f.smokes = false
|
69
|
+
end
|
70
|
+
|
71
|
+
p person.kind
|
72
|
+
# => "friendly"
|
73
|
+
p person.smokes
|
74
|
+
# => false
|
75
|
+
p person
|
76
|
+
# => #<Person:0x88e0 @smokes=false, @kind="friendly">
|
77
|
+
|
78
|
+
person = Person.inspice('comic',:name => "Lucky", :last_name => "Luke", :says => Proc.new {|obj,str| "#{obj.name} says #{str}"})
|
79
|
+
p person.says[person,'hi there']
|
80
|
+
# => "Lucky says hi there"
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spice_init'
|
3
|
+
|
4
|
+
module LCD
|
5
|
+
modspice :core_image => "Hardware Accelerated", :main_display => true,
|
6
|
+
:mirror => "off", :online => true
|
7
|
+
|
8
|
+
class Display
|
9
|
+
claspice :resolution => "1440x960", :colors => "Millions", :brightness => 50,
|
10
|
+
:auto_adjust => true, :show_in_menu => true, :refresh_rate => "n/a"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
p LCD.core_image
|
15
|
+
# => "Hardware Accelerated"
|
16
|
+
p LCD.main_display
|
17
|
+
# => true
|
18
|
+
p LCD.mirror
|
19
|
+
# => "off"
|
20
|
+
p LCD.online
|
21
|
+
# => true
|
22
|
+
p LCD.class_variables
|
23
|
+
# => ["@@mirror", "@@online", "@@main_display", "@@core_image"]
|
24
|
+
p LCD::Display.resolution
|
25
|
+
# => "1440x960"
|
26
|
+
p LCD::Display.colors
|
27
|
+
# => "Millions"
|
28
|
+
p LCD::Display.brightness
|
29
|
+
# => 50
|
30
|
+
p LCD::Display.auto_adjust
|
31
|
+
# => true
|
32
|
+
p LCD::Display.show_in_menu
|
33
|
+
# => true
|
34
|
+
p LCD::Display.refresh_rate
|
35
|
+
# => "n/a"
|
36
|
+
p LCD::Display.class_variables
|
37
|
+
# => ["@@brightness", "@@refresh_rate", "@@show_in_menu", "@@colors", "@@auto_adjust", "@@resolution"]
|
38
|
+
|
39
|
+
module LCD
|
40
|
+
modspice :core_image => "Hardware Accelerated", :main_display => true,
|
41
|
+
:mirror => "off", :online => true, :track_spices => true
|
42
|
+
|
43
|
+
class Display
|
44
|
+
claspice :resolution => "1440x960", :colors => "Millions", :brightness => 50,
|
45
|
+
:auto_adjust => true, :show_in_menu => true, :refresh_rate => "n/a",
|
46
|
+
:track_spices => true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
p LCD.spices_added
|
51
|
+
# => ["online=", "online", "core_image=", "core_image", "main_display=", "main_display", "mirror=", "mirror"]
|
52
|
+
p LCD::Display.spices_added
|
53
|
+
# => ["brightness=", "brightness", "auto_adjust=", "auto_adjust", "show_in_menu=", "show_in_menu",
|
54
|
+
# "refresh_rate=", "refresh_rate", "resolution=", "resolution", "colors=", "colors"]
|
55
|
+
|
56
|
+
M = Module.new
|
57
|
+
M.modspice :core_image => "Hardware Accelerated", :main_display => true,
|
58
|
+
:mirror => "off", :online => true,
|
59
|
+
:track_spices => true
|
60
|
+
p M.spices_added
|
61
|
+
# => ["online=", "online", "core_image=", "core_image", "main_display=", "main_display", "mirror=", "mirror"]
|
62
|
+
p M.class_variables
|
63
|
+
# => ["@@main_display", "@@spices_added", "@@core_image", "@@mirror", "@@online"]
|
64
|
+
|
65
|
+
module Tiempo
|
66
|
+
FORMATS = {:short => "%m/%d/%y", :long => "%A, %B %d, %Y"}
|
67
|
+
modspice :fecha => Proc.new {|time,key| time.strftime(FORMATS[key.to_sym])},
|
68
|
+
:ahora => Proc.new {Time.now}
|
69
|
+
end
|
70
|
+
|
71
|
+
p Tiempo.fecha(Time.now,:short)
|
72
|
+
# => "11/14/10"
|
73
|
+
p Tiempo.fecha(Time.now,:long)
|
74
|
+
# => "Sunday, November 14, 2010"
|
75
|
+
p Tiempo.ahora
|
76
|
+
# => Sun Nov 14 02:56:19 -0200 2010
|
data/lib/spice_init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "spiceinit"
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Do nothing if ActiveSupport is present.
|
2
|
+
unless defined?(ActiveSupport)
|
3
|
+
|
4
|
+
# ActiveSupport is not loaded.
|
5
|
+
# However, we still need <tt>extract_options!</tt>
|
6
|
+
#
|
7
|
+
class Hash
|
8
|
+
# By default, only instances of Hash itself are extractable.
|
9
|
+
# Subclasses of Hash may implement this method and return
|
10
|
+
# true to declare themselves as extractable. If a Hash
|
11
|
+
# is extractable, Array#extract_options! pops it from
|
12
|
+
# the Array when it is the last element of the Array.
|
13
|
+
def extractable_options?
|
14
|
+
instance_of?(Hash)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Array
|
19
|
+
# Extracts options from a set of arguments. Removes and returns the last
|
20
|
+
# element in the array if it's a hash, otherwise returns a blank hash.
|
21
|
+
#
|
22
|
+
# def options(*args)
|
23
|
+
# args.extract_options!
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# options(1, 2) # => {}
|
27
|
+
# options(1, 2, :a => :b) # => {:a=>:b}
|
28
|
+
def extract_options!
|
29
|
+
if last.is_a?(Hash) && last.extractable_options?
|
30
|
+
pop
|
31
|
+
else
|
32
|
+
{}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module SpiceInit
|
2
|
+
module Instance
|
3
|
+
def insinit(*args,&block)
|
4
|
+
|
5
|
+
object, options = allocate, args.extract_options!
|
6
|
+
track_spices = options.has_key?(:track_spices) ? options.delete(:track_spices) : false
|
7
|
+
|
8
|
+
# create an anonymous Module with features from options
|
9
|
+
features = ::Module.new do
|
10
|
+
options.each do |key,value|
|
11
|
+
match = key.to_s.match(/([\!\?]$)/)
|
12
|
+
if match
|
13
|
+
|
14
|
+
setter = var = match.pre_match
|
15
|
+
getter = setter + match[1]
|
16
|
+
|
17
|
+
define_method("#{getter}") do
|
18
|
+
instance_variable_get("@#{var}")
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_writer setter
|
22
|
+
object.instance_variable_set("@#{var}", value)
|
23
|
+
|
24
|
+
else
|
25
|
+
|
26
|
+
attr_accessor key
|
27
|
+
object.instance_variable_set("@#{key}", value)
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
define_method("spices_added") do
|
32
|
+
features.instance_methods.reject { |f| f =~ /spices_added/ }
|
33
|
+
end if track_spices
|
34
|
+
end
|
35
|
+
|
36
|
+
# extend object with features
|
37
|
+
object.extend(features)
|
38
|
+
|
39
|
+
# if there are some args make a call to initialize
|
40
|
+
# block is set to nil to avoid calling it twice on initialize
|
41
|
+
object.send(:initialize, *args, &block=nil)
|
42
|
+
|
43
|
+
# if a block is given then pass the object for more processing
|
44
|
+
yield(object) if block_given?
|
45
|
+
|
46
|
+
# return the final object
|
47
|
+
object
|
48
|
+
end
|
49
|
+
|
50
|
+
alias_method :inspice, :insinit
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module SpiceInit
|
2
|
+
module Module
|
3
|
+
def modinit(attributes={})
|
4
|
+
raise TypeError unless self.is_a?(Module)
|
5
|
+
|
6
|
+
track_spices = attributes.has_key?(:track_spices) ? attributes.delete(:track_spices) : false
|
7
|
+
|
8
|
+
if track_spices
|
9
|
+
class_variable_set("@@spices_added",[])
|
10
|
+
end
|
11
|
+
|
12
|
+
attributes.each do |key,value|
|
13
|
+
|
14
|
+
match = key.to_s.match(/([\!\?]$)/)
|
15
|
+
if match
|
16
|
+
setter = var = match.pre_match
|
17
|
+
getter = setter + match[1]
|
18
|
+
else
|
19
|
+
setter = getter = var = key
|
20
|
+
end
|
21
|
+
class_variable_set("@@#{var}",value)
|
22
|
+
module_eval %Q{
|
23
|
+
|
24
|
+
def self.#{getter}(*args)
|
25
|
+
if @@#{var}.is_a?(Proc)
|
26
|
+
@@#{var}.call(*args)
|
27
|
+
else
|
28
|
+
@@#{var}
|
29
|
+
end
|
30
|
+
rescue
|
31
|
+
raise ArgumentError
|
32
|
+
caller
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.#{setter}=(value)
|
36
|
+
@@#{var} = value
|
37
|
+
end
|
38
|
+
}
|
39
|
+
if track_spices
|
40
|
+
module_eval %Q{
|
41
|
+
def self.spices_added
|
42
|
+
@@spices_added
|
43
|
+
end
|
44
|
+
} unless respond_to?(:spices_added)
|
45
|
+
spices_added << "#{setter}=" << "#{getter}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
alias_method :clasinit, :modinit
|
50
|
+
alias_method :modspice, :modinit
|
51
|
+
alias_method :claspice, :modinit
|
52
|
+
end
|
53
|
+
end
|
data/lib/spiceinit.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
include Spiced::Instance
|
3
|
+
|
4
|
+
describe SpiceInit::Instance do
|
5
|
+
context "#insinit" do
|
6
|
+
it "defines inspice instance variables respecting the ones at initialize" do
|
7
|
+
person = Person.inspice(:name => "Lucky", :last_name => "Luke")
|
8
|
+
person.instance_variables.should include("@kind","@last_name","@name")
|
9
|
+
end
|
10
|
+
it "defines attribute readers" do
|
11
|
+
person = Person.inspice(:name => "Lucky", :last_name => "Luke")
|
12
|
+
[person.name,person.last_name].should include('Lucky','Luke')
|
13
|
+
end
|
14
|
+
it "defines attribute writers" do
|
15
|
+
person = Person.inspice(:name => "Lucky", :last_name => "Luke")
|
16
|
+
person.name = "Rey"
|
17
|
+
person.last_name = "Tintin"
|
18
|
+
[person.name,person.last_name].should include("Rey","Tintin")
|
19
|
+
end
|
20
|
+
it "defines accessors for keys ending with (! or ?)" do
|
21
|
+
person = Person.inspice(:cool? => true, :friendly? => true)
|
22
|
+
[person.cool?,person.friendly?].should include(true,true)
|
23
|
+
person.cool = false
|
24
|
+
person.friendly = false
|
25
|
+
[person.cool?,person.friendly?].should include(false,false)
|
26
|
+
end
|
27
|
+
it "can take a block which prevents any block at initialize from running" do
|
28
|
+
person = Person.inspice(:cool? => true, :friendly? => true) do |p|
|
29
|
+
p.smokes = false
|
30
|
+
p.kind = 'healthy'
|
31
|
+
end
|
32
|
+
[person.smokes,person.kind].should include(false,'healthy')
|
33
|
+
end
|
34
|
+
it "can set initialize arguments that could be expected at initialize" do
|
35
|
+
person = Person.inspice('friend')
|
36
|
+
person.kind.should be_eql('friend')
|
37
|
+
end
|
38
|
+
it "can set any attribute declared inside the class through the block" do
|
39
|
+
person = Person.inspice() do |p|
|
40
|
+
p.kind = 'comic'
|
41
|
+
p.smokes = false
|
42
|
+
end
|
43
|
+
[person.kind,person.smokes].should include(false,'comic')
|
44
|
+
end
|
45
|
+
it "can take a proc as a key value" do
|
46
|
+
person = Person.inspice(:says => Proc.new {|s| s})
|
47
|
+
person.says['hi!'].should be_eql('hi!')
|
48
|
+
end
|
49
|
+
it "can track spices added by passing :track_spices => true" do
|
50
|
+
person = Person.inspice(:track_spices => true, :cool? => true, :friendly? => true)
|
51
|
+
person.spices_added.should include("friendly?", "friendly=", "cool?", "cool=")
|
52
|
+
end
|
53
|
+
it "modules cannot use inspice" do
|
54
|
+
m = Module.new
|
55
|
+
lambda {m.inspice(:foo => 'bar')}.should raise_exception(NoMethodError)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
include Spiced::Module
|
3
|
+
|
4
|
+
describe SpiceInit::Module do
|
5
|
+
before(:each) do
|
6
|
+
@LCD = ::Module.new
|
7
|
+
@Tiempo = ::Module.new
|
8
|
+
end
|
9
|
+
context "#modinit" do
|
10
|
+
it "defines class variables for each key" do
|
11
|
+
@LCD.modspice LCD1
|
12
|
+
@LCD.class_variables.should include(*LCD1_CVARS)
|
13
|
+
end
|
14
|
+
it "defines class attribute readers" do
|
15
|
+
@LCD.modspice LCD1
|
16
|
+
LCD1.each do |k,v|
|
17
|
+
@LCD.send(k).should be_eql(v)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
it "defines class attribute writers" do
|
21
|
+
@LCD.modspice LCD1
|
22
|
+
writers = LCD1.keys.map {|k|(k.to_s.gsub(/\?/,'') << '=').to_sym}
|
23
|
+
writers.each {|w| @LCD.send w,'changed'}
|
24
|
+
LCD1.keys.each do |k|
|
25
|
+
@LCD.send(k).should be_eql('changed')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
it "can track spices added by passing :track_spices => true" do
|
29
|
+
@LCD.modspice LCD2
|
30
|
+
@LCD.spices_added.should include(*LCD2_SPICES)
|
31
|
+
end
|
32
|
+
it "key methods with proc values are called as methods" do
|
33
|
+
@Tiempo.modspice TSPICES
|
34
|
+
@Tiempo.ahora.should be_kind_of(Time)
|
35
|
+
end
|
36
|
+
it "key methods with proc values can take expected arguments" do
|
37
|
+
now = Time.now
|
38
|
+
@Tiempo.modspice TSPICES
|
39
|
+
@Tiempo.fecha(now,:short).should be_eql(now.strftime(FORMATS[:short]))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
5
|
+
# $LOAD_PATH.unshift(File.dirname(__FILE__))
|
6
|
+
|
7
|
+
require 'spiceinit'
|
8
|
+
|
9
|
+
module Spiced
|
10
|
+
autoload :Module, 'spiced/module'
|
11
|
+
autoload :Instance, 'spiced/instance'
|
12
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Spiced
|
2
|
+
module Instance
|
3
|
+
class Person
|
4
|
+
attr_accessor :smokes, :kind
|
5
|
+
def initialize(kind=nil)
|
6
|
+
@kind = kind
|
7
|
+
if block_given?
|
8
|
+
yield(self)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
#
|
13
|
+
# person = Person.inspice('comic',:name => "Lucky", :last_name => "Luke", :is_cool? => true) do |ll|
|
14
|
+
# ll.smokes = 'cigarettes'
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# p person
|
18
|
+
# => <Person:0x9128 @kind="comic", @smokes="cigarettes", @name="Lucky", @last_name="Luke", @is_cool=true>
|
19
|
+
#
|
20
|
+
# person = Person.inspice('drama',:name => "Lucky", :last_name => "Luke", :is_cool? => true) do |ll|
|
21
|
+
# ll.smokes = 'cigarettes'
|
22
|
+
# ll.kind = 'comic'
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# p person
|
26
|
+
# => #<Person:0xb4dc @last_name="Luke", @name="Lucky", @is_cool=true, @smokes="cigarettes", @kind="comic">
|
27
|
+
#
|
28
|
+
# person = Person.inspice('comic',:name => "Lucky", :last_name => "Luke", :is_cool? => true)
|
29
|
+
#
|
30
|
+
# p person
|
31
|
+
# => #<Person:0xad5c @last_name="Luke", @name="Lucky", @is_cool=true, @smokes="cigars", @kind="comic">
|
32
|
+
#
|
33
|
+
# person = Person.new('friendly') do |f|
|
34
|
+
# f.smokes = false
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# p person.kind
|
38
|
+
# => "friendly"
|
39
|
+
# p person.smokes
|
40
|
+
# => false
|
41
|
+
# p person
|
42
|
+
# => #<Person:0x88e0 @smokes=false, @kind="friendly">
|
43
|
+
#
|
44
|
+
# person = Person.inspice('comic',:name => "Lucky", :last_name => "Luke", :says => Proc.new {|obj,str| "#{obj.name} says #{str}"})
|
45
|
+
# p person.says[person,'hi there']
|
46
|
+
# => "Lucky says hi there"
|
47
|
+
#
|
48
|
+
# class Person;end
|
49
|
+
#
|
50
|
+
# person = Person.inspice(:name => "Lucky", :last_name => "Luke", :is_cool? => true)
|
51
|
+
# p person
|
52
|
+
# => #<Person:0xb93c @name="Lucky", @last_name="Luke", @is_cool=true>
|
53
|
+
# p person.name
|
54
|
+
# => "Lucky"
|
55
|
+
# p person.last_name
|
56
|
+
# => "Luke"
|
57
|
+
# p person.is_cool?
|
58
|
+
# => true
|
59
|
+
#
|
60
|
+
# person = Person.inspice(:name => "Lucky", :last_name => "Luke",
|
61
|
+
# :is_cool? => true, :track_spices => true)
|
62
|
+
# p person.spices_added
|
63
|
+
# => ["is_cool?", "is_cool=", "last_name=", "name", "name=", "last_name"]
|
64
|
+
#
|
65
|
+
# class Person
|
66
|
+
# attr_accessor :smokes
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# person = Person.inspice(:name => "Lucky", :last_name => "Luke", :is_cool? => true) do |ll|
|
70
|
+
# ll.smokes = 'cigarettes'
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# p person
|
74
|
+
# => #<Person:0x9eac @is_cool=true, @smokes="cigarettes", @name="Lucky", @last_name="Luke">
|
75
|
+
# p person.smokes
|
76
|
+
# => "cigarettes"
|
77
|
+
# person.smokes = 'cigars'
|
78
|
+
# p person.smokes
|
79
|
+
# => "cigars"
|
80
|
+
#
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Spiced
|
2
|
+
module Module
|
3
|
+
LCD1 = {:core_image => "Hardware Accelerated", :main_display? => true,
|
4
|
+
:mirror => "off", :online => true}
|
5
|
+
LCD1_CVARS = LCD1.keys.map {|k| "@@#{k}".gsub(/\?$/,'')}
|
6
|
+
|
7
|
+
LCD2 = LCD1.merge(:track_spices => true)
|
8
|
+
LCD2_CVARS = LCD2.keys.map {|k| "@@#{k}"}
|
9
|
+
LCD2_SPICES = LCD1.keys.map {|k| k.to_s} + LCD1.keys.map {|k|(k.to_s.gsub(/\?/,'') << '=')}
|
10
|
+
|
11
|
+
# DISPLAY1 = {:resolution => "1440x960", :colors => "Millions", :brightness => 50,
|
12
|
+
# :auto_adjust => true, :show_in_menu => true, :refresh_rate => "n/a"}
|
13
|
+
# DISPLAY1_CVARS = DISPLAY1.keys.map {|k| "@@#{k}"}
|
14
|
+
#
|
15
|
+
# DISPLAY2 = DISPLAY1.merge(:track_spices => true)
|
16
|
+
# DISPLAY2_CVARS = DISPLAY2.keys.map {|k| "@@#{k}"}
|
17
|
+
|
18
|
+
FORMATS = {:short => "%m/%d/%y", :long => "%A, %B %d, %Y"}
|
19
|
+
|
20
|
+
TSPICES = {:fecha => Proc.new {|time,key| time.strftime(FORMATS[key.to_sym])},
|
21
|
+
:ahora => Proc.new {Time.now}}
|
22
|
+
end
|
23
|
+
end
|
data/spiceinit.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path("../lib/spiceinit/version", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "spiceinit"
|
6
|
+
s.version = SpiceInit::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ['Luciano Altube']
|
9
|
+
s.email = ['55elements@gmail.com']
|
10
|
+
s.homepage = "https://github.com/djtek/spiceinit"
|
11
|
+
s.summary = "With spiceinit you can initialize with extra methods and/or add class methods from a hash."
|
12
|
+
s.description = "spiceinit - add spices to your rubies"
|
13
|
+
|
14
|
+
s.required_rubygems_version = ">= 1.3.6"
|
15
|
+
# s.rubyforge_project = "spiceinit"
|
16
|
+
|
17
|
+
s.add_development_dependency "rspec", "~> 1.3"
|
18
|
+
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
21
|
+
s.require_path = 'lib'
|
22
|
+
|
23
|
+
s.extra_rdoc_files = ["LICENSE", "README.rdoc"]
|
24
|
+
s.rdoc_options = ['--title', 'spiceinit: add spices to your rubies',
|
25
|
+
'--main', 'README.rdoc', '--line-numbers', '--inline-source']
|
26
|
+
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: spiceinit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Luciano Altube
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-11-15 00:00:00 -02:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 9
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 3
|
33
|
+
version: "1.3"
|
34
|
+
type: :development
|
35
|
+
version_requirements: *id001
|
36
|
+
description: spiceinit - add spices to your rubies
|
37
|
+
email:
|
38
|
+
- 55elements@gmail.com
|
39
|
+
executables: []
|
40
|
+
|
41
|
+
extensions: []
|
42
|
+
|
43
|
+
extra_rdoc_files:
|
44
|
+
- LICENSE
|
45
|
+
- README.rdoc
|
46
|
+
files:
|
47
|
+
- .gitignore
|
48
|
+
- LICENSE
|
49
|
+
- README.rdoc
|
50
|
+
- Rakefile
|
51
|
+
- examples/inspice.rb
|
52
|
+
- examples/modspice.rb
|
53
|
+
- lib/spice_init.rb
|
54
|
+
- lib/spiceinit.rb
|
55
|
+
- lib/spiceinit/extend.rb
|
56
|
+
- lib/spiceinit/extract_options.rb
|
57
|
+
- lib/spiceinit/instance.rb
|
58
|
+
- lib/spiceinit/module.rb
|
59
|
+
- lib/spiceinit/version.rb
|
60
|
+
- spec/insinit_spec.rb
|
61
|
+
- spec/modinit_spec.rb
|
62
|
+
- spec/spec_helper.rb
|
63
|
+
- spec/spiced/instance.rb
|
64
|
+
- spec/spiced/module.rb
|
65
|
+
- spiceinit.gemspec
|
66
|
+
has_rdoc: true
|
67
|
+
homepage: https://github.com/djtek/spiceinit
|
68
|
+
licenses: []
|
69
|
+
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options:
|
72
|
+
- --title
|
73
|
+
- "spiceinit: add spices to your rubies"
|
74
|
+
- --main
|
75
|
+
- README.rdoc
|
76
|
+
- --line-numbers
|
77
|
+
- --inline-source
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
hash: 3
|
86
|
+
segments:
|
87
|
+
- 0
|
88
|
+
version: "0"
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
hash: 23
|
95
|
+
segments:
|
96
|
+
- 1
|
97
|
+
- 3
|
98
|
+
- 6
|
99
|
+
version: 1.3.6
|
100
|
+
requirements: []
|
101
|
+
|
102
|
+
rubyforge_project:
|
103
|
+
rubygems_version: 1.3.7
|
104
|
+
signing_key:
|
105
|
+
specification_version: 3
|
106
|
+
summary: With spiceinit you can initialize with extra methods and/or add class methods from a hash.
|
107
|
+
test_files: []
|
108
|
+
|