Module: HasManyVersions

Defined in:
lib/has_many_versions.rb

Defined Under Namespace

Classes: HistoryItem

Instance Method Summary collapse

Instance Method Details

#<<(*records) ⇒ Object Also known as: push, concat



67
68
69
70
71
# File 'lib/has_many_versions.rb', line 67

def <<(*records)
  upgrade_proxy_object do |new_version|
    add_records_without_versioning_transaction(new_version, records)
  end
end

#add_records_without_versioning_transaction(new_version, records, excluded_ids = []) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/has_many_versions.rb', line 37

def add_records_without_versioning_transaction(new_version, records, excluded_ids = [])
  changing_records = flatten_deeper(records).select{ |r|
    (!r.new_record? && (r.changed? || (r.version != (new_version - 1))))
  }
  excluded_ids.concat(changing_records.collect(&:id)) unless changing_records.empty?
  excluded_ids.empty? ? 
    proxy_reflection.klass.update_all(
      ['version = ?', new_version], 
      ["#{proxy_reflection.primary_key_name} = ? and version = ?", proxy_owner.id, new_version - 1]
    ) : proxy_reflection.klass.update_all(
      ['version = ?', new_version], 
      ["#{proxy_reflection.primary_key_name} = ? and version = ? and #{proxy_reflection.klass.primary_key} not in (?)", proxy_owner.id, new_version - 1, excluded_ids]
    )
  records = flatten_deeper(records).collect do |r|
    if changing_records.include?(r)
      new_r = r.clone
      new_r.from_version = r.id if new_r.respond_to?(:from_version=)
      new_r
    else
      r
    end
  end
  flatten_deeper(records).each do |record|
    record.initial_version = proxy_owner.version if record.initial_version.nil? or record.new_record?
    record.version = proxy_owner.version
  end
  __concat__(*records)
end

#at(target_version) ⇒ Object



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

def at(target_version)
  proxy_reflection.klass.find(:all, :conditions => ["#{proxy_reflection.primary_key_name} = ? and initial_version <= ? and version >= ?", proxy_owner.id, target_version, target_version])
end

#conditionsObject



86
87
88
89
90
# File 'lib/has_many_versions.rb', line 86

def conditions
  interpolate_sql(@reflection.sanitized_conditions ?
    '%s AND %s.version = #{version}' % [@reflection.sanitized_conditions, proxy_reflection.quoted_table_name] :
    '%s.version = #{version}' % [proxy_reflection.quoted_table_name])
end

#delete_records(records) ⇒ Object



80
81
82
83
84
# File 'lib/has_many_versions.rb', line 80

def delete_records(records)
  upgrade_proxy_object do |new_version|
    delete_records_without_versioning_transaction(new_version, records)
  end
end

#delete_records_without_versioning_transaction(new_version, records) ⇒ Object



76
77
78
# File 'lib/has_many_versions.rb', line 76

def delete_records_without_versioning_transaction(new_version, records)
  proxy_reflection.klass.update_all ['version = ?', new_version], ["#{proxy_reflection.primary_key_name} = ? and version = ? and #{proxy_reflection.klass.primary_key} not in (?)", proxy_owner.id, new_version - 1, records.collect(&proxy_reflection.klass.primary_key.to_sym)]
end

#history(from = [proxy_owner.version - 10, 1].max, to = proxy_owner.version) ⇒ Object



92
93
94
95
96
97
98
99
100
101
# File 'lib/has_many_versions.rb', line 92

def history(from = [proxy_owner.version - 10, 1].max, to = proxy_owner.version)
  history_items = proxy_reflection.klass.find(:all, :conditions => ["#{proxy_reflection.primary_key_name} = ? and version >= ? and initial_version <= ?", proxy_owner.id, from, to])
  to = proxy_owner.version if to > proxy_owner.version
  from = 1 if from < 1
  (from..to).collect do |version|
    HistoryItem.new(version, history_items.select { |item| 
      item.initial_version <= version && item.version >= version
    })
  end
end

#replace(other_array) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/has_many_versions.rb', line 24

def replace(other_array)
  other_array.each { |val| raise_on_type_mismatch(val) }

  load_target
  other   = other_array.size < 100 ? other_array : other_array.to_set
  current = @target.size < 100 ? @target : @target.to_set

  upgrade_proxy_object do |new_version|
    delete_records_without_versioning_transaction(new_version, @target.select { |v| !other.include?(v) })
    add_records_without_versioning_transaction(new_version, other_array.select { |v| !current.include?(v) }, @target.select { |v| !other.include?(v) }.collect(&:id))
  end
end

#rollback(target_version = proxy_owner.version - 1) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/has_many_versions.rb', line 103

def rollback(target_version = proxy_owner.version - 1)
  return if target_version == proxy_owner.version
  upgrade_proxy_object do |new_version|
    proxy_reflection.klass.find(:all, :conditions => ["#{proxy_reflection.primary_key_name} = ? and initial_version <= ? and version >= ?", proxy_owner.id, target_version, target_version]).each do |new_record|
      new_record = new_record.clone
      new_record.initial_version = new_version
      new_record.version = new_version
      new_record.save!
    end
  end

end

#upgrade_proxy_objectObject



13
14
15
16
17
18
19
20
21
22
# File 'lib/has_many_versions.rb', line 13

def upgrade_proxy_object
  proxy_owner.transaction do
    new_version = proxy_owner.version + 1
    proxy_owner.version = new_version
    proxy_owner.class.update_all ['version = ?', new_version], ["#{proxy_reflection.klass.primary_key} = ?", proxy_owner.id]
    proxy_owner.save!
    yield new_version
    proxy_owner.reload
  end
end