Class: Storable
- Inherits:
-
Object
- Object
- Storable
- Defined in:
- lib/storable.rb
Overview
Storable makes data available in multiple formats and can re-create objects from files. Fields are defined using the Storable.field method which tells Storable the order and name.
Defined Under Namespace
Classes: OrderedHash
Constant Summary collapse
- VERSION =
0.5- NICE_TIME_FORMAT =
"%Y-%m-%d@%H:%M:%S".freeze
- SUPPORTED_FORMATS =
[:tsv, :csv, :yaml, :json, :s, :string].freeze
Instance Attribute Summary collapse
-
#format ⇒ Object
This value will be used as a default unless provided on-the-fly.
Class Method Summary collapse
- .append_file(path, content, flush = true) ⇒ Object
-
.field(args = {}) ⇒ Object
Accepts field definitions in the one of the follow formats:.
-
.field_names ⇒ Object
Returns an array of field names defined by self.field.
-
.field_types ⇒ Object
Returns an array of field types defined by self.field.
-
.from_csv(from = []) ⇒ Object
Create a new instance of the object from comma-delimited data.
-
.from_delimited(from = [], delim = ',') ⇒ Object
Create a new instance of the object from a delimited string.
-
.from_file(file_path, format = 'yaml') ⇒ Object
Create a new instance of the object using data from file.
-
.from_hash(from = {}) ⇒ Object
Create a new instance of the object from a hash.
-
.from_json(*from) ⇒ Object
Create a new instance of the object from a JSON string.
-
.from_tsv(from = []) ⇒ Object
Create a new instance from tab-delimited data.
-
.from_yaml(*from) ⇒ Object
Create a new instance of the object from YAML.
- .read_file_to_array(path) ⇒ Object
- .write_file(path, content, flush = true) ⇒ Object
- .write_or_append_file(write_or_append, path, content = '', flush = true) ⇒ Object
Instance Method Summary collapse
-
#dump(format = nil, with_titles = false) ⇒ Object
Dump the object data to the given format.
-
#field_names ⇒ Object
Returns an array of field names defined by self.field.
-
#field_types ⇒ Object
Returns an array of field types defined by self.field.
- #postprocess ⇒ Object
-
#to_csv(with_titles = false) ⇒ Object
Return the object data as a comma delimited string.
-
#to_delimited(with_titles = false, delim = ',') ⇒ Object
Return the object data as a delimited string.
-
#to_file(file_path = nil, with_titles = true) ⇒ Object
Write the object data to the given file.
-
#to_hash(with_titles = true) ⇒ Object
Return the object data as a hash
with_titlesis ignored. - #to_json(with_titles = true) ⇒ Object
- #to_string(*args) ⇒ Object
-
#to_tsv(with_titles = false) ⇒ Object
Return the object data as a tab delimited string.
- #to_yaml(with_titles = true) ⇒ Object
Instance Attribute Details
#format ⇒ Object
This value will be used as a default unless provided on-the-fly. See SUPPORTED_FORMATS for available values.
32 33 34 |
# File 'lib/storable.rb', line 32 def format @format end |
Class Method Details
.append_file(path, content, flush = true) ⇒ Object
283 284 285 |
# File 'lib/storable.rb', line 283 def self.append_file(path, content, flush=true) write_or_append_file('a', path, content, flush) end |
.field(args = {}) ⇒ Object
Accepts field definitions in the one of the follow formats:
field :product
field :product => Integer
The order they’re defined determines the order the will be output. The fields data is available by the standard accessors, class.product and class.product= etc… The value of the field will be cast to the type (if provided) when read from a file. The value is not touched when the type is not provided.
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/storable.rb', line 55 def self.field(args={}) # TODO: Examine casting from: http://codeforpeople.com/lib/ruby/fattr/fattr-1.0.3/ args = {args => nil} unless args.kind_of?(Hash) args.each_pair do |m,t| [[:@@field_names, m], [:@@field_types, t]].each do |tuple| class_variable_set(tuple[0], []) unless class_variable_defined?(tuple[0]) class_variable_set(tuple[0], class_variable_get(tuple[0]) << tuple[1]) end next if method_defined?(m) define_method(m) do instance_variable_get("@#{m}") end define_method("#{m}=") do |val| instance_variable_set("@#{m}",val) end end end |
.field_names ⇒ Object
Returns an array of field names defined by self.field
76 77 78 |
# File 'lib/storable.rb', line 76 def self.field_names class_variable_get(:@@field_names) end |
.field_types ⇒ Object
Returns an array of field types defined by self.field. Fields that did not receive a type are set to nil.
85 86 87 |
# File 'lib/storable.rb', line 85 def self.field_types class_variable_get(:@@field_types) end |
.from_csv(from = []) ⇒ Object
Create a new instance of the object from comma-delimited data. from a JSON string split into an array by line.
239 240 241 |
# File 'lib/storable.rb', line 239 def self.from_csv(from=[]) self.from_delimited(from, ',') end |
.from_delimited(from = [], delim = ',') ⇒ Object
Create a new instance of the object from a delimited string. from a JSON string split into an array by line. delim is the field delimiter.
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
# File 'lib/storable.rb', line 246 def self.from_delimited(from=[],delim=',') return if from.empty? # We grab an instance of the class so we can hash = {} fnames = values = [] if (from.size > 1 && !from[1].empty?) fnames = from[0].chomp.split(delim) values = from[1].chomp.split(delim) else fnames = self.field_names values = from[0].chomp.split(delim) end fnames.each_with_index do |key,index| next unless values[index] hash[key.to_sym] = values[index] end hash = from_hash(hash) if hash.kind_of?(Hash) hash end |
.from_file(file_path, format = 'yaml') ⇒ Object
Create a new instance of the object using data from file.
107 108 109 110 111 112 113 114 |
# File 'lib/storable.rb', line 107 def self.from_file(file_path, format='yaml') raise "Cannot read file (#{file_path})" unless File.exists?(file_path) raise "#{self} doesn't support from_#{format}" unless self.respond_to?("from_#{format}") format = format || File.extname(file_path).tr('.', '') me = send("from_#{format}", read_file_to_array(file_path)) me.format = format me end |
.from_hash(from = {}) ⇒ Object
Create a new instance of the object from a hash.
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/storable.rb', line 125 def self.from_hash(from={}) return nil if !from || from.empty? me = self.new fnames = field_names fnames.each_with_index do |key,index| stored_value = from[key] || from[key.to_s] # support for symbol keys and string keys # TODO: Correct this horrible implementation (sorry, me. It's just one of those days.) if field_types[index] == Array ((value ||= []) << stored_value).flatten elsif field_types[index].kind_of?(Hash) value = stored_value else # SimpleDB stores attribute shit as lists of values ##value = stored_value.first if stored_value.is_a?(Array) && stored_value.size == 1 value = (stored_value.is_a?(Array) && stored_value.size == 1) ? stored_value.first : stored_value if field_types[index] == Time value = Time.parse(value) elsif field_types[index] == DateTime value = DateTime.parse(value) elsif field_types[index] == TrueClass value = (value.to_s == "true") elsif field_types[index] == Float value = value.to_f elsif field_types[index] == Integer value = value.to_i elsif field_types[index].kind_of?(Storable) && stored_value.kind_of?(Hash) # I don't know why this is here so I'm going to raise an exception # and wait a while for an error in one of my other projects. #value = field_types[index].from_hash(stored_value) raise "Delano, delano, delano. Clean up Storable!" end end me.send("#{key}=", value) if self.method_defined?("#{key}=") end me.postprocess me end |
.from_json(*from) ⇒ Object
Create a new instance of the object from a JSON string. from a YAML String or Array (split into by line).
196 197 198 199 200 201 202 203 204 205 |
# File 'lib/storable.rb', line 196 def self.from_json(*from) from_str = [from].flatten.compact.join('') tmp = JSON::load(from_str) hash_sym = tmp.keys.inject({}) do |hash, key| hash[key.to_sym] = tmp[key] hash end hash_sym = from_hash(hash_sym) if hash_sym.kind_of?(Hash) hash_sym end |
.from_tsv(from = []) ⇒ Object
Create a new instance from tab-delimited data.
from a JSON string split into an array by line.
234 235 236 |
# File 'lib/storable.rb', line 234 def self.from_tsv(from=[]) self.from_delimited(from, "\t") end |
.from_yaml(*from) ⇒ Object
Create a new instance of the object from YAML. from a YAML String or Array (split into by line).
184 185 186 187 188 189 |
# File 'lib/storable.rb', line 184 def self.from_yaml(*from) from_str = [from].flatten.compact.join('') hash = YAML::load(from_str) hash = from_hash(hash) if hash.kind_of?(Hash) hash end |
.read_file_to_array(path) ⇒ Object
268 269 270 271 272 273 274 275 276 277 |
# File 'lib/storable.rb', line 268 def self.read_file_to_array(path) contents = [] return contents unless File.exists?(path) open(path, 'r') do |l| contents = l.readlines end contents end |
.write_file(path, content, flush = true) ⇒ Object
279 280 281 |
# File 'lib/storable.rb', line 279 def self.write_file(path, content, flush=true) write_or_append_file('w', path, content, flush) end |
.write_or_append_file(write_or_append, path, content = '', flush = true) ⇒ Object
287 288 289 290 291 292 293 294 295 296 |
# File 'lib/storable.rb', line 287 def self.write_or_append_file(write_or_append, path, content = '', flush = true) #STDERR.puts "Writing to #{ path }..." create_dir(File.dirname(path)) open(path, write_or_append) do |f| f.puts content f.flush if flush; end File.chmod(0600, path) end |
Instance Method Details
#dump(format = nil, with_titles = false) ⇒ Object
Dump the object data to the given format.
95 96 97 98 99 100 |
# File 'lib/storable.rb', line 95 def dump(format=nil, with_titles=false) format &&= format.to_sym format ||= 's' # as in, to_s raise "Format not defined (#{format})" unless SUPPORTED_FORMATS.member?(format) send("to_#{format}", with_titles) end |
#field_names ⇒ Object
Returns an array of field names defined by self.field
80 81 82 |
# File 'lib/storable.rb', line 80 def field_names self.class.send(:class_variable_get, :@@field_names) end |
#field_types ⇒ Object
Returns an array of field types defined by self.field. Fields that did not receive a type are set to nil.
90 91 92 |
# File 'lib/storable.rb', line 90 def field_types self.class.send(:class_variable_get, :@@field_types) end |
#postprocess ⇒ Object
41 42 |
# File 'lib/storable.rb', line 41 def postprocess end |
#to_csv(with_titles = false) ⇒ Object
Return the object data as a comma delimited string. with_titles specifiy whether to include field names (default: false)
229 230 231 |
# File 'lib/storable.rb', line 229 def to_csv(with_titles=false) to_delimited(with_titles, ',') end |
#to_delimited(with_titles = false, delim = ',') ⇒ Object
Return the object data as a delimited string. with_titles specifiy whether to include field names (default: false) delim is the field delimiter.
213 214 215 216 217 218 219 220 221 |
# File 'lib/storable.rb', line 213 def to_delimited(with_titles=false, delim=',') values = [] field_names.each do |fname| values << self.send(fname.to_s) # TODO: escape values end output = values.join(delim) output = field_names.join(delim) << $/ << output if with_titles output end |
#to_file(file_path = nil, with_titles = true) ⇒ Object
Write the object data to the given file.
116 117 118 119 120 121 122 |
# File 'lib/storable.rb', line 116 def to_file(file_path=nil, with_titles=true) raise "Cannot store to nil path" if file_path.nil? format = File.extname(file_path).tr('.', '') format &&= format.to_sym format ||= @format Storable.write_file(file_path, dump(format, with_titles)) end |
#to_hash(with_titles = true) ⇒ Object
Return the object data as a hash with_titles is ignored.
174 175 176 177 178 179 180 |
# File 'lib/storable.rb', line 174 def to_hash(with_titles=true) tmp = USE_ORDERED_HASH ? Storable::OrderedHash.new : {} field_names.each do |fname| tmp[fname] = self.send(fname) end tmp end |
#to_json(with_titles = true) ⇒ Object
206 207 208 |
# File 'lib/storable.rb', line 206 def to_json(with_titles=true) to_hash.to_json end |
#to_string(*args) ⇒ Object
102 103 104 |
# File 'lib/storable.rb', line 102 def to_string(*args) to_s(*args) end |
#to_tsv(with_titles = false) ⇒ Object
Return the object data as a tab delimited string. with_titles specifiy whether to include field names (default: false)
224 225 226 |
# File 'lib/storable.rb', line 224 def to_tsv(with_titles=false) to_delimited(with_titles, "\t") end |
#to_yaml(with_titles = true) ⇒ Object
190 191 192 |
# File 'lib/storable.rb', line 190 def to_yaml(with_titles=true) to_hash.to_yaml end |