From c95b75b879399b3f05bcf176c8644293cc36264f Mon Sep 17 00:00:00 2001 From: Don Morrison Date: Sun, 5 Mar 2017 19:59:33 -0800 Subject: [PATCH] Extract csv file handling to `CSV::Storage` Adds `CSV::Storage` to perform the reading and writing to csv files. The new class is used in the `Dataset` and the `Gateway`. The connection is passed in to the dataset to keep the command functionality working. --- lib/rom/csv/dataset.rb | 33 ++++++++++++--------------- lib/rom/csv/gateway.rb | 11 +++------ lib/rom/csv/storage.rb | 52 ++++++++++++++++++++++++++++++++++++++++++ lib/rom/csv/types.rb | 4 ++++ 4 files changed, 73 insertions(+), 27 deletions(-) create mode 100644 lib/rom/csv/storage.rb diff --git a/lib/rom/csv/dataset.rb b/lib/rom/csv/dataset.rb index 838df77..533066c 100644 --- a/lib/rom/csv/dataset.rb +++ b/lib/rom/csv/dataset.rb @@ -1,17 +1,24 @@ require 'rom/memory/dataset' +require 'rom/csv/storage' module ROM module CSV + # Type definition used to constrain the `connection` option + StorageType = Types.Definition(Storage).constrained(type: Storage) + # Dataset for CSV # # @api public class Dataset < ROM::Memory::Dataset - option :path, + + # Connection to the file + # + # @return [Storage] + # + # @api private + option :connection, optional: true, - type: Types::Strict::String - option :file_options, - default: proc { {} }, - type: Types::Strict::Hash + type: StorageType # Convert each CSV::Row to a hash # @@ -21,23 +28,11 @@ def self.row_proc end def reload! - @data = load_data + @data = connection.load end def sync! - write_data && reload! - end - - def write_data - ::CSV.open(path, 'wb', file_options) do |csv| - data.to_a.each do |tuple| - csv << tuple - end - end - end - - def load_data - ::CSV.table(path, file_options).by_row! + connection.dump(data) && reload! end def count diff --git a/lib/rom/csv/gateway.rb b/lib/rom/csv/gateway.rb index 7b060cc..9ef86a2 100644 --- a/lib/rom/csv/gateway.rb +++ b/lib/rom/csv/gateway.rb @@ -2,6 +2,7 @@ require 'rom/initializer' require 'rom/csv/dataset' require 'rom/csv/commands' +require 'rom/csv/storage' # Ruby Object Mapper # @@ -72,7 +73,7 @@ class Gateway < ROM::Gateway def initialize(*) super @datasets = {} - @connection = ::CSV.table(path, csv_options).by_row! + @connection = Storage.new(path, csv_options) end # Return dataset with the given name @@ -94,7 +95,7 @@ def [](name) # # @api public def dataset(name) - datasets[name] = Dataset.new(connection, dataset_options) + datasets[name] = Dataset.new(connection.load, connection: connection) end # Check if dataset exists @@ -105,12 +106,6 @@ def dataset(name) def dataset?(name) datasets.key?(name) end - - private - - def dataset_options - { path: path, file_options: csv_options } - end end end end diff --git a/lib/rom/csv/storage.rb b/lib/rom/csv/storage.rb new file mode 100644 index 0000000..8c3b888 --- /dev/null +++ b/lib/rom/csv/storage.rb @@ -0,0 +1,52 @@ +require 'csv' +require 'rom/initializer' + +module ROM + module CSV + # CSV file storage for datasets + # + # @api private + class Storage + extend Initializer + + # Path to the file + # + # @return [String] + # + # @api private + param :path, + type: Types::Strict::String + + # Options for file passed to `CSV` + # + # @return [Hash] + # + # @api private + param :csv_options, + default: proc { {} }, + type: Types::Strict::Hash + + # Dump the data to the file at `path` + # + # @return [undefined] + # + # @api public + def dump(data) + ::CSV.open(path, 'wb', csv_options) do |csv| + data.to_a.each do |tuple| + csv << tuple + end + end + end + + # Load the data from the file at `path` + # + # @return [CSV::Table] + # + # @api public + def load + ::CSV.table(path, csv_options).by_row! + end + end + end +end diff --git a/lib/rom/csv/types.rb b/lib/rom/csv/types.rb index f496816..8b939d6 100644 --- a/lib/rom/csv/types.rb +++ b/lib/rom/csv/types.rb @@ -4,6 +4,10 @@ module ROM module CSV module Types include ROM::Types + + def self.Definition(primitive) + Dry::Types::Definition.new(primitive) + end end end end