Class: ArDumper
- Inherits:
-
Object
- Object
- ArDumper
- Defined in:
- lib/ar_dumper_base.rb
Overview
proc = Proc.new { |options| options.rating > 8 ? ‘HIGHLY RATED’ ? ‘AVERAGE’}
Girlfriend.dumper :xml, :procs => {'my_rating' => proc}
<girlfriend>
# ... other attributes and methods ...
<>HIGHLY RATED</my_rating>
</girlfriend>
Instance Attribute Summary collapse
-
#fields ⇒ Object
readonly
Returns the value of attribute fields.
-
#klass ⇒ Object
readonly
Returns the value of attribute klass.
-
#options ⇒ Object
readonly
Returns the value of attribute options.
Class Method Summary collapse
-
.compute_page_size(max_records, page_num, page_size) ⇒ Object
:nodoc:.
-
.paginate_dump_records(klass, options = {}, &block) ⇒ Object
Pagination Helpers…
-
.paginate_each_record(klass, options = {}, &block) ⇒ Object
Quick and dirty paginate to loop thru each page Options are: *
:find
- a map of the finder options passed to find.
Instance Method Summary collapse
-
#build_attribute_list ⇒ Object
build a list of attributes, methods and procs.
-
#build_header_list ⇒ Object
Returns an array with the header names This will be in the same order as the data returned by dump_record attributes + methods + procs.
-
#csv_writer ⇒ Object
Try to use the FasterCSV if it exists otherwise use csv.
- #dump(format) ⇒ Object
-
#dump_record(record) ⇒ Object
collect the record data into an array.
-
#dump_to_csv ⇒ Object
CSV DUMPER.
-
#dump_to_fixture ⇒ Object
Yaml/Fixture Dumper.
-
#dump_to_xml ⇒ Object
XML Dumper.
-
#dumper(file_extension = nil, header = nil, footer = nil, &block) ⇒ Object
Wrapper around the outside of dumper See options in dumper.
-
#initialize(klass, dump_options = {}) ⇒ ArDumper
constructor
A new instance of ArDumper.
-
#prepare_target(file_extension = nil) ⇒ Object
Create the options(file) based on these options.
-
#write_csv_row(row_data, header_list = []) ⇒ Object
Write out the csv row using the selected csv writer.
Constructor Details
#initialize(klass, dump_options = {}) ⇒ ArDumper
Returns a new instance of ArDumper.
84 85 86 87 88 89 90 91 92 |
# File 'lib/ar_dumper_base.rb', line 84 def initialize(klass, ={}) @klass = klass = build_attribute_list unless [:text_format].nil? || String.new.respond_to?([:text_format]) raise ArDumperException.new("Invalid value for option :text_format #{options[:text_format]}") end end |
Instance Attribute Details
#fields ⇒ Object (readonly)
Returns the value of attribute fields.
80 81 82 |
# File 'lib/ar_dumper_base.rb', line 80 def fields @fields end |
#klass ⇒ Object (readonly)
Returns the value of attribute klass.
81 82 83 |
# File 'lib/ar_dumper_base.rb', line 81 def klass @klass end |
#options ⇒ Object (readonly)
Returns the value of attribute options.
82 83 84 |
# File 'lib/ar_dumper_base.rb', line 82 def end |
Class Method Details
.compute_page_size(max_records, page_num, page_size) ⇒ Object
:nodoc:
442 443 444 |
# File 'lib/ar_dumper_base.rb', line 442 def self.compute_page_size(max_records, page_num, page_size)#:nodoc: max_records ? [(max_records - (page_num * page_size)), page_size].min : page_size end |
.paginate_dump_records(klass, options = {}, &block) ⇒ Object
Pagination Helpers… OR YOU COULD INSTALL paginate_find plugin!
Quick and dirty paginate to loop thru the records page by page Options are:
-
:find
- a map of the finder options passed to find. For example, + => [‘hairy = ?’, ‘of course’], :include => :rodents + -
:page_size
- the page size to use. Defaults to dumper_page_size or 50. Set to false to disable pagination
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 |
# File 'lib/ar_dumper_base.rb', line 415 def self.paginate_dump_records(klass, ={}, &block) = ([:find]||{}).clone #pagination is not needed when :page_size => false if [:page_size].is_a?(FalseClass) yield klass.find(:all, ), 0 return end [:page_size]||= dumper_page_size #limit becomes the maximum amount of records to pull max_records = [:limit] page_num = 0 [:limit] = compute_page_size(max_records, page_num, [:page_size]) records = [] while ([:limit] > 0 && (page_num == 0 || records.length == [:page_size])) records = klass.find :all, .update(:offset => page_num * [:page_size]) yield records, page_num page_num = page_num + 1 #calculate the limit if an original limit (max_records) was set [:limit] = compute_page_size(max_records, page_num, [:page_size]) end end |
.paginate_each_record(klass, options = {}, &block) ⇒ Object
Quick and dirty paginate to loop thru each page Options are:
-
:find
- a map of the finder options passed to find. For example, + => [‘hairy = ?’, ‘of course’], :include => :rodents + -
:page_size
- the page size to use. Defaults to dumper_page_size or 50. Set to false to disable pagination
450 451 452 453 454 455 456 457 |
# File 'lib/ar_dumper_base.rb', line 450 def self.paginate_each_record(klass, ={}, &block) counter = -1 paginate_dump_records(klass, ) do |records, page_num| records.each do |record| yield record, (counter +=1) end end end |
Instance Method Details
#build_attribute_list ⇒ Object
build a list of attributes, methods and procs
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/ar_dumper_base.rb', line 95 def build_attribute_list#:nodoc: if [:only] [:attributes] = Array([:only]) else [:attributes] = @klass.column_names - Array([:except]).collect { |e| e.to_s } end [:attributes] = [:attributes].collect{|attr| "#{attr}"} [:methods] = [:methods].is_a?(Hash) ? [:methods].values : Array([:methods]) #if procs are specified as an array separate the headers(keys) from the procs(values) if [:procs].is_a?(Hash) [:proc_headers]= [:procs].keys [:procs]= [:procs].values else [:procs] = Array([:procs]) [:proc_headers]||= Array.new 0.upto([:procs].size - [:proc_headers].size - 1) {|idx| [:proc_headers] << "proc_#{idx}" } end end |
#build_header_list ⇒ Object
Returns an array with the header names This will be in the same order as the data returned by dump_record attributes + methods + procs
:header
The header defaults to the attributes and method names. When set
to false no header is specified
* +hash+ A map from attribute or method name to Header column name
* +array+ A list in the same order that is used to display record data
:procs
If a hash, then the keys are the names. If an array, then use proc_1, proc_2, etc :text_format
Format names with a text format such as :titlieze
, :dasherize
, :underscore
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 |
# File 'lib/ar_dumper_base.rb', line 319 def build_header_list#:nodoc: = [:header] columns = [:attributes] + [:methods] header_names = if .is_a?(Hash) .symbolize_keys! #Get the header for each attribute and method columns.collect{|field|([field.to_sym]||field).to_s} #ordered by attributes, methods, then procs elsif .is_a?(Array) header_names = header_names.concat(columns[.length..-1]) if header_names.length < columns.length #default to column names else columns end #add process names header_names.concat([:proc_headers]) #format names with a text format such as titlieze, dasherize, underscore header_names.collect!{|n| n.to_s.send([:text_format])} if [:text_format] header_names end |
#csv_writer ⇒ Object
Try to use the FasterCSV if it exists otherwise use csv
295 296 297 298 299 300 301 302 303 304 305 306 |
# File 'lib/ar_dumper_base.rb', line 295 def csv_writer #:nodoc: unless @@csv_writer @@csv_writer = :faster begin require 'faster_csv' ::FasterCSV rescue Exception => exc @@csv_writer = :normal end end @@csv_writer end |
#dump(format) ⇒ Object
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/ar_dumper_base.rb', line 120 def dump(format) case format.to_sym when :csv dump_to_csv when :xml dump_to_xml when :yaml, :fixture, :yml dump_to_fixture else raise ArDumperException.new("Unknown format #{format}. Please specify :csv, :xml, or :yml ") end end |
#dump_record(record) ⇒ Object
collect the record data into an array
172 173 174 175 176 177 |
# File 'lib/ar_dumper_base.rb', line 172 def dump_record(record) record_values = [:attributes].inject([]){|values, attr| values << record["#{attr}"]; values } record_values = [:methods].inject(record_values) {|values, method| values << record.send(method); values } record_values = [:procs].inject(record_values){|values, proc| values << proc.call(); values } record_values end |
#dump_to_csv ⇒ Object
CSV DUMPER
Dump csv data
-
:csv
- any options to pass to csv parser. :col_sep Example + :csv => => “t” + :row_sep Row seperator -
:page_size
- the page size to use. Defaults to dumper_page_size or 50
269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/ar_dumper_base.rb', line 269 def dump_to_csv header = nil [:csv]||={} if ![:header].is_a?(FalseClass) header_list = build_header_list #print the header unless set to false header = write_csv_row(header_list) end dumper(:csv, header) do |record| [:target] << write_csv_row(dump_record(record)) end end |
#dump_to_fixture ⇒ Object
Yaml/Fixture Dumper
dumps the data to a fixture file In addition to options listed in dumper
: :root
Basename of the record. Defaults to the class name so each record is named customer_1
244 245 246 247 248 249 250 251 252 253 254 255 |
# File 'lib/ar_dumper_base.rb', line 244 def dump_to_fixture basename = [:root]||@klass.table_name.singularize header_list = build_header_list # doctor the yaml a bit to print the hash header at the top # instead of each record dumper(:yml, "---\s") do |record| record_data = Hash.new dump_record(record).each_with_index{|field, idx| record_data[header_list[idx].to_s] = field.to_s } [:target] << {"#{basename}_#{record.id}" => record_data}.to_yaml.gsub(/^---\s\n/, "\n") end end |
#dump_to_xml ⇒ Object
XML Dumper
Dumps the data to an xml file
Using the ActiveRecord version of dumper so we CANNOT specify fields that are not attributes
In addition to options listed in dumper
:
-
:xml
- xml options for ActiveRecord .to_xml
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/ar_dumper_base.rb', line 190 def dump_to_xml #preserve the original skip instruct skip_instruct = [:skip_instruct].is_a?(TrueClass) #use the fields if :only is not specified in the xml options ={:only => [:only], :except => [:except], :methods => [:methods], :procs => [:procs] } .update([:xml]) if [:xml] #do not instruct for each set [:skip_instruct] = true [:indent]||=2 [:margin] = [:margin].to_i + 1 #set the variable on the options [:xml] = #builder for header and footer = { :margin => [:margin] - 1, :indent => [:indent] } [:root] = ([:root] || @klass.to_s.underscore.pluralize).to_s #use the builder to make sure we are indented properly builder = Builder::XmlMarkup.new(.clone) builder.instruct! unless skip_instruct builder << "<#{options[:root]}>\n" header = builder.target! #get the footer. Using the builder will make sure we are indented properly builder = Builder::XmlMarkup.new() builder << "</#{options[:root]}>" = builder.target! dumper(:xml, header, ) do |record| [:target] << record.to_xml(.dup) end end |
#dumper(file_extension = nil, header = nil, footer = nil, &block) ⇒ Object
Wrapper around the outside of dumper See options in dumper
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 |
# File 'lib/ar_dumper_base.rb', line 139 def dumper(file_extension=nil, header = nil, = nil, &block) [:counter] = -1 begin #get the file parameters target = prepare_target(file_extension) target << header if header ArDumper.paginate_dump_records(@klass, ) do |records, page_num| #save state on options to make it accessible by #class and procs [:result_set] = records [:page_num] = page_num records.each do |record| [:record] = record yield record end #flush after each set target.flush if target.respond_to?(:flush) end target << if #final step close the options[:target] ensure target.close if target && target.respond_to?(:close) end [:full_file_name]||target end |
#prepare_target(file_extension = nil) ⇒ Object
Create the options(file) based on these options. The options must respond to << Current optionss are :string, :file, :tempfile
:target_type
The options for the data. Defaults to :file
* :string prints to string. Do not use with large data sets
* :tmp_file. Use a temporary file that is destroyed when the process exists
* :file. Use a standard file
:filename
basename of the file. Defaults to random time based string for non-temporary files :file_extension
Extension (suffix) like .csv, .xml. Added only if the basename has no suffix.
:file_extension is only available when +:target_type_type => :file+
:file_path
path or directory of the file. Defaults to dumper_file_path or temporary directories
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 |
# File 'lib/ar_dumper_base.rb', line 365 def prepare_target(file_extension = nil) [:target] = case [:target_type] #to string option dumps to a string instead of a file when :string String.new #use a temporary file #open a temporary file with the basename specified by filename #defaults to the value of one of the environment variables TMPDIR, TMP, or TEMP when :tmp_file Tempfile.open([:filename]||(@@dumper_tmp_file_basename+@klass.name.downcase), [:file_path]||@@dumper_file_path) #default to a real file else extension = [:file_extension]||file_extension mode = [:append_to_file].is_a?(TrueClass)? 'a' : 'w' filename = [:filename]||"#{@@dumper_tmp_file_basename}.#{@klass.name.downcase}.#{Time.now.to_f.to_s}.#{extension}" #append an extension unless one already exists filename += ".#{extension}" if extension && !filename =~ /\.\w*$/ #get the file path if the filename does not contain one if File.basename(filename) == filename path = [:file_path]||@@dumper_file_path filename = File.join(path, filename) unless path.blank? end File.open(filename, mode) end [:full_file_name] = [:target].path if [:target].respond_to?(:path) [:target] end |
#write_csv_row(row_data, header_list = []) ⇒ Object
Write out the csv row using the selected csv writer
285 286 287 288 289 290 291 |
# File 'lib/ar_dumper_base.rb', line 285 def write_csv_row(row_data, header_list=[])#:nodoc: if csv_writer == :faster ::FasterCSV::Row.new(header_list, row_data).to_csv([:csv]) else ::CSV.generate_line(row_data, [:csv][:col_sep], [:csv][:row_sep]) + ([:csv][:row_sep]||"\n") end end |