db_facet
By Bettercall.io.
db_facet recursively fetches records from a database and generates a tree structure representing the records and its relations. This structure can be stored and read by DbSpiderWeaver to insert the data into the database again.
It`s designed for fast database writes (relying on raw SQL bulk INSERT`s with activerecord-import) and supports rails globalize.
Common usages would be to export and import an account, or build a fresh account by cloning an existing one.
db_facet is written to work on RubyOnRails, but can be used in any system just by writing the activerecord models and its relations representing your database.
Installation
Add this line to your application's Gemfile:
gem 'db_facet'
And then execute:
$ bundle
Or install it yourself as:
$ gem install db_facet
Usage
Here is a sample class using db_facet.
It clones an user account with all its dependencies to a fresh new account.
# Usage:
# new_attrs = {name: 'Demo account', email: 'demo@example.com'}
# new_account = CloneAccount.new(template_user.id, new_attrs).build
class CloneAccount
INCLUDE_TEMPLATE_MODELS = %w(
User
Album
Photo
Video
Invoice
)
def initialize template_user_id, new_attrs
@template_user_id = template_user_id
@new_attrs = new_attrs.deep_dup
end
def build
seed = fetch_seed @template_user_id
override_seed! seed, template_overrides(User.new)
new_user_id = save! seed
User.find new_user_id
end
private
def template_overrides user
@new_attrs.delete "password"
@new_attrs.delete "session_token"
@new_attrs.merge!(
profile_theme: 34
)
# children overrides
@new_attrs.merge!(
lang_config: {locale: 'fr'},
invoices: lambda {|data| data[:cc_end] = nil }
)
@new_attrs
end
# db_facet interface
def fetch_seed template_user_id
Rails.cache.fetch "account-seed-#{template_user_id}" do
DbSpider.new(User.find(template_user_id), INCLUDE_MODELS).spide
end
end
def override_seed! seed, overrides
DbSpiderRootMerger.new(seed).merge! overrides
end
def save! seed
DbSpiderWeaver.new(seed, timer: true).weave!
end
end
Hash structure
{
class_name: 'User',
data: {name: 'Chuck Norris!'},
reflections: {
albuns: [
{
class_name: 'Albuns',
data: {name: 'Day off 2017/02'},
reflections: {
photos: ...
Classes
Class | description |
---|---|
DbSpider | Crawls db and generates the Hash structure. |
DbSpiderReaderNode | Wrapper for an AR model record. |
DbSpiderNodeSet | Proxy class to instantiate and reuse DbSpiderReaderNode`s. |
DbSpiderWeaver | Reads the Hash structure generated by DbSpider and INSERTS`s into the database. |
DbSpiderWriterNode | Wrapper for a node generated by DbSpiderReaderNode. |
DbSpiderRootMerger | Apply a diff to the Hash structure. Accepts a simplified data structure as parameter. |
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake test
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/tomlobato/db_facet.
License
The gem is available as open source under the terms of the MIT License.