Module: TableDiffer::ClassMethods
- Defined in:
- lib/table_differ.rb
Instance Method Summary collapse
-
#create_snapshot(suggestion = Time.now) ⇒ Object
creates a new snapshot.
-
#delete_snapshot(name) ⇒ Object
deletes the named snapshot.
-
#delete_snapshots(snaps = self.snapshots, &block) ⇒ Object
deletes every snapshot named in the array Model.delete_snapshots(:all) deletes all snapshots.
- #diff_snapshot(options = {}) ⇒ Object
- #restore_snapshot(name) ⇒ Object
-
#snapshot_name(name) ⇒ Object
pass a date or name fragment, receive the full snapshot name.
-
#snapshots ⇒ Object
returns an array of the snapshot names that currently exist.
- #table_differ_remap_objects(params, records, table) ⇒ Object
Instance Method Details
#create_snapshot(suggestion = Time.now) ⇒ Object
creates a new snapshot
35 36 37 38 39 |
# File 'lib/table_differ.rb', line 35 def create_snapshot suggestion=Time.now name = snapshot_name(suggestion) connection.execute("CREATE TABLE #{name} AS SELECT * FROM #{table_name}") name end |
#delete_snapshot(name) ⇒ Object
deletes the named snapshot
50 51 52 |
# File 'lib/table_differ.rb', line 50 def delete_snapshot name connection.execute("DROP TABLE #{snapshot_name(name)}") end |
#delete_snapshots(snaps = self.snapshots, &block) ⇒ Object
deletes every snapshot named in the array Model.delete_snapshots(:all) deletes all snapshots
56 57 58 59 |
# File 'lib/table_differ.rb', line 56 def delete_snapshots snaps=self.snapshots, &block snaps = snaps.select(&block) if block snaps.each { |name| delete_snapshot(name) } end |
#diff_snapshot(options = {}) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/table_differ.rb', line 87 def diff_snapshot ={} oldtable = snapshot_name([:old]) || snapshots.last newtable = snapshot_name([:new]) || table_name ignore = [] if [:ignore] ignore = Array([: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}") # 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) } if [:unique_by] added = table_differ_remap_objects([:unique_by], added, newtable) removed = table_differ_remap_objects([: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 |
#restore_snapshot(name) ⇒ Object
41 42 43 44 45 46 47 |
# File 'lib/table_differ.rb', line 41 def restore_snapshot name name = snapshot_name(name) raise "#{name} doesn't exist" unless connection.tables.include?(name) delete_all connection.execute("INSERT INTO #{table_name} SELECT * FROM #{name}") end |
#snapshot_name(name) ⇒ Object
pass a date or name fragment, receive the full snapshot name. it’s ok to pass a snapshot name; it will be returned unchaged.
15 16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/table_differ.rb', line 15 def snapshot_name name return nil if name.nil? if name.kind_of?(Date) || name.kind_of?(Time) name = name.strftime("%Y%m%d_%H%M%S") end unless name.index(table_name) == 0 name = "#{table_name}_#{name}" end name end |
#snapshots ⇒ Object
returns an array of the snapshot names that currently exist
30 31 32 |
# File 'lib/table_differ.rb', line 30 def snapshots connection.tables.grep(/^#{table_name}_/).sort end |
#table_differ_remap_objects(params, records, table) ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/table_differ.rb', line 61 def table_differ_remap_objects params, records, table model = self if table != table_name # create an exact copy of the model, but using a different table model = Class.new(self) model.table_name = table end params = Array(params) records.map do |record| result = record if record.id.nil? # don't look up real ActiveRecord object if we already have one args = params.inject({}) { |hash,key| hash[key] = record[key]; hash } real_record = model.where(args).first if real_record if model != self real_record = self.new(real_record.attributes) # convert fake model to real model end real_record.original_attributes = record.attributes result = real_record end end result end end |