45
46
47
48
49
50
51
52
53
54
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
# File 'lib/versionable/plugins/versionable.rb', line 45
def enable_versioning(opts={})
attr_accessor :rolling_back
key :version_number, Integer, :default => 0
define_method(:version_message) do
@version_message
end
define_method(:version_message=) do |message|
@version_message = message
end
define_method(:versions_count) do
@versions_count ||= Version.count(:doc_id => self._id.to_s)
end
define_method(:versions) do
@limit ||= opts[:limit] || 10
@versions ||= Version.all(:doc_id => self._id.to_s, :order => 'pos desc', :limit => @limit).reverse
end
define_method(:all_versions) do
Version.where(:doc_id => self._id.to_s).sort(:pos.desc)
end
define_method(:delete_version) do |pos|
case pos
when :all
@versions_count = 0
self.all_versions.each(&:delete)
else
@versions_count -= 1
self.version_at(pos).delete
self.all_versions.where(['pos > ?', pos]).each do |version|
version.update_attributes(:pos => version.pos - 1)
end
end
end
define_method(:rollback) do |*args|
pos = args.first pos = self.versions.count-2 if pos.nil?
version = self.version_at(pos)
if version
possible_keys = (self.attributes.keys + version.data.keys).uniq.compact
possible_keys.each do |key|
self.send(:"#{key}=", version.data[key]) if self.respond_to?(:"#{key}=")
end
end
self.version_number = version.pos
self
end
define_method(:rollback!) do |*args|
pos = args.first self.rollback(pos)
@rolling_back = true
save!
@rolling_back = false
self
end
define_method(:diff) do |key, pos1, pos2, *optional_format|
format = optional_format.first || :html version1 = self.version_at(pos1)
version2 = self.version_at(pos2)
Differ.diff_by_word(version1.content(key), version2.content(key)).format_as(format)
end
define_method(:current_version) do
data = self.attributes
data.delete(:version_number)
Version.new(:data => data, :date => Time.now, :doc_id => self._id.to_s)
end
define_method(:version_at) do |pos|
case pos
when :current
current_version
when :first
index = self.versions.index {|v| v.pos == 0}
version = self.versions[index] if index
version ||= Version.first(:doc_id => self._id.to_s, :pos => 0)
version
when :last
self.versions[self.versions.count-2]
when :latest
self.versions.last
else
index = self.versions.index {|v| v.pos == pos}
version = self.versions[index] if index
version ||= Version.first(:doc_id => self._id.to_s, :pos => pos)
version
end
end
end
|