valuable 0.9.2 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +2 -0
- data/README.markdown +106 -71
- data/examples/person.rb +8 -0
- data/examples/rails_presenter.rb +51 -0
- data/lib/valuable.rb +16 -6
- data/lib/valuable/utils.rb +23 -3
- data/test/default_values_from_anon_methods.rb +29 -0
- data/test/parse_with_test.rb +47 -0
- data/todo.txt +13 -12
- data/valuable.version +1 -1
- metadata +9 -5
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/README.markdown
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
Introducing Valuable
|
2
2
|
====================
|
3
3
|
|
4
|
-
Valuable enables quick modeling... it's attr_accessor on steroids.
|
4
|
+
Valuable enables quick modeling... it's attr_accessor on steroids. Its simple interface allows you to build, change and discard models without hassles, so you can get on with the logic specific to your application.
|
5
5
|
|
6
|
-
|
6
|
+
Valuable provides DRY decoration like attr_accessor, but includes default values and other formatting (like, "2" => 2), and a constructor that accepts an attributes hash. It provides a class-level list of attributes, an instance-level attributes hash, and more.
|
7
|
+
|
8
|
+
Tested with "Rubinius":http://www.rubini.us, 1.8.7, 1.9.1, 1.9.2, 1.9.3
|
9
|
+
|
10
|
+
Frequent Uses
|
11
|
+
-------------
|
7
12
|
|
8
13
|
**pre-refactor modeling** to model a class you want to abstract but know would be a pain... as in, "I would love to pull Appointment out of this WorkOrder class, but since that isn't going to happen soon, let me quickly create WorkOrder.appointments... I can then create Appointment\#to\_s, appointment.end_time, appointment.duration, etc. I can use that to facilitate emitting XML or doing something with views, rather than polluting WorkOrder with appointment-related logic."
|
9
14
|
|
@@ -11,10 +16,8 @@ Frequent Uses:
|
|
11
16
|
|
12
17
|
**creating models from non-standard data sources** to keep data from non-standard data sources in memory during an import or to render data from an API call.
|
13
18
|
|
14
|
-
Valuable provides DRY decoration like attr_accessor, but includes default values and other formatting (like, "2" => 2), and a constructor that accepts an attributes hash. It provides a class-level list of attributes, an instance-level attributes hash, and more.
|
15
|
-
|
16
19
|
Type Casting in Ruby? You must be crazy...
|
17
|
-
|
20
|
+
------------------------------------------
|
18
21
|
Yeah, I get that alot. I mean, about type casting. I'm not writing
|
19
22
|
C# over here. Rails does it, they just don't call it type casting,
|
20
23
|
so no one complains when they pass in "2" as a parameter and mysteriously
|
@@ -48,23 +51,11 @@ you'll end up with this:
|
|
48
51
|
>> p.phone_number.class
|
49
52
|
=> PhoneNumber
|
50
53
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
Default Values
|
55
|
-
--------------
|
56
|
-
Default values are used when no value is provided to the constructor. If the value nil is provided, nil will be used instead of the default.
|
57
|
-
|
58
|
-
When a default value and a klass are specified, the default value will NOT be cast to type klass -- you must do it.
|
59
|
-
|
60
|
-
If a value having a default is set to null after it is constructed, it will NOT be set to the default.
|
61
|
-
|
62
|
-
If there is no default value, the result will be nil, EVEN if type casting is provided. Thus, a field typically cast as an Integer can be nil. See calculation of average.
|
63
|
-
|
64
|
-
Examples
|
65
|
-
-------
|
54
|
+
"Yeah, I could have just done that myself."
|
55
|
+
"Right, but now you don't have to."
|
66
56
|
|
67
|
-
|
57
|
+
Basic Syntax
|
58
|
+
------------
|
68
59
|
|
69
60
|
class Fruit < Valuable
|
70
61
|
has_value :name
|
@@ -83,6 +74,16 @@ _constructor accepts an attributes hash_
|
|
83
74
|
|
84
75
|
_default values_
|
85
76
|
|
77
|
+
Default values are used when no value is provided to the constructor. If the value nil is provided, nil will be used instead of the default. Default values are populated on instanciation.
|
78
|
+
|
79
|
+
When a default value and a klass are specified, the default value will NOT be cast to type klass -- you must do it.
|
80
|
+
|
81
|
+
If a value having a default is set to null after it is constructed, it will NOT be set to the default.
|
82
|
+
|
83
|
+
If there is no default value, the result will be nil, EVEN if type casting is provided. Thus, a field typically cast as an Integer can be nil. See calculation of average.
|
84
|
+
|
85
|
+
The :default option will accept a lambda and call it on instanciation.
|
86
|
+
|
86
87
|
class Developer
|
87
88
|
has_value :name
|
88
89
|
has_value :nickname, :default => 'mort'
|
@@ -101,7 +102,25 @@ _setting a value to nil overrides the default._
|
|
101
102
|
>> Developer.new(:name => 'KDD', :nickname => nil).nickname
|
102
103
|
=> nil
|
103
104
|
|
104
|
-
|
105
|
+
_aliases_
|
106
|
+
|
107
|
+
# This example requires active_support because of Hash.from_xml
|
108
|
+
|
109
|
+
class Software < Valuable
|
110
|
+
has_value :name, :alias => 'Title'
|
111
|
+
end
|
112
|
+
|
113
|
+
>> xml = '<software><Title>Windows XP</Title></software>'
|
114
|
+
|
115
|
+
>> xp = Software.new(Hash.from_xml(xml)['software'])
|
116
|
+
|
117
|
+
>> xp.name
|
118
|
+
=> "Windows XP"
|
119
|
+
|
120
|
+
|
121
|
+
Formatting Input
|
122
|
+
----------------
|
123
|
+
_aka light-weight type-casting_
|
105
124
|
|
106
125
|
class BaseballPlayer < Valuable
|
107
126
|
|
@@ -125,11 +144,11 @@ _formatting aka light-weight type-casting_
|
|
125
144
|
# - integer
|
126
145
|
# - decimal ( casts to BigDecimal... NOTE: nil remains nil, not 0 as in nil.to_i )
|
127
146
|
# - string
|
128
|
-
# - boolean ( NOTE: '0' casts to FALSE... I would be fascinated to know when this is not the correct behavior. )
|
147
|
+
# - boolean ( NOTE: '0' casts to FALSE... This isn't intuitive, but I would be fascinated to know when this is not the correct behavior. )
|
129
148
|
# - or any class ( formats as SomeClass.new( ) unless value.is_a?( SomeClass ) )
|
130
149
|
|
131
|
-
|
132
|
-
|
150
|
+
Collections
|
151
|
+
-----------
|
133
152
|
|
134
153
|
class MailingList < Valuable
|
135
154
|
has_collection :emails
|
@@ -174,78 +193,93 @@ _formatting collections_
|
|
174
193
|
>> t.players.last
|
175
194
|
=> #<Player:0x7fa51ea6a9f8 @attributes={:salary=>"435800", :first_name=>"Travis", :last_name=>"Snider"}>
|
176
195
|
|
177
|
-
|
178
|
-
|
179
|
-
# This example requires active_support because of Hash.from_xml
|
196
|
+
parse_with parses each item in a collection...
|
180
197
|
|
181
|
-
class
|
182
|
-
|
198
|
+
class Roster < Valuable
|
199
|
+
has_collection :players, :klass => Player, :parse_with => :find_by_name
|
183
200
|
end
|
184
201
|
|
185
|
-
|
202
|
+
Advanced Defaults
|
203
|
+
-----------------
|
186
204
|
|
187
|
-
|
205
|
+
class Borg < Valuable
|
206
|
+
cattr_accessor :count
|
207
|
+
has_value :position, :default => lambda { Borg.count += 1 }
|
208
|
+
|
209
|
+
def designation
|
210
|
+
"#{self.position} of #{Borg.count}"
|
211
|
+
end
|
212
|
+
end
|
188
213
|
|
189
|
-
>>
|
190
|
-
|
214
|
+
>> Borg.count = 6
|
215
|
+
>> seven = Borg.new
|
216
|
+
>> Borg.count = 9
|
217
|
+
>> seven.designation
|
218
|
+
=> '7 of 9'
|
191
219
|
|
220
|
+
Advanced Input Parsing
|
221
|
+
----------------------
|
192
222
|
|
193
|
-
|
223
|
+
Sometimes, .to_s isn't enough... the architypical example being Date.parse(value). In these cases, you can specify what class-level method should be used to process the input.
|
194
224
|
|
195
|
-
|
196
|
-
has_value :month, :klass => Integer, :default => Time.now.month
|
197
|
-
has_value :year, :klass => Integer, :default => Time.now.year
|
225
|
+
require 'date'
|
198
226
|
|
199
|
-
|
200
|
-
|
201
|
-
end
|
227
|
+
class Person < Valuable
|
228
|
+
has_value :date_of_birth, :alias => :dob, :klass => Date, :parse_with => :parse
|
202
229
|
|
203
|
-
def
|
204
|
-
Date.
|
230
|
+
def age_in_days
|
231
|
+
Date.today - dob
|
205
232
|
end
|
233
|
+
end
|
206
234
|
|
207
|
-
|
208
|
-
|
209
|
-
|
235
|
+
>> sammy = Person.new(:dob => '2012-02-17')
|
236
|
+
>> sammy.age_in_days
|
237
|
+
=> Rational(8, 1)
|
210
238
|
|
211
|
-
|
212
|
-
['starts_at between ? and ?', start_date, end_date]
|
213
|
-
end
|
214
|
-
end
|
239
|
+
use it to load associated data from an exising set...
|
215
240
|
|
216
|
-
|
241
|
+
class Planet < Valuable
|
242
|
+
has_value :name
|
243
|
+
has_value :spaceport
|
217
244
|
|
218
|
-
|
219
|
-
|
220
|
-
@presenter = CalendarPresenter.new(params[:calendar])
|
245
|
+
def Planet.list
|
246
|
+
@list ||= []
|
221
247
|
end
|
222
|
-
end
|
223
248
|
|
224
|
-
|
249
|
+
def Planet.find_by_name( needle )
|
250
|
+
list.find{|i| i.name == needle }
|
251
|
+
end
|
252
|
+
end
|
225
253
|
|
226
|
-
|
254
|
+
class Spaceship < Valuable
|
255
|
+
has_value :name
|
256
|
+
has_value :home, :klass => Planet, :parse_with => :find_by_name
|
257
|
+
end
|
227
258
|
|
228
|
-
|
229
|
-
=>
|
259
|
+
Planet.list << Planet.new(:name => 'Earth', :spaceport => 'KSC')
|
260
|
+
Planet.list << Planet.new(:name => 'Mars', :spaceport => 'Olympus Mons')
|
230
261
|
|
231
|
-
>>
|
232
|
-
|
262
|
+
>> vger = Spaceship.new( :name => "V'ger", :home => 'Earth')
|
263
|
+
>> vger.home.spaceport
|
264
|
+
=> 'KSC'
|
233
265
|
|
234
|
-
|
266
|
+
Parse via lambda:
|
235
267
|
|
236
|
-
|
268
|
+
require 'active_support'
|
237
269
|
|
238
|
-
|
239
|
-
|
270
|
+
class Movie < Valuable
|
271
|
+
has_value :title, :parse_with => lambda{|x| x.titleize}
|
272
|
+
end
|
240
273
|
|
241
|
-
>>
|
242
|
-
=> Thu, 28 Feb 2002
|
274
|
+
>> best_movie_ever = Movie.new(:title => 'the usual suspects')
|
243
275
|
|
244
|
-
|
276
|
+
>> best_movie_ever.title
|
277
|
+
=> "The Usual Suspects"
|
245
278
|
|
246
|
-
|
279
|
+
More about Attributes
|
280
|
+
---------------------
|
247
281
|
|
248
|
-
|
282
|
+
Access the attributes via the attributes hash. Only default and specified attributes will have entries here.
|
249
283
|
|
250
284
|
class Person < Valuable
|
251
285
|
has_value :name
|
@@ -264,9 +298,10 @@ _you can access the attributes via the attributes hash. Only default and specifi
|
|
264
298
|
>> elvis.ssn
|
265
299
|
=> nil
|
266
300
|
|
267
|
-
|
301
|
+
Get a list of all the defined attributes from the class:
|
268
302
|
|
269
303
|
>> Person.attributes
|
270
304
|
=> [:name, :is_developer, :ssn]
|
271
305
|
|
306
|
+
It's a relatively simple tool that lets you create models with a (hopefully) intuitive syntax, prevents you from writing yet another obvious constructor, and allows you to keep your brain focused on your app.
|
272
307
|
|
data/examples/person.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# This class might appear in a controller like this:
|
2
|
+
#
|
3
|
+
# class CalendarController < ApplicationController
|
4
|
+
# def show
|
5
|
+
# @presenter = CalendarPresenter.new(params[:calendar])
|
6
|
+
# end
|
7
|
+
# end
|
8
|
+
#
|
9
|
+
# but in documentation, makes more sense this way :)
|
10
|
+
#
|
11
|
+
# >> @presenter = CalendarPresenter.new # first pageload
|
12
|
+
#
|
13
|
+
# >> @presenter.start_date
|
14
|
+
# => Tue, 01 Dec 2009
|
15
|
+
#
|
16
|
+
# >> @presenter.end_date
|
17
|
+
# => Thu, 31 Dec 2009
|
18
|
+
#
|
19
|
+
# >> # User selects some other month and year; the next request looks like...
|
20
|
+
#
|
21
|
+
# >> @presenter = CalendarPresenter.new({:month => '2', :year => '2002'})
|
22
|
+
#
|
23
|
+
# >> @presenter.start_date
|
24
|
+
# => Fri, 01 Feb 2002
|
25
|
+
#
|
26
|
+
# >> @presenter.end_date
|
27
|
+
# => Thu, 28 Feb 2002
|
28
|
+
#
|
29
|
+
# ...
|
30
|
+
#
|
31
|
+
class CalenderPresenter < Valuable
|
32
|
+
has_value :month, :klass => Integer, :default => Time.now.month
|
33
|
+
has_value :year, :klass => Integer, :default => Time.now.year
|
34
|
+
|
35
|
+
def start_date
|
36
|
+
Date.civil( year, month, 1)
|
37
|
+
end
|
38
|
+
|
39
|
+
def end_date
|
40
|
+
Date.civil( year, month, -1) #strange I know
|
41
|
+
end
|
42
|
+
|
43
|
+
def events
|
44
|
+
Event.find(:all, :conditions => event_conditions)
|
45
|
+
end
|
46
|
+
|
47
|
+
def event_conditions
|
48
|
+
['starts_at between ? and ?', start_date, end_date]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
data/lib/valuable.rb
CHANGED
@@ -19,29 +19,39 @@
|
|
19
19
|
#
|
20
20
|
class Valuable
|
21
21
|
|
22
|
-
# Returns a Hash representing all known values. Values are set
|
22
|
+
# Returns a Hash representing all known values. Values are set four ways:
|
23
23
|
#
|
24
|
-
# (1)
|
24
|
+
# (1) Default values are set on instanciation, ie Person.new
|
25
25
|
# (2) they were passed to the constructor
|
26
26
|
# Bus.new(:color => 'green')
|
27
27
|
# (3) they were set via their namesake setter or alias setter
|
28
28
|
# bus.color = 'green'
|
29
29
|
# bus.Passengers = ['bill', 'steve']
|
30
|
-
#
|
30
|
+
# (4) the write_attributes(key, value) method
|
31
|
+
#
|
31
32
|
# Values that have not been set and have no default not appear in this
|
32
33
|
# collection. Their namesake attribute methods will respond with nil.
|
33
|
-
# Always use symbols to access these values
|
34
|
-
#
|
34
|
+
# Always use symbols to access these values, ie:
|
35
|
+
# Person.attributes[:color]
|
36
|
+
# not
|
37
|
+
# Person.attributes['color']
|
38
|
+
#
|
39
|
+
# basic usage:
|
35
40
|
# >> bus = Bus.new(:number => 16) # color has default value 'yellow'
|
36
41
|
# >> bus.attributes
|
37
42
|
# => {:color => 'yellow', :number => 16}
|
38
43
|
def attributes
|
39
|
-
@attributes
|
44
|
+
@attributes
|
45
|
+
end
|
46
|
+
|
47
|
+
def initialize_attributes
|
48
|
+
@attributes ||= Valuable::Utils.initial_copy_of_attributes(self.class.defaults)
|
40
49
|
end
|
41
50
|
|
42
51
|
# accepts an optional hash that will be used to populate the
|
43
52
|
# predefined attributes for this class.
|
44
53
|
def initialize(atts = nil)
|
54
|
+
initialize_attributes
|
45
55
|
self.update_attributes(atts || {})
|
46
56
|
end
|
47
57
|
|
data/lib/valuable/utils.rb
CHANGED
@@ -15,6 +15,20 @@ module Valuable::Utils
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
def initial_copy_of_attributes(atts)
|
19
|
+
out = {}
|
20
|
+
atts.each do |name, value|
|
21
|
+
case value
|
22
|
+
when Proc
|
23
|
+
out[name] = value.call
|
24
|
+
else
|
25
|
+
out[name] = deep_duplicate_of( value )
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
out
|
30
|
+
end
|
31
|
+
|
18
32
|
def deep_duplicate_of(value)
|
19
33
|
Marshal.load(Marshal.dump(value))
|
20
34
|
end
|
@@ -25,7 +39,11 @@ module Valuable::Utils
|
|
25
39
|
case klass
|
26
40
|
when NilClass
|
27
41
|
|
28
|
-
|
42
|
+
if Proc === attributes[name][:parse_with]
|
43
|
+
attributes[name][:parse_with].call(value)
|
44
|
+
else
|
45
|
+
value
|
46
|
+
end
|
29
47
|
|
30
48
|
when :collection
|
31
49
|
if( value.kind_of?(Array) )
|
@@ -77,7 +95,7 @@ module Valuable::Utils
|
|
77
95
|
elsif value.is_a? klass
|
78
96
|
value
|
79
97
|
else
|
80
|
-
klass.new
|
98
|
+
klass.send( attributes[name][:parse_with] || :new, value)
|
81
99
|
end
|
82
100
|
|
83
101
|
end
|
@@ -89,7 +107,7 @@ module Valuable::Utils
|
|
89
107
|
end
|
90
108
|
|
91
109
|
def known_options
|
92
|
-
|
110
|
+
[:klass, :default, :negative, :alias, :parse_with]
|
93
111
|
end
|
94
112
|
|
95
113
|
# this helper raises an exception if the options passed to has_value
|
@@ -101,6 +119,8 @@ module Valuable::Utils
|
|
101
119
|
raise ArgumentError, "has_value did not know how to respond to option(s) #{invalid_options.join(', ')}. Valid (optional) arguments are: #{known_options.join(', ')}" unless invalid_options.empty?
|
102
120
|
|
103
121
|
raise ArgumentError, "#{class_name} doesn't know how to format #{attribute} with :klass => #{options[:klass].inspect}" unless klass_options.any?{|klass| klass === options[:klass]}
|
122
|
+
|
123
|
+
raise( ArgumentError, "#{class_name} can't promise to return a(n) #{options[:klass]} when using :parse_with" ) if options[:klass].is_a?( Symbol ) && options[:parse_with]
|
104
124
|
end
|
105
125
|
end
|
106
126
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
$: << File.expand_path(File.dirname(__FILE__) + '/../lib')
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'test/unit'
|
5
|
+
require 'valuable.rb'
|
6
|
+
|
7
|
+
class Borg < Valuable
|
8
|
+
class << self
|
9
|
+
attr_accessor :count
|
10
|
+
end
|
11
|
+
has_value :position, :default => lambda { Borg.count += 1 }
|
12
|
+
has_value :name
|
13
|
+
|
14
|
+
def designation
|
15
|
+
"#{self.position} of #{Borg.count}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class DefaultValueFromAnonMethodsTest < Test::Unit::TestCase
|
20
|
+
|
21
|
+
def test_that_children_inherit_their_parents_attributes
|
22
|
+
Borg.count = 6
|
23
|
+
seven = Borg.new
|
24
|
+
Borg.count = 9
|
25
|
+
assert_equal '7 of 9', seven.designation
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
$: << File.expand_path(File.dirname(__FILE__) + '/../lib')
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'valuable.rb'
|
5
|
+
require 'mocha'
|
6
|
+
|
7
|
+
class Person < Valuable
|
8
|
+
has_value :first_name
|
9
|
+
has_value :last_name
|
10
|
+
|
11
|
+
def Person.load( name )
|
12
|
+
f, l = name.split(' ') # trivial case
|
13
|
+
new(:first_name => f, :last_name => l)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class RailsApp < Valuable
|
18
|
+
has_value :tech_lead, :klass => Person, :parse_with => :load
|
19
|
+
has_collection :devs, :klass => Person, :parse_with => :load
|
20
|
+
has_value :name, :parse_with => lambda{|x| x == 'IA' ? 'Information Architecture' : x}
|
21
|
+
end
|
22
|
+
|
23
|
+
class ParseWithTest < Test::Unit::TestCase
|
24
|
+
|
25
|
+
def test_that_parse_with_calls_target_classes_parse_method
|
26
|
+
ia = RailsApp.new(:tech_lead => 'Adam Dalton')
|
27
|
+
assert_equal 'Adam', ia.tech_lead.first_name
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_that_collections_are_parsed
|
31
|
+
ia = RailsApp.new(:devs => ['Dennis Camp', 'Richard Hoblitzell', 'Paul Kuracz', 'Magda Lueiro', 'George Meyer', 'David Moyer', 'Bill Snoddy'])
|
32
|
+
expected = ['Dennis', 'Richard', 'Paul', 'Magda', 'George', 'David', 'Bill']
|
33
|
+
actual = ia.devs.map(&:first_name)
|
34
|
+
assert_equal expected, actual
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_that_lambdas_can_be_used_as_parsers
|
38
|
+
assert_equal 'Information Architecture', RailsApp.new(:name => 'IA').name
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_that_it_raises_an_error_when_passed_a_class_and_a_proc
|
42
|
+
animal = Class.new(Valuable)
|
43
|
+
assert_raises ArgumentError, "Class can't promise to return a(n) :integer when using the option :parse_with" do
|
44
|
+
animal.has_value :invalid, :klass => :integer, :parse_with => :method
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/todo.txt
CHANGED
@@ -12,17 +12,6 @@ class SomeSearchThing < Valuable
|
|
12
12
|
|
13
13
|
end
|
14
14
|
|
15
|
-
class Datum < Valuable
|
16
|
-
has_index :by_name
|
17
|
-
has_list :calculations
|
18
|
-
end
|
19
|
-
-or-
|
20
|
-
class Datum < Valuable
|
21
|
-
lists :calculations
|
22
|
-
indexes :by_name
|
23
|
-
end
|
24
|
-
|
25
|
-
|
26
15
|
BEST PRACTICES DOC
|
27
16
|
|
28
17
|
When creating a searcher:
|
@@ -78,6 +67,18 @@ like this:
|
|
78
67
|
end
|
79
68
|
|
80
69
|
|
81
|
-
|
70
|
+
|
71
|
+
:klass => :decimal
|
72
|
+
- When is decimal available? Only load then.
|
73
|
+
- If calling :decimal and it hasn't loaded, error
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
class Change < Decimal
|
78
|
+
extend Valuable::whatever or
|
79
|
+
extend Valuable
|
80
|
+
|
81
|
+
...
|
82
|
+
end
|
82
83
|
|
83
84
|
- do a better job with method_missing
|
data/valuable.version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.9.
|
1
|
+
0.9.3
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: valuable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 61
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 9
|
9
|
-
-
|
10
|
-
version: 0.9.
|
9
|
+
- 3
|
10
|
+
version: 0.9.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Johnathon Wright
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2012-02-25 00:00:00 -06:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -33,13 +33,17 @@ files:
|
|
33
33
|
- README.markdown
|
34
34
|
- Rakefile
|
35
35
|
- examples/baseball.rb
|
36
|
+
- examples/person.rb
|
36
37
|
- examples/phone_number.rb
|
38
|
+
- examples/rails_presenter.rb
|
37
39
|
- lib/valuable.rb
|
38
40
|
- lib/valuable/utils.rb
|
39
41
|
- test/alias_test.rb
|
40
42
|
- test/bad_attributes_test.rb
|
43
|
+
- test/default_values_from_anon_methods.rb
|
41
44
|
- test/deprecated_test.rb
|
42
45
|
- test/inheritance_test.rb
|
46
|
+
- test/parse_with_test.rb
|
43
47
|
- test/typical_test.rb
|
44
48
|
- test/valuable_test.rb
|
45
49
|
- test/write_and_read_attribute_test.rb
|
@@ -76,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
80
|
requirements: []
|
77
81
|
|
78
82
|
rubyforge_project:
|
79
|
-
rubygems_version: 1.
|
83
|
+
rubygems_version: 1.6.2
|
80
84
|
signing_key:
|
81
85
|
specification_version: 3
|
82
86
|
summary: attr_accessor on steroids with defaults, default constructor, and attribute formatting.
|