README.md
# db_facet
[![Gem Version](https://badge.fury.io/rb/db_facet.svg)](https://badge.fury.io/rb/db_facet)
[![Code Climate](https://codeclimate.com/github/tomlobato/db_facet.svg)](https://codeclimate.com/github/tomlobato/db_facet)
![](http://ruby-gem-downloads-badge.herokuapp.com/db_facet?type=total&label=gem%20downloads)
By [Bettercall.io](https://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](https://github.com/zdennis/activerecord-import)) and supports rails [globalize](https://github.com/globalize/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:
```ruby
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.
```ruby
# 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
```yml
{
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](https://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](http://opensource.org/licenses/MIT).