db_facet
db_facet extracts and inserts subsets of a database content, like a full user account with all its photos, invoices and history.
DbSpider recursively fetch records from a database and generates a Hash structure representing the data entities and its relations.
The Hash structure can be read by DbSpiderWeaver to insert the data into the database again.
Common usages would be to export and import an account, or build a fresh account by cloning an existing one.
It`s designed to ensure a blazing fast database write (DbSpiderWeaver, that relies on activerecord-import) and supports rails globalize.
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 user.
# Usage:
# new_attrs = {name: 'Demo account', email: '[email protected]'}
# new_fresh_user = 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
tmp_user = build_user
override_seed! seed, overrides(tmp_user)
new_user_id = save! seed
User.find new_user_id
end
private
def template_overrides user
@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
def build_user
user.new
end
# db_facet interface
def fetch_seed template_user_id
# You could cache the generated data structure if using
# it often and it is viable to clear when changed.
# Rails.cache.fetch "export-import-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 descriptions
- 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.