Class: Db::Sync

Inherits:
Object
  • Object
show all
Includes:
ActiveSupport::Configurable
Defined in:
lib/db/sync.rb,
lib/db/sync/version.rb

Overview

Databse Sync

Defined Under Namespace

Classes: Diff, Model, Railtie

Constant Summary collapse

VERSION =
'0.0.15'.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sync_dir = nil, tables = nil) ⇒ Sync

Returns a new instance of Sync.



14
15
16
17
# File 'lib/db/sync.rb', line 14

def initialize(sync_dir = nil, tables = nil)
  self.sync_dir = File.join((Rails.root || '.'), 'db', (sync_dir || 'data'))
  self.custom_tables = tables
end

Instance Attribute Details

#custom_tablesObject

Returns the value of attribute custom_tables.



12
13
14
# File 'lib/db/sync.rb', line 12

def custom_tables
  @custom_tables
end

#sync_dirObject

Returns the value of attribute sync_dir.



12
13
14
# File 'lib/db/sync.rb', line 12

def sync_dir
  @sync_dir
end

Instance Method Details

#all_tablesObject



120
121
122
123
124
# File 'lib/db/sync.rb', line 120

def all_tables
  ActiveRecord::Base.connection.tables.reject do |table|
    %w(schema_info, schema_migrations).include?(table)
  end
end

#configure {|config| ... } ⇒ Object

Yields:

  • (config)


130
131
132
# File 'lib/db/sync.rb', line 130

def configure
  yield(config)
end

#data_model(table) ⇒ Object



134
135
136
137
138
# File 'lib/db/sync.rb', line 134

def data_model(table)
  result = Class.new(Db::Sync::Model)
  result.table_name = table
  result
end

#delete_records(table, deletes, commit = false) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/db/sync.rb', line 59

def delete_records(table, deletes, commit = false)
  arel_model = Arel::Table.new(table)

  deletes.each do |delete_params|
    log << "[#{table}] DELETE #{delete_params}"
    next unless commit

    delete_manager = Arel::DeleteManager.new
    delete_manager.from(arel_model)
    delete_data = delete_params.map do |key, value|
      [arel_model[key].eq(value)]
    end

    delete_manager.where(delete_data)
    # print "#{delete_manager.to_sql}\n"
    ActiveRecord::Base.connection.execute(delete_manager.to_sql)
  end
end

#insert_records(table, inserts, commit = true) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/db/sync.rb', line 42

def insert_records(table, inserts, commit = true)
  inserts.each do |record|
    log << "[#{table}] INSERT #{record}"
    next unless commit

    insert_manager = Arel::InsertManager.new
    arel_model = Arel::Table.new(table)
    insert_data = record.map do |key, value|
      [arel_model[key], value]
    end

    insert_manager.insert(insert_data)
    # print "#{insert_manager.to_sql}\n"
    ActiveRecord::Base.connection.execute(insert_manager.to_sql)
  end
end

#logObject



19
20
21
# File 'lib/db/sync.rb', line 19

def log
  @log ||= []
end

#sync_downObject



99
100
101
102
103
104
105
106
107
108
# File 'lib/db/sync.rb', line 99

def sync_down
  # TODO: change to row by row saving
  Dir.mkdir(sync_dir) unless Dir.exist?(sync_dir)
  working_tables.each do |table|
    File.open(table_filename(table), 'w') do |f|
      current_records = table_model_records(table)
      f << current_records.to_yaml
    end
  end
end

#sync_up(commit = true) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/db/sync.rb', line 23

def sync_up(commit = true)
  @log = []
  # TODO: change to row by row loading
  working_tables.each do |table|
    table_model = data_model(table)
    fail 'Tables without id are not supported!' unless table_model.include_id?

    data = File.read(table_filename(table))
    all_records = YAML.load(data)
    current_records = table_model.records

    diff = Db::Sync::Diff.new(current_records, all_records, table_model.pkey)
    delete_records(table, diff.deletes, commit)
    update_records(table, diff.updates, commit)
    insert_records(table, diff.inserts, commit)
    # TODO: fix auto increments
  end
end

#table_filename(table) ⇒ Object



126
127
128
# File 'lib/db/sync.rb', line 126

def table_filename(table)
  File.join(sync_dir, "#{table}.yml")
end

#table_model_records(table) ⇒ Object



110
111
112
113
114
# File 'lib/db/sync.rb', line 110

def table_model_records(table)
  # TODO: Some kind of paging
  table_model = data_model(table)
  table_model.records
end

#update_records(table, updates, commit = false) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/db/sync.rb', line 78

def update_records(table, updates, commit = false)
  arel_model = Arel::Table.new(table)

  updates.each do |update|
    log << "[#{table}] UPDATE #{update[:key]} with #{update[:changes]}"
    next unless commit

    update_manager = Arel::UpdateManager.new
    update_key = update[:key].map do |key, value|
      [arel_model[key].eq(value)]
    end
    update_changes = update[:changes].map do |key, value|
      [arel_model[key], value]
    end

    update_manager.table(arel_model).where(update_key).set(update_changes)
    # print "#{update_manager.to_sql}\n"
    ActiveRecord::Base.connection.execute(update_manager.to_sql)
  end
end

#working_tablesObject



116
117
118
# File 'lib/db/sync.rb', line 116

def working_tables
  custom_tables || config.tables || all_tables
end