Module: ArchiveMethods

Included in:
ActiveRecord::Base
Defined in:
lib/activerecord_archive.rb

Overview

:nodoc:

Instance Method Summary collapse

Instance Method Details

#do_archive(conditions, options = {}) ⇒ Object



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/activerecord_archive.rb', line 2

def do_archive(conditions, options = {})
  options[:prefix] = 'ar_archive_' unless options[:prefix]
  options[:prefix] = 'ar_archive_' if options[:prefix].blank?

  if self.respond_to?(:table_name)
    tabname = self.table_name
  else
    raise 'MissingTableName'
  end

  raise 'PrefixAndTableNameTooLong - maximum is 64 characters' if "#{options[:prefix]}#{tabname}".size > 64
  raise 'PrimaryKey id expected but not found' unless self.primary_key == 'id'

  # do a simple query first in case to cause an exception if there is an error in conditions
  ActiveRecord::Base.connection.execute("
    SELECT COUNT(*)
    FROM #{tabname}
    WHERE #{conditions}
  ")

  ActiveRecord::Base.connection.execute("
    CREATE TABLE IF NOT EXISTS #{options[:prefix]}#{tabname}
      LIKE #{tabname}
  ")

  # use replace into in case of duplicate inserts
  ActiveRecord::Base.connection.execute("
    REPLACE INTO #{options[:prefix]}#{tabname}
      SELECT * FROM #{tabname} WHERE #{conditions}
  ")

  if options[:recursive_foreign_key] && !options[:recursive_foreign_key].blank?
    # for self-referencing foreign keys, delete child records first
    # delete only records in parent table where ids match those in archive table
    ActiveRecord::Base.connection.execute("
      DELETE FROM #{tabname}
      WHERE #{tabname}.#{options[:recursive_foreign_key]} IS NOT NULL AND EXISTS(
        SELECT #{options[:prefix]}#{tabname}.id
        FROM #{options[:prefix]}#{tabname}
        WHERE #{options[:prefix]}#{tabname}.id = #{tabname}.id)
    ")
  end

  # delete only records in parent table where ids match those in archive table
  ActiveRecord::Base.connection.execute("
    DELETE FROM #{tabname}
    WHERE EXISTS(
      SELECT #{options[:prefix]}#{tabname}.id
      FROM #{options[:prefix]}#{tabname}
      WHERE #{options[:prefix]}#{tabname}.id = #{tabname}.id)
  ")
end

#do_restore(conditions, options = {}) ⇒ Object



55
56
57
58
59
60
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/activerecord_archive.rb', line 55

def do_restore(conditions, options = {})
  options[:prefix] = 'ar_archive_' unless options[:prefix]
  options[:prefix] = 'ar_archive_' if options[:prefix].blank?

  if self.respond_to?(:table_name)
    tabname = self.table_name
  else
    raise 'MissingTableName'
  end

  raise 'PrefixAndTableNameTooLong - maximum is 64 characters' if "#{options[:prefix]}#{tabname}".size > 64
  raise 'PrimaryKey id expected but not found' unless self.primary_key == 'id'

  # do a simple query first in case to cause an exception if there is an error in conditions
  ActiveRecord::Base.connection.execute("
    SELECT COUNT(*)
    FROM #{options[:prefix]}#{tabname}
    WHERE #{conditions}
  ")

  if options[:recursive_foreign_key] && !options[:recursive_foreign_key].blank?
    # use replace into in case of duplicate inserts
    # for self-referencing foreign keys, insert parent records first
    ActiveRecord::Base.connection.execute("
    REPLACE INTO #{tabname}
      SELECT * FROM #{options[:prefix]}#{tabname} WHERE (#{conditions}) AND #{options[:prefix]}#{tabname}.#{options[:recursive_foreign_key]} IS NULL
    ")
    # now insert child records
    ActiveRecord::Base.connection.execute("
    REPLACE INTO #{tabname}
      SELECT * FROM #{options[:prefix]}#{tabname} WHERE (#{conditions}) AND #{options[:prefix]}#{tabname}.#{options[:recursive_foreign_key]} IS NOT NULL
    ")
  else
    # use replace into in case of duplicate inserts
    ActiveRecord::Base.connection.execute("
    REPLACE INTO #{tabname}
      SELECT * FROM #{options[:prefix]}#{tabname} WHERE #{conditions}
    ")
  end

  # delete only records in archive table where ids match those in parent table
  ActiveRecord::Base.connection.execute("
    DELETE FROM #{options[:prefix]}#{tabname}
    WHERE EXISTS(
      SELECT #{tabname}.id
      FROM #{tabname}
      WHERE #{tabname}.id = #{options[:prefix]}#{tabname}.id)
  ")
end