class RailsSync::Analyzer

Attributes

adapter[R]
dest_arel_table[R]
my_arel_table[R]
synchro_type[R]

Public Class Methods

new(options = {}) click to toggle source
# File lib/rails_sync/analyzer.rb, line 5
def initialize(options = {})
  @adapter = RailsSync::Adapter.new(options[:dest])
  @dest = options[:dest]
  @record = options[:record]
  @server_id = options[:server_id]

  @synchro_type = @record.name
  @table_name = @record.table_name
  @dest_table = options[:dest_table]
  @primary_key = options[:primary_key]
  @dest_primary_key = options[:dest_primary_key]
  @dest_conditions = Hash(options[:dest_conditions])

  @full_mappings = options[:full_mappings]
  @my_columns = @primary_key + @full_mappings.map { |col| col[0] }
  @dest_columns = @dest_primary_key + @full_mappings.map { |col| col[1] }

  instance_table
  @my_arel_table ||= Arel::Table.new(@table_name)
  @dest_arel_table ||= Arel::Table.new(@dest_table_name, as: 't1')
end

Public Instance Methods

analyze_conditions() click to toggle source
# File lib/rails_sync/analyzer.rb, line 96
def analyze_conditions
  mappings = @full_mappings.map do |mapping|
    my_arel_table[mapping[0]].not_eq(dest_arel_table[mapping[1]])
  end
  Arel::Nodes::SqlLiteral.new mappings.map(&:to_sql).join(' OR ')
end
analyze_diffs(type = 'update') click to toggle source
# File lib/rails_sync/analyzer.rb, line 58
def analyze_diffs(type = 'update')
  return [] if skip_analyze?(type)
  sql = fetch_diffs(type)
  results = connection.execute(sql)
  fields = results.fields.in_groups(2).first
  results.map do |result|
    r = result.in_groups(2)
    hash_value = fields.zip( r[0].zip(r[1]) ).to_h
    hash_value.select do |key, v|
      v[0].to_s != v[1].to_s || @primary_key.include?(key)
    end
  end
end
analyze_table() click to toggle source
# File lib/rails_sync/analyzer.rb, line 90
def analyze_table
  attrs = @my_columns.map { |col| my_arel_table[col] }
  attrs += @dest_columns.map { |col| dest_arel_table[col] }
  my_arel_table.project(*attrs)
end
cache_diffs(type = 'update') click to toggle source
# File lib/rails_sync/analyzer.rb, line 36
def cache_diffs(type = 'update')
  analyze_diffs(type).each do |diff|
    audit = SyncAudit.new synchro_type: synchro_type

    _params = {}
    @primary_key.each do |primary_key|
      _params[primary_key] = diff.delete(primary_key).compact.first
    end

    audit.synchro_params = _params
    audit.synchro_id = _params['id']

    audit.operation = type
    audit.audited_changes = diff
    begin
      audit.save
    rescue ActiveRecord::ValueTooLong => e # todo not require active record
      puts e.message
    end
  end
end
connection() click to toggle source
# File lib/rails_sync/analyzer.rb, line 27
def connection
  @record.connection
end
fetch_diffs(type = 'update') click to toggle source
# File lib/rails_sync/analyzer.rb, line 72
def fetch_diffs(type = 'update')
  if type == 'update'
    query = analyze_table.join(dest_arel_table).on(on_conditions)
    query.where(analyze_conditions)
  elsif type == 'insert'
    query = analyze_table.join(dest_arel_table, Arel::Nodes::RightOuterJoin).on(on_conditions)
    query.where(my_arel_table[@primary_key[0]].eq(nil))
  elsif type == 'delete'
    query = analyze_table.join(dest_arel_table, Arel::Nodes::OuterJoin).on(on_conditions)
    query.where(my_arel_table[@primary_key[0]].not_eq(nil).and(dest_arel_table[@dest_primary_key[0]].eq(nil)))
  else
    query = analyze_table.join(dest_arel_table, Arel::Nodes::FullOuterJoin).on(on_conditions)
  end

  query.where(where_conditions) if where_conditions.present?
  query.to_sql
end
on_conditions() click to toggle source
# File lib/rails_sync/analyzer.rb, line 103
def on_conditions
  mappings = @primary_key.map.with_index do |left_key, index|
    my_arel_table[left_key].eq(dest_arel_table[@dest_primary_key[index]])
  end
  Arel::Nodes::SqlLiteral.new mappings.map(&:to_sql).join(' AND ')
end
skip_analyze?(type) click to toggle source
# File lib/rails_sync/analyzer.rb, line 31
def skip_analyze?(type)
  ( type == 'delete' && !@primary_key.include?(@record.primary_key) ) ||
    ( type == 'insert' && @record.id_insert? && !@primary_key.include?(@record.primary_key) )
end
where_conditions() click to toggle source
# File lib/rails_sync/analyzer.rb, line 110
def where_conditions
  cons = @dest_conditions.map do |key, value|
    col, meth = key.to_s.split('-')
    dest_arel_table[col].send meth, value
  end

  Arel::Nodes::SqlLiteral.new cons.map(&:to_sql).join(' AND ')
end