paper_trail_manager 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/Gemfile +17 -0
  2. data/Gemfile.lock +147 -0
  3. data/LICENSE.txt +20 -0
  4. data/README.md +32 -0
  5. data/Rakefile +52 -0
  6. data/VERSION +1 -0
  7. data/app/controllers/paper_trail_manager/changes_controller.rb +109 -0
  8. data/app/helpers/paper_trail_manager/changes_helper.rb +99 -0
  9. data/app/views/paper_trail_manager/changes/_version.html.haml +32 -0
  10. data/app/views/paper_trail_manager/changes/index.atom.builder +44 -0
  11. data/app/views/paper_trail_manager/changes/index.html.haml +26 -0
  12. data/app/views/paper_trail_manager/changes/show.html.haml +8 -0
  13. data/lib/paper_trail_manager.rb +70 -0
  14. data/paper_trail_manager.gemspec +209 -0
  15. data/spec/controllers/paper_trail_manager/changes_controller_spec.rb +8 -0
  16. data/spec/dummy/Rakefile +7 -0
  17. data/spec/dummy/app/controllers/application_controller.rb +7 -0
  18. data/spec/dummy/app/controllers/entities_controller.rb +83 -0
  19. data/spec/dummy/app/controllers/platforms_controller.rb +83 -0
  20. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  21. data/spec/dummy/app/helpers/entities_helper.rb +2 -0
  22. data/spec/dummy/app/helpers/platforms_helper.rb +2 -0
  23. data/spec/dummy/app/models/entity.rb +6 -0
  24. data/spec/dummy/app/models/platform.rb +6 -0
  25. data/spec/dummy/app/views/entities/_form.html.erb +17 -0
  26. data/spec/dummy/app/views/entities/edit.html.erb +6 -0
  27. data/spec/dummy/app/views/entities/index.html.erb +21 -0
  28. data/spec/dummy/app/views/entities/new.html.erb +5 -0
  29. data/spec/dummy/app/views/entities/show.html.erb +5 -0
  30. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  31. data/spec/dummy/app/views/platforms/_form.html.erb +17 -0
  32. data/spec/dummy/app/views/platforms/edit.html.erb +6 -0
  33. data/spec/dummy/app/views/platforms/index.html.erb +21 -0
  34. data/spec/dummy/app/views/platforms/new.html.erb +5 -0
  35. data/spec/dummy/app/views/platforms/show.html.erb +5 -0
  36. data/spec/dummy/config.ru +4 -0
  37. data/spec/dummy/config/application.rb +45 -0
  38. data/spec/dummy/config/boot.rb +10 -0
  39. data/spec/dummy/config/database.yml +22 -0
  40. data/spec/dummy/config/environment.rb +5 -0
  41. data/spec/dummy/config/environments/development.rb +26 -0
  42. data/spec/dummy/config/environments/production.rb +49 -0
  43. data/spec/dummy/config/environments/test.rb +35 -0
  44. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  45. data/spec/dummy/config/initializers/inflections.rb +10 -0
  46. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  47. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  48. data/spec/dummy/config/initializers/session_store.rb +8 -0
  49. data/spec/dummy/config/locales/en.yml +5 -0
  50. data/spec/dummy/config/routes.rb +64 -0
  51. data/spec/dummy/db/migrate/20110228091428_create_entities.rb +14 -0
  52. data/spec/dummy/db/migrate/20110228093241_create_platforms.rb +14 -0
  53. data/spec/dummy/db/migrate/20110228094444_create_versions.rb +18 -0
  54. data/spec/dummy/db/schema.rb +40 -0
  55. data/spec/dummy/public/404.html +26 -0
  56. data/spec/dummy/public/422.html +26 -0
  57. data/spec/dummy/public/500.html +26 -0
  58. data/spec/dummy/public/favicon.ico +0 -0
  59. data/spec/dummy/public/javascripts/application.js +2 -0
  60. data/spec/dummy/public/javascripts/controls.js +965 -0
  61. data/spec/dummy/public/javascripts/dragdrop.js +974 -0
  62. data/spec/dummy/public/javascripts/effects.js +1123 -0
  63. data/spec/dummy/public/javascripts/prototype.js +6001 -0
  64. data/spec/dummy/public/javascripts/rails.js +175 -0
  65. data/spec/dummy/script/rails +6 -0
  66. data/spec/dummy/spec/controllers/entities_controller_spec.rb +125 -0
  67. data/spec/dummy/spec/controllers/platforms_controller_spec.rb +125 -0
  68. data/spec/dummy/spec/helpers/entities_helper_spec.rb +15 -0
  69. data/spec/dummy/spec/helpers/platforms_helper_spec.rb +15 -0
  70. data/spec/dummy/spec/integration/navigation_spec.rb +9 -0
  71. data/spec/dummy/spec/integration/paper_trail_manager_spec.rb +194 -0
  72. data/spec/dummy/spec/models/entity_spec.rb +14 -0
  73. data/spec/dummy/spec/models/platform_spec.rb +14 -0
  74. data/spec/dummy/spec/requests/entities_spec.rb +11 -0
  75. data/spec/dummy/spec/requests/platforms_spec.rb +11 -0
  76. data/spec/dummy/spec/routing/entities_routing_spec.rb +35 -0
  77. data/spec/dummy/spec/routing/platforms_routing_spec.rb +35 -0
  78. data/spec/dummy/spec/views/entities/edit.html.erb_spec.rb +15 -0
  79. data/spec/dummy/spec/views/entities/index.html.erb_spec.rb +14 -0
  80. data/spec/dummy/spec/views/entities/new.html.erb_spec.rb +15 -0
  81. data/spec/dummy/spec/views/entities/show.html.erb_spec.rb +11 -0
  82. data/spec/dummy/spec/views/platforms/edit.html.erb_spec.rb +15 -0
  83. data/spec/dummy/spec/views/platforms/index.html.erb_spec.rb +14 -0
  84. data/spec/dummy/spec/views/platforms/new.html.erb_spec.rb +15 -0
  85. data/spec/dummy/spec/views/platforms/show.html.erb_spec.rb +11 -0
  86. data/spec/paper_trail_manager_spec.rb +7 -0
  87. data/spec/spec_helper.rb +82 -0
  88. data/spec/support/factories.rb +12 -0
  89. metadata +387 -0
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "rails", "~> 3.0"
4
+ gem "haml", "~> 3.0"
5
+ gem "paper_trail", "~> 2.0"
6
+ gem "will_paginate", "~> 3.0.pre2"
7
+
8
+ group *[:development, :test] do
9
+ gem "capybara", ">= 0.4.0"
10
+ gem "factory_girl_rails", "~> 1.1.beta1"
11
+ gem "jeweler", "~> 1.5.2"
12
+ gem "rdoc"
13
+ gem "rspec-rails", "~> 2.5.0"
14
+ gem "ruby-debug"
15
+ gem "spork", "~> 0.9.0.rc"
16
+ gem "sqlite3-ruby", :require => "sqlite3"
17
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,147 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ abstract (1.0.0)
5
+ actionmailer (3.0.9)
6
+ actionpack (= 3.0.9)
7
+ mail (~> 2.2.19)
8
+ actionpack (3.0.9)
9
+ activemodel (= 3.0.9)
10
+ activesupport (= 3.0.9)
11
+ builder (~> 2.1.2)
12
+ erubis (~> 2.6.6)
13
+ i18n (~> 0.5.0)
14
+ rack (~> 1.2.1)
15
+ rack-mount (~> 0.6.14)
16
+ rack-test (~> 0.5.7)
17
+ tzinfo (~> 0.3.23)
18
+ activemodel (3.0.9)
19
+ activesupport (= 3.0.9)
20
+ builder (~> 2.1.2)
21
+ i18n (~> 0.5.0)
22
+ activerecord (3.0.9)
23
+ activemodel (= 3.0.9)
24
+ activesupport (= 3.0.9)
25
+ arel (~> 2.0.10)
26
+ tzinfo (~> 0.3.23)
27
+ activeresource (3.0.9)
28
+ activemodel (= 3.0.9)
29
+ activesupport (= 3.0.9)
30
+ activesupport (3.0.9)
31
+ arel (2.0.10)
32
+ builder (2.1.2)
33
+ capybara (0.4.1.2)
34
+ celerity (>= 0.7.9)
35
+ culerity (>= 0.2.4)
36
+ mime-types (>= 1.16)
37
+ nokogiri (>= 1.3.3)
38
+ rack (>= 1.0.0)
39
+ rack-test (>= 0.5.4)
40
+ selenium-webdriver (>= 0.0.27)
41
+ xpath (~> 0.1.3)
42
+ celerity (0.8.8)
43
+ childprocess (0.1.8)
44
+ ffi (~> 1.0.6)
45
+ columnize (0.3.2)
46
+ culerity (0.2.15)
47
+ diff-lcs (1.1.2)
48
+ erubis (2.6.6)
49
+ abstract (>= 1.0.0)
50
+ factory_girl (2.0.0.beta2)
51
+ factory_girl_rails (1.1.beta1)
52
+ factory_girl (~> 2.0.0.beta)
53
+ rails (>= 3.0.0)
54
+ ffi (1.0.7)
55
+ rake (>= 0.8.7)
56
+ git (1.2.5)
57
+ haml (3.1.2)
58
+ i18n (0.5.0)
59
+ jeweler (1.5.2)
60
+ bundler (~> 1.0.0)
61
+ git (>= 1.2.5)
62
+ rake
63
+ json_pure (1.5.1)
64
+ linecache (0.43)
65
+ mail (2.2.19)
66
+ activesupport (>= 2.3.6)
67
+ i18n (>= 0.4.0)
68
+ mime-types (~> 1.16)
69
+ treetop (~> 1.4.8)
70
+ mime-types (1.16)
71
+ nokogiri (1.4.4)
72
+ paper_trail (2.0.2)
73
+ rails (~> 3)
74
+ polyglot (0.3.1)
75
+ rack (1.2.2)
76
+ rack-mount (0.6.14)
77
+ rack (>= 1.0.0)
78
+ rack-test (0.5.7)
79
+ rack (>= 1.0)
80
+ rails (3.0.9)
81
+ actionmailer (= 3.0.9)
82
+ actionpack (= 3.0.9)
83
+ activerecord (= 3.0.9)
84
+ activeresource (= 3.0.9)
85
+ activesupport (= 3.0.9)
86
+ bundler (~> 1.0)
87
+ railties (= 3.0.9)
88
+ railties (3.0.9)
89
+ actionpack (= 3.0.9)
90
+ activesupport (= 3.0.9)
91
+ rake (>= 0.8.7)
92
+ rdoc (~> 3.4)
93
+ thor (~> 0.14.4)
94
+ rake (0.9.2)
95
+ rdoc (3.7)
96
+ rspec (2.5.0)
97
+ rspec-core (~> 2.5.0)
98
+ rspec-expectations (~> 2.5.0)
99
+ rspec-mocks (~> 2.5.0)
100
+ rspec-core (2.5.1)
101
+ rspec-expectations (2.5.0)
102
+ diff-lcs (~> 1.1.2)
103
+ rspec-mocks (2.5.0)
104
+ rspec-rails (2.5.0)
105
+ actionpack (~> 3.0)
106
+ activesupport (~> 3.0)
107
+ railties (~> 3.0)
108
+ rspec (~> 2.5.0)
109
+ ruby-debug (0.10.4)
110
+ columnize (>= 0.1)
111
+ ruby-debug-base (~> 0.10.4.0)
112
+ ruby-debug-base (0.10.4)
113
+ linecache (>= 0.3)
114
+ rubyzip (0.9.4)
115
+ selenium-webdriver (0.1.4)
116
+ childprocess (>= 0.1.7)
117
+ ffi (>= 1.0.7)
118
+ json_pure
119
+ rubyzip
120
+ spork (0.9.0.rc4)
121
+ sqlite3 (1.3.3)
122
+ sqlite3-ruby (1.3.3)
123
+ sqlite3 (>= 1.3.3)
124
+ thor (0.14.6)
125
+ treetop (1.4.9)
126
+ polyglot (>= 0.3.1)
127
+ tzinfo (0.3.29)
128
+ will_paginate (3.0.pre2)
129
+ xpath (0.1.3)
130
+ nokogiri (~> 1.3)
131
+
132
+ PLATFORMS
133
+ ruby
134
+
135
+ DEPENDENCIES
136
+ capybara (>= 0.4.0)
137
+ factory_girl_rails (~> 1.1.beta1)
138
+ haml (~> 3.0)
139
+ jeweler (~> 1.5.2)
140
+ paper_trail (~> 2.0)
141
+ rails (~> 3.0)
142
+ rdoc
143
+ rspec-rails (~> 2.5.0)
144
+ ruby-debug
145
+ spork (~> 0.9.0.rc)
146
+ sqlite3-ruby
147
+ will_paginate (~> 3.0.pre2)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2011 Igal Koshevoy
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,32 @@
1
+ PaperTrailManager
2
+ ================
3
+
4
+ Browse, subscribe, view and revert changes to records when using Ruby on Rails 3 and the `paper_trail` gem.
5
+
6
+ **WARNING**: This is alpha-quality software. There are tests, it's useful, but it could use more work.
7
+
8
+ Installation
9
+ ------------
10
+
11
+ If you have a Ruby on Rails 3 application where you're using the `paper_trail` gem to track changes to your records, you can make use of this like:
12
+
13
+ Add the following line to your `Gemfile`:
14
+
15
+ gem 'paper_trail_manager', :git => 'https://github.com/igal/paper_trail_manager.git'
16
+
17
+ Install the libary:
18
+
19
+ bundle install
20
+
21
+ Add the following line to your `config/routes.rb`:
22
+
23
+ resources :changes, :controller => 'paper_trail_manager/changes'
24
+
25
+ Restart the server and go to the `/changes` URI to browse, subscribe, view and revert your changes. The top-level URL will look something like this:
26
+
27
+ http://localhost:3000/changes
28
+
29
+ License
30
+ -------
31
+
32
+ This program is provided under an MIT open source license, read the [LICENSE.txt](http://github.com/igal/paper_trail_manager/blob/master/LICENSE.txt) file for details.
data/Rakefile ADDED
@@ -0,0 +1,52 @@
1
+ # encoding: UTF-8
2
+ require 'rubygems'
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError
6
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ require 'rake'
10
+ require 'rdoc/task'
11
+
12
+ require 'rspec/core'
13
+ require 'rspec/core/rake_task'
14
+
15
+ RSpec::Core::RakeTask.new(:spec)
16
+
17
+ task :default => :spec
18
+
19
+ Rake::RDocTask.new(:rdoc) do |rdoc|
20
+ rdoc.rdoc_dir = 'rdoc'
21
+ rdoc.title = 'PaperTrailManager'
22
+ rdoc.options << '--line-numbers' << '--inline-source'
23
+ rdoc.rdoc_files.include('README.rdoc')
24
+ rdoc.rdoc_files.include('lib/**/*.rb')
25
+ end
26
+
27
+ require "jeweler"
28
+ Jeweler::Tasks.new do |gem|
29
+ gem.name = "paper_trail_manager"
30
+ gem.summary = gem.description = "A user interface for `paper_trail` versioning data in Ruby on Rails 3 applications."
31
+ gem.files = Dir["{app,lib,spec}/**/*"] + ["LICENSE.txt", "Rakefile", "README.md", "VERSION", "paper_trail_manager.gemspec", "Gemfile", "Gemfile.lock"] - Dir["spec/dummy/{log,tmp}/**/*"] - Dir["spec/dummy/db/*.sqlite3"]
32
+
33
+ gem.authors = ["Igal Koshevoy"]
34
+ gem.email = "igal@pragmaticraft.com"
35
+ gem.homepage = "http://github.com/igal/paper_trail_manager"
36
+ end
37
+
38
+ namespace :spork do
39
+ task :spec do
40
+ exec "rspec --drb spec"
41
+ end
42
+
43
+ task :serve do
44
+ exec "spork"
45
+ end
46
+ end
47
+
48
+ desc "Freshen files like Gemfile.lock and .gemspec"
49
+ task :freshen do
50
+ sh "bundle check || bundle --local || bundle update --local || bundle update"
51
+ Rake::Task['gemspec'].invoke
52
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,109 @@
1
+ class PaperTrailManager::ChangesController < ApplicationController
2
+ # List changes
3
+ def index
4
+ unless change_index_allowed?
5
+ flash[:error] = "You do not have permission to list changes."
6
+ return(redirect_to root_url)
7
+ end
8
+
9
+ @versions = Version.order('created_at DESC, id DESC')
10
+ if params[:type]
11
+ @versions = @versions.where(:item_type => params[:type])
12
+ end
13
+ if params[:id]
14
+ @versions = @versions.where(:item_id => params[:id])
15
+ end
16
+
17
+ @versions = @versions.paginate(:page => params[:page], :per_page => 50)
18
+
19
+ respond_to do |format|
20
+ format.html # index.html.erb
21
+ format.atom # index.atom.builder
22
+ format.json { render :json => @versions }
23
+ end
24
+ end
25
+
26
+ # Show a change
27
+ def show
28
+ begin
29
+ @version = Version.find(params[:id])
30
+ rescue ActiveRecord::RecordNotFound
31
+ flash[:error] = "No such version."
32
+ return(redirect_to :action => :index)
33
+ end
34
+
35
+ unless change_show_allowed?(@version)
36
+ flash[:error] = "You do not have permission to show that change."
37
+ return(redirect_to :action => :index)
38
+ end
39
+
40
+ respond_to do |format|
41
+ format.html # show.html.erb
42
+ format.json { render :json => @version }
43
+ end
44
+ end
45
+
46
+ # Rollback a change
47
+ def update
48
+ begin
49
+ @version = Version.find(params[:id])
50
+ rescue ActiveRecord::RecordNotFound
51
+ flash[:error] = "No such version."
52
+ return(redirect_to(:action => :index))
53
+ end
54
+
55
+ unless change_revert_allowed?(@version)
56
+ flash[:error] = "You do not have permission to revert this change."
57
+ return(redirect_to :action => :index)
58
+ end
59
+
60
+ if @version.event == "create"
61
+ @record = @version.item_type.constantize.find(@version.item_id)
62
+ @result = @record.destroy
63
+ else
64
+ @record = @version.reify
65
+ @result = @record.save
66
+ end
67
+
68
+ if @result
69
+ if @version.event == "create"
70
+ flash[:notice] = "Rolled back newly-created record by destroying it."
71
+ redirect_to :action => :index
72
+ else
73
+ flash[:notice] = "Rolled back changes to this record."
74
+ redirect_to change_item_url(@version)
75
+ end
76
+ else
77
+ flash[:error] = "Couldn't rollback. Sorry."
78
+ redirect_to :action => :index
79
+ end
80
+ end
81
+
82
+ protected
83
+
84
+ # Return the URL for the item represented by the +version+, e.g. a Company record instance referenced by a version.
85
+ def change_item_url(version)
86
+ return send("#{version.item_type.downcase}_url", version.item_id)
87
+ rescue NoMethodError
88
+ return nil
89
+ end
90
+ helper_method :change_item_url
91
+
92
+ # Allow index?
93
+ def change_index_allowed?
94
+ return PaperTrailManager.allow_index?(self)
95
+ end
96
+ helper_method :change_index_allowed?
97
+
98
+ # Allow show?
99
+ def change_show_allowed?(version)
100
+ return PaperTrailManager.allow_show?(self, version)
101
+ end
102
+ helper_method :change_show_allowed?
103
+
104
+ # Allow revert?
105
+ def change_revert_allowed?(version)
106
+ return PaperTrailManager.allow_revert?(self, version)
107
+ end
108
+ helper_method :change_revert_allowed?
109
+ end
@@ -0,0 +1,99 @@
1
+ class PaperTrailManager
2
+ module ChangesHelper
3
+ # Return HTML representing the +object+, which is either its text or a stylized "nil".
4
+ def text_or_nil(object)
5
+ if object.nil?
6
+ return content_tag("em", "nil")
7
+ else
8
+ return h(object)
9
+ end
10
+ end
11
+
12
+ # Return an hash of changes for the given +Version+ record. The resulting
13
+ # data structure is a hash whose keys are the names of changed columns and
14
+ # values containing a hash with current and previous value. E.g.,:
15
+ #
16
+ # {
17
+ # "my_column_name" => {
18
+ # :previous => "past value",
19
+ # :current => "current_value",
20
+ # },
21
+ # "title" => {
22
+ # :previous => "puppies",
23
+ # :current => "kittens",
24
+ # },
25
+ # ...
26
+ # }
27
+ def changes_for(version)
28
+ changes = {}
29
+ current = version.next.try(:reify)
30
+ # FIXME #reify randomly throws "ArgumentError Exception: syntax error on line 13, col 30:" -- why?
31
+ previous = version.reify rescue nil
32
+ record = \
33
+ begin
34
+ version.item_type.constantize.find(version.item_id)
35
+ rescue ActiveRecord::RecordNotFound
36
+ previous || current
37
+ end
38
+
39
+ # Bail out if no changes are available
40
+ return changes unless record
41
+
42
+ case version.event
43
+ when "create", "update"
44
+ current ||= record
45
+ when "destroy"
46
+ previous ||= record
47
+ else
48
+ raise ArgumentError, "Unknown event: #{version.event}"
49
+ end
50
+
51
+ (current or previous).attribute_names.each do |name|
52
+ next if name == "updated_at"
53
+ next if name == "created_at"
54
+ current_value = current.read_attribute(name) if current
55
+ previous_value = previous.read_attribute(name) if previous
56
+ unless current_value == previous_value || (version.event == "create" && current_value.blank?)
57
+ changes[name] = {
58
+ :previous => previous_value,
59
+ :current => current_value,
60
+ }
61
+ end
62
+ end
63
+
64
+ return changes
65
+ end
66
+
67
+ # Returns string title for the versioned record.
68
+ def change_title_for(version)
69
+ current = version.next.try(:reify)
70
+ previous = version.reify rescue nil
71
+ record = version.item_type.constantize.find(version.item_id) rescue nil
72
+
73
+ name = nil
74
+ [:name, :title, :to_s].each do |name_method|
75
+ [previous, current, record].each do |obj|
76
+ name = obj.send(name_method) if obj.respond_to?(name_method)
77
+ break if name
78
+ end
79
+ break if name
80
+ end
81
+
82
+ return h(name)
83
+ end
84
+
85
+ # Returns sorted array of types of items that there are changes for.
86
+ def change_item_types
87
+ return ActiveRecord::Base.connection.select_values('SELECT DISTINCT(item_type) FROM versions ORDER BY item_type')
88
+ end
89
+
90
+ # Returns HTML link for the item stored in the version, e.g. a link to a Company record stored in the version.
91
+ def change_item_link(version)
92
+ if url = change_item_url(version)
93
+ return link_to(change_title_for(version), url, :class => 'change_item')
94
+ else
95
+ return content_tag(:span, change_title_for(version), :class => 'change_item')
96
+ end
97
+ end
98
+ end
99
+ end