relational_exporter
A gem to make it easy to export data from relational databases. RelationalExporter shines when your intended output is a "flat" CSV file, but your data is relational (each record can have multiple associated sub-records). Define your schema (once) in a familiar ActiveRecord-y way and leverage the robust model featureset. Once your schema is defined, define one or more output configurations which can be re-used to generate an export file.
TODO
- Add concurrency for faster exports
- Support multiple formats (currently only CSV)
- Improve DSL
- Clean up the code (revise worker/job model)
Installation
Add this line to your application's Gemfile:
gem 'relational_exporter'
And then execute:
$ bundle
Or install it yourself as:
$ gem install relational_exporter
Usage
# Define schemas
my_schema = {
person: {
table_name: :person,
primary_key: :id,
has_many: {
addresses: nil,
emails: nil
},
has_one: {
avatar: [{ foreign_key: :ref_id }]
}
},
avatar: {
table_name: :avatar,
belongs_to: {
person: [{ foreign_key: :ref_id }]
}
}
}
# Define output
my_output_config = {
format: :csv,
output: {
model: :person,
scope: {
where: "person.status = 'active'"
},
associations: {
emails: {},
avatar: {
scope: {
where: "ref_type like 'person'",
limit: 1,
order: "id desc"
}
}
}
}
}
# Define DB connection info
my_conn = {
adapter: 'mysql2',
host: ENV['DB_HOST'],
username: ENV['DB_USER'],
password: ENV['DB_PASS'],
database: 'my_database'
}
# Run the export!
r = RelationalExporter::Runner.new schema: my_schema, connection_config: my_conn, logger: Logger.new(STDERR)
r.export(my_output_config) do |record|
# examine the record and it's associations using any
# Active Record models that were defined in your schema!
puts record.class # => Person
# filter out the record if desired
record = nil if record.name == 'Bob'
end
Support for Active Model Serializers
Install the active_model_serializers
gem in your application to take advantage of easy serialization. For CSV exports, relational_exporter
will look for a serializer when rendering the CSV row. If your serializer implements the self.csv_header_prefix_for_key(key)
method, relational_exporter
will use that method to determine the column header for a given model attribute.
Example:
class PersonSerializer < ActiveModel::Serializer
attributes :id, :name, :brother_name
def self.csv_header_prefix_for_key(key)
key == :brother_name ? '' : 'Person'
end
end
Would generate a CSV header row like:
PersonId,PersonName,BrotherName
Notice how the 'BrotherName' is not prefixed with 'Person'
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request