lib/table_differ.rb
# pass a date or name fragment, receive the full snapshot name.
# it's ok to pass a snapshot name; it will be returned unchaged.
pass a date or name fragment, receive the full snapshot name.
it's ok to pass a snapshot name; it will be returned unchaged.
pass a date or name fragment receive the full snapshot name . it ' s ok to pass a snapshot name ; it will be returned unchaged .
def diff_snapshot options={}
      oldtable = snapshot_name(options[:old]) || snapshots.last
      newtable = snapshot_name(options[:new]) || table_name
      ignore = []
      if options[:ignore]
        ignore = Array(options[:ignore]).map(&:to_s)
      end
      columns = column_names - ignore
      cols = columns.map { |c| "#{c} as #{c}" }.join(", ")
      added =   find_by_sql("SELECT #{cols} FROM #{newtable} EXCEPT SELECT #{cols} FROM #{oldtable}")
      removed = find_by_sql("SELECT #{cols} FROM #{oldtable} EXCEPT SELECT #{cols} FROM #{newtable}")
      if options[:unique_by]
        added = table_differ_remap_objects(options[:unique_by], added, newtable)
        removed = table_differ_remap_objects(options[:unique_by], removed, oldtable)
      end
      changed = added & removed
      changed.each do |obj|
        orig = removed.find { |r| r == obj }
        raise "this is impossible" if orig.nil?
        obj.original_attributes = (orig.original_attributes || orig.attributes).except(*ignore)
      end
      added -= changed
      removed -= changed
      [*added, *removed].each { |o| o.original_attributes = nil }
      [added, removed, changed]
    end
def diff_snapshot options = { } oldtable = snapshot_name ( options [ :old ] ) || snapshots . last newtable = snapshot_name ( options [ :new ] ) || table_name ignore = [ ] if options [ :ignore ] ignore = Array ( options [ :ignore ] ) . map ( & :to_s ) end columns = column_names - ignore cols = columns . map { | c | "#{c} as #{c}" } . join ( ", " ) added = find_by_sql ( "SELECT #{cols} FROM #{newtable} EXCEPT SELECT #{cols} FROM #{oldtable}" ) removed = find_by_sql ( "SELECT #{cols} FROM #{oldtable} EXCEPT SELECT #{cols} FROM #{newtable}" ) if options [ :unique_by ] added = table_differ_remap_objects ( options [ :unique_by ] , added , newtable ) removed = table_differ_remap_objects ( options [ :unique_by ] , removed , oldtable ) end changed = added & removed changed . each do | obj | orig = removed . find { | r | r == obj } raise "this is impossible" if orig . nil? obj . original_attributes = ( orig . original_attributes || orig . attributes ) . except ( * ignore ) end added -= changed removed -= changed [ * added , * removed ] . each { | o | o . original_attributes = nil } [ added , removed , changed ] end
pass a date or name fragment, receive the full snapshot name.
pass a date or name fragment receive the full snapshot name .
# hm, none of this seems to matter...  TODO: mark appropriate objects read-only: obj.readonly! # AR always thinks the record is persisted in the db, even when it obviously isn't # added.each   { |o| o.instance_variable_set("@new_record", true) } unless table_name == oldtable # removed.each { |o| o.instance_variable_set("@new_record", true) } unless table_name == newtable # actually, it's probably more reliable just to use the presence of an id to determine if the record can be saved # [*added, *removed].select { |o| !o.id }.each { |o| o.instance_variable_set("@new_record", true) }
options
<not_specific>