storable 0.5.8 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. data/CHANGES.txt +6 -0
  2. data/lib/storable.rb +62 -27
  3. data/storable.gemspec +1 -1
  4. metadata +3 -3
@@ -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
 
@@ -4,7 +4,7 @@
4
4
  #++
5
5
 
6
6
 
7
- USE_ORDERED_HASH = (RUBY_VERSION =~ /1.9/).nil?
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.5.8"
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
- [[:@@field_names, m], [:@@field_types, t]].each do |tuple|
63
- class_variable_set(tuple[0], []) unless class_variable_defined?(tuple[0])
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
- # Returns an array of field names defined by self.field
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.send(:class_variable_get, :@@field_names)
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.send(:class_variable_get, :@@field_types)
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
- tmp[fname] = self.send(fname)
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.kind_of?(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
+
@@ -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.5.8"
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.5.8
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-10-08 00:00:00 -04:00
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.2
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)"