storable 0.5.8 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +6 -0
- data/lib/storable.rb +62 -27
- data/storable.gemspec +1 -1
- metadata +3 -3
data/CHANGES.txt
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
STORABLE, CHANGES
|
2
2
|
|
3
|
+
#### 0.6.0 (2009-11-27) #############################
|
4
|
+
|
5
|
+
* FIXED: Undefined @@field_names error when no fields specified
|
6
|
+
* ADDED: Support for field output processors
|
7
|
+
* ADDED: Storable::DefaultProcessors
|
8
|
+
|
3
9
|
|
4
10
|
#### 0.5.8 (2009-10-06) #############################
|
5
11
|
|
data/lib/storable.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
#++
|
5
5
|
|
6
6
|
|
7
|
-
USE_ORDERED_HASH = (RUBY_VERSION =~
|
7
|
+
USE_ORDERED_HASH = (RUBY_VERSION =~ /^1.9/).nil?
|
8
8
|
|
9
9
|
begin
|
10
10
|
require 'json'
|
@@ -15,19 +15,40 @@ end
|
|
15
15
|
require 'yaml'
|
16
16
|
require 'fileutils'
|
17
17
|
require 'time'
|
18
|
-
|
18
|
+
|
19
|
+
|
20
|
+
class Storable
|
21
|
+
module DefaultProcessors
|
22
|
+
def hash_proc_processor
|
23
|
+
Proc.new do |procs|
|
24
|
+
a = {}
|
25
|
+
procs.each_pair { |n,v|
|
26
|
+
a[n] = (Proc === v) ? v.source : v
|
27
|
+
}
|
28
|
+
a
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
19
34
|
# Storable makes data available in multiple formats and can
|
20
35
|
# re-create objects from files. Fields are defined using the
|
21
36
|
# Storable.field method which tells Storable the order and
|
22
37
|
# name.
|
23
38
|
class Storable
|
39
|
+
extend Storable::DefaultProcessors
|
40
|
+
|
24
41
|
require 'storable/orderedhash' if USE_ORDERED_HASH
|
25
42
|
unless defined?(SUPPORTED_FORMATS) # We can assume all are defined
|
26
|
-
VERSION = "0.
|
43
|
+
VERSION = "0.6.0"
|
27
44
|
NICE_TIME_FORMAT = "%Y-%m-%d@%H:%M:%S".freeze
|
28
45
|
SUPPORTED_FORMATS = [:tsv, :csv, :yaml, :json, :s, :string].freeze
|
29
46
|
end
|
30
47
|
|
48
|
+
class << self
|
49
|
+
attr_accessor :field_names, :field_types
|
50
|
+
end
|
51
|
+
|
31
52
|
# This value will be used as a default unless provided on-the-fly.
|
32
53
|
# See SUPPORTED_FORMATS for available values.
|
33
54
|
attr_reader :format
|
@@ -48,23 +69,29 @@ class Storable
|
|
48
69
|
#
|
49
70
|
# field :product
|
50
71
|
# field :product => Integer
|
72
|
+
# field :product do |val|
|
73
|
+
# # modify val before it's stored.
|
74
|
+
# end
|
51
75
|
#
|
52
76
|
# The order they're defined determines the order the will be output. The fields
|
53
77
|
# data is available by the standard accessors, class.product and class.product= etc...
|
54
78
|
# The value of the field will be cast to the type (if provided) when read from a file.
|
55
79
|
# The value is not touched when the type is not provided.
|
56
|
-
def self.field(args={})
|
80
|
+
def self.field(args={}, &processor)
|
57
81
|
# TODO: Examine casting from: http://codeforpeople.com/lib/ruby/fattr/fattr-1.0.3/
|
58
82
|
args = {args => nil} unless args.kind_of?(Hash)
|
59
83
|
|
60
84
|
args.each_pair do |m,t|
|
85
|
+
self.field_names ||= []
|
86
|
+
self.field_types ||= []
|
87
|
+
self.field_names << m
|
88
|
+
self.field_types << t unless t.nil?
|
61
89
|
|
62
|
-
|
63
|
-
|
64
|
-
class_variable_set(tuple[0], class_variable_get(tuple[0]) << tuple[1])
|
90
|
+
unless processor.nil?
|
91
|
+
define_method("_storable_processor_#{m}", &processor)
|
65
92
|
end
|
66
93
|
|
67
|
-
next if method_defined?(m)
|
94
|
+
next if method_defined?(m) # don't refine the accessor methods
|
68
95
|
|
69
96
|
define_method(m) do instance_variable_get("@#{m}") end
|
70
97
|
define_method("#{m}=") do |val|
|
@@ -80,23 +107,15 @@ class Storable
|
|
80
107
|
self.class.field_names.member? n.to_sym
|
81
108
|
end
|
82
109
|
|
83
|
-
|
84
|
-
def self.field_names
|
85
|
-
class_variable_get(:@@field_names)
|
86
|
-
end
|
110
|
+
|
87
111
|
# Returns an array of field names defined by self.field
|
88
112
|
def field_names
|
89
|
-
self.class.
|
90
|
-
end
|
91
|
-
# Returns an array of field types defined by self.field. Fields that did
|
92
|
-
# not receive a type are set to nil.
|
93
|
-
def self.field_types
|
94
|
-
class_variable_get(:@@field_types)
|
113
|
+
self.class.field_names
|
95
114
|
end
|
96
115
|
# Returns an array of field types defined by self.field. Fields that did
|
97
116
|
# not receive a type are set to nil.
|
98
117
|
def field_types
|
99
|
-
self.class.
|
118
|
+
self.class.field_types
|
100
119
|
end
|
101
120
|
|
102
121
|
# Dump the object data to the given format.
|
@@ -185,22 +204,40 @@ class Storable
|
|
185
204
|
def to_hash
|
186
205
|
tmp = USE_ORDERED_HASH ? Storable::OrderedHash.new : {}
|
187
206
|
field_names.each do |fname|
|
188
|
-
|
207
|
+
v = self.send(fname)
|
208
|
+
v = process(fname, v) if has_processor?(fname)
|
209
|
+
if Array === v
|
210
|
+
v = v.collect { |v2| v2.kind_of?(Storable) ? v2.to_hash : v2 }
|
211
|
+
end
|
212
|
+
tmp[fname] = v.kind_of?(Storable) ? v.to_hash : v
|
189
213
|
end
|
190
214
|
tmp
|
191
215
|
end
|
192
216
|
|
217
|
+
def to_json(*from, &blk)
|
218
|
+
to_hash.to_json(*from, &blk)
|
219
|
+
end
|
220
|
+
|
221
|
+
def to_yaml(*from, &blk)
|
222
|
+
to_hash.to_yaml(*from, &blk)
|
223
|
+
end
|
224
|
+
|
225
|
+
def process(fname, val)
|
226
|
+
self.send :"_storable_processor_#{fname}", val
|
227
|
+
end
|
228
|
+
|
229
|
+
def has_processor?(fname)
|
230
|
+
self.respond_to? :"_storable_processor_#{fname}"
|
231
|
+
end
|
232
|
+
|
193
233
|
# Create a new instance of the object from YAML.
|
194
234
|
# +from+ a YAML String or Array (split into by line).
|
195
235
|
def self.from_yaml(*from)
|
196
236
|
from_str = [from].flatten.compact.join('')
|
197
237
|
hash = YAML::load(from_str)
|
198
|
-
hash = from_hash(hash) if hash
|
238
|
+
hash = from_hash(hash) if Hash === hash
|
199
239
|
hash
|
200
240
|
end
|
201
|
-
def to_yaml
|
202
|
-
to_hash.to_yaml
|
203
|
-
end
|
204
241
|
|
205
242
|
# Create a new instance of the object from a JSON string.
|
206
243
|
# +from+ a YAML String or Array (split into by line).
|
@@ -214,9 +251,6 @@ class Storable
|
|
214
251
|
hash_sym = from_hash(hash_sym) if hash_sym.kind_of?(Hash)
|
215
252
|
hash_sym
|
216
253
|
end
|
217
|
-
def to_json(with_titles=true)
|
218
|
-
to_hash.to_json
|
219
|
-
end
|
220
254
|
|
221
255
|
# Return the object data as a delimited string.
|
222
256
|
# +with_titles+ specifiy whether to include field names (default: false)
|
@@ -307,3 +341,4 @@ class Storable
|
|
307
341
|
end
|
308
342
|
end
|
309
343
|
|
344
|
+
|
data/storable.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
@spec = Gem::Specification.new do |s|
|
2
2
|
s.name = "storable"
|
3
3
|
s.rubyforge_project = "storable"
|
4
|
-
s.version = "0.
|
4
|
+
s.version = "0.6.0"
|
5
5
|
s.summary = "Storable: Marshal Ruby classes into and out of multiple formats (yaml, json, csv, tsv)"
|
6
6
|
s.description = s.summary
|
7
7
|
s.author = "Delano Mandelbaum"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: storable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Delano Mandelbaum
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-11-27 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -58,7 +58,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements: []
|
59
59
|
|
60
60
|
rubyforge_project: storable
|
61
|
-
rubygems_version: 1.3.
|
61
|
+
rubygems_version: 1.3.5
|
62
62
|
signing_key:
|
63
63
|
specification_version: 3
|
64
64
|
summary: "Storable: Marshal Ruby classes into and out of multiple formats (yaml, json, csv, tsv)"
|