dumb_delimited

A library for unsophisticated delimited flat file IO. dumb_delimited mixes models and persistence in that "probably wrong but feels so right" kind of way.

Usage Example

Let's say we have a products file "products.csv", and a customers file "customers.psv".

"products.csv" is a comma-delimited flat file and has four columns: SKU, Product Name, Base Price, and Sale Price. An example row from "products.csv" might be:

AB81H0F,Widget Alpha,899.99,499.99

"customers.psv" is a pipe-delimited flat file and has three columns: Customer Name, Email, and Address. An example row from "customers.psv" might be:

Bob Bobbington|[email protected]|808 Bounce Lane, Austin, TX 78703

To interact with these files, we create model classes via the DumbDelimited#[] method. Note that a created class can either be used as a superclass or simply assigned to a constant.

class Product < DumbDelimited[:sku, :name, :base_price, :sale_price]
  def on_sale?
    sale_price < base_price
  end
end

Customer = DumbDelimited[:name, :email, :address]
Customer.delimiter = "|"

Because "customers.psv" is pipe-delimited, we also set the delimiter for the Customer class. By default, model classes use comma (",") as the delimiter. Whenever a delimiter is set, it applies to all future IO operations for that model class.

Now we can read each flat file, and recieve an array of model objects.

products = Product.parse_file("products.csv")
customers = Customer.parse_file("customers.psv")

This, however, will load the entire contents of each file into memory. Let's say our customers file is very large, and we would prefer to iterate over it rather than load it all into memory at once. To do so, we can use the each_in_file method that the model class provides. Below is a complete example in which we load our product data, create a listing of products on sale, and iterate over our customers, notifying each customer of the sale products:

products = Product.parse_file("products.csv")

listing = products.select(&:on_sale?).map do |product|
  "* #{product.name} (#{product.sale_price})"
end.join("\n")

Customer.each_in_file("customers.psv") do |customer|
  message =
    "Hi #{customer.name}!\n\n" \
    "The following products are on sale:\n\n#{listing}"

  notify(customer.email, message)
end

Let's say the sale is now over, and we want to change our sale prices back to our base prices. dumb_delimited includes the pleasant_path gem, which offers a fluent API for writing files. To finish our task, we use the Array#write_to_file method provided by pleasant_path, which in turn invokes Product#to_s (provided by dumb_delimited) on each model object.

Product.parse_file("products.csv").each do |product|
  product.sale_price = product.base_price
end.write_to_file("products.csv")

For a more detailed explanation of the dumb_delimited API, browse the full documentation.

Installation

$ gem install dumb_delimited

Development

Run rake test to run the tests. You can also run rake irb for an interactive prompt that pre-loads the project code.

License

MIT License