paper_trail_without_deprecated 3.0.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +21 -0
  5. data/CHANGELOG.md +68 -0
  6. data/Gemfile +2 -0
  7. data/MIT-LICENSE +20 -0
  8. data/README.md +979 -0
  9. data/Rakefile +18 -0
  10. data/gemfiles/3.0.gemfile +31 -0
  11. data/lib/generators/paper_trail/USAGE +2 -0
  12. data/lib/generators/paper_trail/install_generator.rb +23 -0
  13. data/lib/generators/paper_trail/templates/add_object_changes_column_to_versions.rb +9 -0
  14. data/lib/generators/paper_trail/templates/create_versions.rb +18 -0
  15. data/lib/paper_trail.rb +115 -0
  16. data/lib/paper_trail/cleaner.rb +34 -0
  17. data/lib/paper_trail/config.rb +14 -0
  18. data/lib/paper_trail/frameworks/cucumber.rb +31 -0
  19. data/lib/paper_trail/frameworks/rails.rb +79 -0
  20. data/lib/paper_trail/frameworks/rspec.rb +24 -0
  21. data/lib/paper_trail/frameworks/rspec/extensions.rb +20 -0
  22. data/lib/paper_trail/frameworks/sinatra.rb +31 -0
  23. data/lib/paper_trail/has_paper_trail.rb +308 -0
  24. data/lib/paper_trail/serializers/json.rb +17 -0
  25. data/lib/paper_trail/serializers/yaml.rb +17 -0
  26. data/lib/paper_trail/version.rb +200 -0
  27. data/lib/paper_trail/version_number.rb +3 -0
  28. data/paper_trail.gemspec +36 -0
  29. data/spec/models/widget_spec.rb +13 -0
  30. data/spec/paper_trail_spec.rb +47 -0
  31. data/spec/spec_helper.rb +41 -0
  32. data/test/custom_json_serializer.rb +13 -0
  33. data/test/dummy/Rakefile +7 -0
  34. data/test/dummy/app/controllers/application_controller.rb +17 -0
  35. data/test/dummy/app/controllers/test_controller.rb +5 -0
  36. data/test/dummy/app/controllers/widgets_controller.rb +31 -0
  37. data/test/dummy/app/helpers/application_helper.rb +2 -0
  38. data/test/dummy/app/models/animal.rb +4 -0
  39. data/test/dummy/app/models/article.rb +16 -0
  40. data/test/dummy/app/models/authorship.rb +5 -0
  41. data/test/dummy/app/models/book.rb +5 -0
  42. data/test/dummy/app/models/cat.rb +2 -0
  43. data/test/dummy/app/models/document.rb +4 -0
  44. data/test/dummy/app/models/dog.rb +2 -0
  45. data/test/dummy/app/models/elephant.rb +3 -0
  46. data/test/dummy/app/models/fluxor.rb +3 -0
  47. data/test/dummy/app/models/foo_widget.rb +2 -0
  48. data/test/dummy/app/models/legacy_widget.rb +4 -0
  49. data/test/dummy/app/models/person.rb +28 -0
  50. data/test/dummy/app/models/post.rb +4 -0
  51. data/test/dummy/app/models/protected_widget.rb +3 -0
  52. data/test/dummy/app/models/song.rb +12 -0
  53. data/test/dummy/app/models/translation.rb +4 -0
  54. data/test/dummy/app/models/widget.rb +10 -0
  55. data/test/dummy/app/models/wotsit.rb +4 -0
  56. data/test/dummy/app/versions/post_version.rb +3 -0
  57. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  58. data/test/dummy/config.ru +4 -0
  59. data/test/dummy/config/application.rb +63 -0
  60. data/test/dummy/config/boot.rb +10 -0
  61. data/test/dummy/config/database.yml +22 -0
  62. data/test/dummy/config/environment.rb +5 -0
  63. data/test/dummy/config/environments/development.rb +40 -0
  64. data/test/dummy/config/environments/production.rb +73 -0
  65. data/test/dummy/config/environments/test.rb +37 -0
  66. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  67. data/test/dummy/config/initializers/inflections.rb +10 -0
  68. data/test/dummy/config/initializers/mime_types.rb +5 -0
  69. data/test/dummy/config/initializers/paper_trail.rb +5 -0
  70. data/test/dummy/config/initializers/secret_token.rb +7 -0
  71. data/test/dummy/config/initializers/session_store.rb +8 -0
  72. data/test/dummy/config/locales/en.yml +5 -0
  73. data/test/dummy/config/routes.rb +3 -0
  74. data/test/dummy/db/migrate/20110208155312_set_up_test_tables.rb +136 -0
  75. data/test/dummy/db/schema.rb +101 -0
  76. data/test/dummy/public/404.html +26 -0
  77. data/test/dummy/public/422.html +26 -0
  78. data/test/dummy/public/500.html +26 -0
  79. data/test/dummy/public/favicon.ico +0 -0
  80. data/test/dummy/public/javascripts/application.js +2 -0
  81. data/test/dummy/public/javascripts/controls.js +965 -0
  82. data/test/dummy/public/javascripts/dragdrop.js +974 -0
  83. data/test/dummy/public/javascripts/effects.js +1123 -0
  84. data/test/dummy/public/javascripts/prototype.js +6001 -0
  85. data/test/dummy/public/javascripts/rails.js +175 -0
  86. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  87. data/test/dummy/script/rails +6 -0
  88. data/test/functional/controller_test.rb +90 -0
  89. data/test/functional/modular_sinatra_test.rb +44 -0
  90. data/test/functional/sinatra_test.rb +45 -0
  91. data/test/functional/thread_safety_test.rb +26 -0
  92. data/test/paper_trail_test.rb +27 -0
  93. data/test/test_helper.rb +40 -0
  94. data/test/unit/cleaner_test.rb +143 -0
  95. data/test/unit/inheritance_column_test.rb +43 -0
  96. data/test/unit/model_test.rb +1314 -0
  97. data/test/unit/protected_attrs_test.rb +46 -0
  98. data/test/unit/serializer_test.rb +117 -0
  99. data/test/unit/serializers/json_test.rb +40 -0
  100. data/test/unit/serializers/mixin_json_test.rb +36 -0
  101. data/test/unit/serializers/mixin_yaml_test.rb +49 -0
  102. data/test/unit/serializers/yaml_test.rb +40 -0
  103. data/test/unit/timestamp_test.rb +44 -0
  104. data/test/unit/version_test.rb +74 -0
  105. metadata +286 -0
@@ -0,0 +1,18 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake/testtask'
5
+ desc 'Run tests on PaperTrail with Test::Unit.'
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << 'lib'
8
+ t.libs << 'test'
9
+ t.pattern = 'test/**/*_test.rb'
10
+ t.verbose = false
11
+ end
12
+
13
+ require 'rspec/core/rake_task'
14
+ desc 'Run PaperTrail specs for the RSpec helper.'
15
+ RSpec::Core::RakeTask.new(:spec)
16
+
17
+ desc 'Default: run all available test suites'
18
+ task :default => [:test, :spec]
@@ -0,0 +1,31 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~> 3.0'
4
+
5
+ group :development, :test do
6
+ gem 'rake'
7
+ gem 'shoulda', '~> 3.5'
8
+ gem 'ffaker', '>= 1.15'
9
+
10
+ # Testing of Rails
11
+ gem 'railties', '~> 3.0'
12
+
13
+ # Testing of Sinatra
14
+ gem 'sinatra', '~> 1.0'
15
+ gem 'rack-test', '>= 0.6'
16
+
17
+ # Use sqlite3 gem for regular Ruby
18
+ gem 'sqlite3', '~> 1.2', :platform => :ruby
19
+
20
+ # RSpec testing
21
+ gem 'rspec-rails', '~> 2.14'
22
+
23
+ platforms :jruby, :ruby_18 do
24
+ # shoulda-matchers > 2.0 is not compatible with Ruby18.
25
+ # Since we can't specify difference between JRuby 18/19, we need to use shoulda-matchers 1.5 for all JRuby testing.
26
+ gem 'shoulda-matchers', '~> 1.5'
27
+ end
28
+
29
+ # Use jRuby's sqlite3 adapter for jRuby
30
+ gem 'activerecord-jdbcsqlite3-adapter', '~> 1.2.9', :platform => :jruby
31
+ end
@@ -0,0 +1,2 @@
1
+ Description:
2
+ Generates (but does not run) a migration to add a versions table.
@@ -0,0 +1,23 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+ require 'rails/generators/active_record'
4
+
5
+ module PaperTrail
6
+ class InstallGenerator < ::Rails::Generators::Base
7
+ include ::Rails::Generators::Migration
8
+
9
+ source_root File.expand_path('../templates', __FILE__)
10
+ class_option :with_changes, :type => :boolean, :default => false, :desc => "Store changeset (diff) with each version"
11
+
12
+ desc 'Generates (but does not run) a migration to add a versions table.'
13
+
14
+ def create_migration_file
15
+ migration_template 'create_versions.rb', 'db/migrate/create_versions.rb'
16
+ migration_template 'add_object_changes_column_to_versions.rb', 'db/migrate/add_object_changes_column_to_versions.rb' if options.with_changes?
17
+ end
18
+
19
+ def self.next_migration_number(dirname)
20
+ ActiveRecord::Generators::Base.next_migration_number(dirname)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ class AddObjectChangesColumnToVersions < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :versions, :object_changes, :text
4
+ end
5
+
6
+ def self.down
7
+ remove_column :versions, :object_changes
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ class CreateVersions < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :versions do |t|
4
+ t.string :item_type, :null => false
5
+ t.integer :item_id, :null => false
6
+ t.string :event, :null => false
7
+ t.string :whodunnit
8
+ t.text :object
9
+ t.datetime :created_at
10
+ end
11
+ add_index :versions, [:item_type, :item_id]
12
+ end
13
+
14
+ def self.down
15
+ remove_index :versions, [:item_type, :item_id]
16
+ drop_table :versions
17
+ end
18
+ end
@@ -0,0 +1,115 @@
1
+ require 'paper_trail/config'
2
+ require 'paper_trail/has_paper_trail'
3
+ require 'paper_trail/cleaner'
4
+
5
+ # Require all frameworks and serializers
6
+ Dir[File.join(File.dirname(__FILE__), 'paper_trail', 'frameworks', '*.rb')].each { |file| require file }
7
+ Dir[File.join(File.dirname(__FILE__), 'paper_trail', 'serializers', '*.rb')].each { |file| require file }
8
+
9
+ # PaperTrail's module methods can be called in both models and controllers.
10
+ module PaperTrail
11
+ extend PaperTrail::Cleaner
12
+
13
+ # Switches PaperTrail on or off.
14
+ def self.enabled=(value)
15
+ PaperTrail.config.enabled = value
16
+ end
17
+
18
+ # Returns `true` if PaperTrail is on, `false` otherwise.
19
+ # PaperTrail is enabled by default.
20
+ def self.enabled?
21
+ !!PaperTrail.config.enabled
22
+ end
23
+
24
+ # Returns `true` if PaperTrail is enabled for the request, `false` otherwise.
25
+ #
26
+ # See `PaperTrail::Controller#paper_trail_enabled_for_controller`.
27
+ def self.enabled_for_controller?
28
+ !!paper_trail_store[:request_enabled_for_controller]
29
+ end
30
+
31
+ # Sets whether PaperTrail is enabled or disabled for the current request.
32
+ def self.enabled_for_controller=(value)
33
+ paper_trail_store[:request_enabled_for_controller] = value
34
+ end
35
+
36
+ # Set the field which records when a version was created.
37
+ def self.timestamp_field=(field_name)
38
+ PaperTrail.config.timestamp_field = field_name
39
+ end
40
+
41
+ # Returns the field which records when a version was created.
42
+ def self.timestamp_field
43
+ PaperTrail.config.timestamp_field
44
+ end
45
+
46
+ # Returns who is reponsible for any changes that occur.
47
+ def self.whodunnit
48
+ paper_trail_store[:whodunnit]
49
+ end
50
+
51
+ # Sets who is responsible for any changes that occur.
52
+ # You would normally use this in a migration or on the console,
53
+ # when working with models directly. In a controller it is set
54
+ # automatically to the `current_user`.
55
+ def self.whodunnit=(value)
56
+ paper_trail_store[:whodunnit] = value
57
+ end
58
+
59
+ # Returns any information from the controller that you want
60
+ # PaperTrail to store.
61
+ #
62
+ # See `PaperTrail::Controller#info_for_paper_trail`.
63
+ def self.controller_info
64
+ paper_trail_store[:controller_info]
65
+ end
66
+
67
+ # Sets any information from the controller that you want PaperTrail
68
+ # to store. By default this is set automatically by a before filter.
69
+ def self.controller_info=(value)
70
+ paper_trail_store[:controller_info] = value
71
+ end
72
+
73
+ # Getter and Setter for PaperTrail Serializer
74
+ def self.serializer=(value)
75
+ PaperTrail.config.serializer = value
76
+ end
77
+
78
+ def self.serializer
79
+ PaperTrail.config.serializer
80
+ end
81
+
82
+ def self.active_record_protected_attributes?
83
+ @active_record_protected_attributes ||= ActiveRecord::VERSION::STRING.to_f < 4.0 || defined?(ProtectedAttributes)
84
+ end
85
+
86
+ private
87
+
88
+ # Thread-safe hash to hold PaperTrail's data.
89
+ # Initializing with needed default values.
90
+ def self.paper_trail_store
91
+ Thread.current[:paper_trail] ||= { :request_enabled_for_controller => true }
92
+ end
93
+
94
+ # Returns PaperTrail's configuration object.
95
+ def self.config
96
+ @@config ||= PaperTrail::Config.instance
97
+ end
98
+
99
+ def self.configure
100
+ yield config
101
+ end
102
+
103
+ end
104
+
105
+ require 'paper_trail/version'
106
+
107
+ ActiveSupport.on_load(:active_record) do
108
+ include PaperTrail::Model
109
+ end
110
+
111
+ if defined?(ActionController)
112
+ ActiveSupport.on_load(:action_controller) do
113
+ include PaperTrail::Rails::Controller
114
+ end
115
+ end
@@ -0,0 +1,34 @@
1
+ module PaperTrail
2
+ module Cleaner
3
+ # Destroys all but the most recent version(s) for items on a given date (or on all dates). Useful for deleting drafts.
4
+ #
5
+ # Options:
6
+ # :keeping An `integer` indicating the number of versions to be kept for each item per date.
7
+ # Defaults to `1`.
8
+ # :date Should either be a `Date` object specifying which date to destroy versions for or `:all`,
9
+ # which will specify that all dates should be cleaned. Defaults to `:all`.
10
+ # :item_id The `id` for the item to be cleaned on, or `nil`, which causes all items to be cleaned.
11
+ # Defaults to `nil`.
12
+ def clean_versions!(options = {})
13
+ options = {:keeping => 1, :date => :all}.merge(options)
14
+ gather_versions(options[:item_id], options[:date]).each do |item_id, versions|
15
+ versions.group_by { |v| v.created_at.to_date }.each do |date, versions| # now group the versions by date and iterate through those
16
+ versions.pop(options[:keeping]) # remove the number of versions we wish to keep from the collection of versions prior to destruction
17
+ versions.map(&:destroy)
18
+ end
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ # Returns a hash of versions grouped by the `item_id` attribute formatted like this: {:item_id => PaperTrail::Version}.
25
+ # If `item_id` or `date` is set, versions will be narrowed to those pointing at items with those ids that were created on specified date.
26
+ def gather_versions(item_id = nil, date = :all)
27
+ raise "`date` argument must receive a Timestamp or `:all`" unless date == :all || date.respond_to?(:to_date)
28
+ versions = item_id ? PaperTrail::Version.where(:item_id => item_id) : PaperTrail::Version
29
+ versions = versions.between(date.to_date, date.to_date + 1.day) unless date == :all
30
+ versions = PaperTrail::Version.all if versions == PaperTrail::Version # if versions has not been converted to an ActiveRecord::Relation yet, do so now
31
+ versions.group_by(&:item_id)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,14 @@
1
+ require 'singleton'
2
+
3
+ module PaperTrail
4
+ class Config
5
+ include Singleton
6
+ attr_accessor :enabled, :timestamp_field, :serializer, :version_limit
7
+
8
+ def initialize
9
+ @enabled = true # Indicates whether PaperTrail is on or off.
10
+ @timestamp_field = :created_at
11
+ @serializer = PaperTrail::Serializers::Yaml
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,31 @@
1
+ if defined? World
2
+ # before hook for Cucumber
3
+ before do
4
+ ::PaperTrail.enabled = false
5
+ ::PaperTrail.whodunnit = nil
6
+ ::PaperTrail.controller_info = {} if defined? ::Rails
7
+ end
8
+
9
+ module PaperTrail
10
+ module Cucumber
11
+ module Extensions
12
+ # :call-seq:
13
+ # with_versioning
14
+ #
15
+ # enable versioning for specific blocks
16
+
17
+ def with_versioning
18
+ was_enabled = ::PaperTrail.enabled?
19
+ ::PaperTrail.enabled = true
20
+ begin
21
+ yield
22
+ ensure
23
+ ::PaperTrail.enabled = was_enabled
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ World PaperTrail::Cucumber::Extensions
31
+ end
@@ -0,0 +1,79 @@
1
+ module PaperTrail
2
+ module Rails
3
+ module Controller
4
+
5
+ def self.included(base)
6
+ if defined?(ActionController) && base == ActionController::Base
7
+ base.before_filter :set_paper_trail_enabled_for_controller
8
+ base.before_filter :set_paper_trail_whodunnit, :set_paper_trail_controller_info
9
+ end
10
+ end
11
+
12
+ protected
13
+
14
+ # Returns the user who is responsible for any changes that occur.
15
+ # By default this calls `current_user` and returns the result.
16
+ #
17
+ # Override this method in your controller to call a different
18
+ # method, e.g. `current_person`, or anything you like.
19
+ def user_for_paper_trail
20
+ current_user if defined?(current_user)
21
+ end
22
+
23
+ # Returns any information about the controller or request that you
24
+ # want PaperTrail to store alongside any changes that occur. By
25
+ # default this returns an empty hash.
26
+ #
27
+ # Override this method in your controller to return a hash of any
28
+ # information you need. The hash's keys must correspond to columns
29
+ # in your `versions` table, so don't forget to add any new columns
30
+ # you need.
31
+ #
32
+ # For example:
33
+ #
34
+ # {:ip => request.remote_ip, :user_agent => request.user_agent}
35
+ #
36
+ # The columns `ip` and `user_agent` must exist in your `versions` # table.
37
+ #
38
+ # Use the `:meta` option to `PaperTrail::Model::ClassMethods.has_paper_trail`
39
+ # to store any extra model-level data you need.
40
+ def info_for_paper_trail
41
+ {}
42
+ end
43
+
44
+ # Returns `true` (default) or `false` depending on whether PaperTrail should
45
+ # be active for the current request.
46
+ #
47
+ # Override this method in your controller to specify when PaperTrail should
48
+ # be off.
49
+ def paper_trail_enabled_for_controller
50
+ true
51
+ end
52
+
53
+ private
54
+
55
+ # Tells PaperTrail whether versions should be saved in the current request.
56
+ def set_paper_trail_enabled_for_controller
57
+ ::PaperTrail.enabled_for_controller = paper_trail_enabled_for_controller
58
+ end
59
+
60
+ # Tells PaperTrail who is responsible for any changes that occur.
61
+ def set_paper_trail_whodunnit
62
+ ::PaperTrail.whodunnit = user_for_paper_trail if paper_trail_enabled_for_controller
63
+ end
64
+
65
+ # DEPRECATED: please use `set_paper_trail_whodunnit` instead.
66
+ def set_whodunnit
67
+ logger.warn '[PaperTrail]: the `set_whodunnit` controller method has been deprecated. Please rename to `set_paper_trail_whodunnit`.'
68
+ set_paper_trail_whodunnit
69
+ end
70
+
71
+ # Tells PaperTrail any information from the controller you want
72
+ # to store alongside any changes that occur.
73
+ def set_paper_trail_controller_info
74
+ ::PaperTrail.controller_info = info_for_paper_trail if paper_trail_enabled_for_controller
75
+ end
76
+
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,24 @@
1
+ if defined? RSpec
2
+ require 'rspec/core'
3
+ require 'rspec/matchers'
4
+ require File.expand_path('../rspec/extensions', __FILE__)
5
+
6
+ RSpec.configure do |config|
7
+ config.include ::PaperTrail::RSpec::Extensions
8
+
9
+ config.before(:each) do
10
+ ::PaperTrail.enabled = false
11
+ ::PaperTrail.whodunnit = nil
12
+ ::PaperTrail.controller_info = {} if defined?(::Rails) && defined?(::RSpec::Rails)
13
+ end
14
+
15
+ config.before(:each, :versioning => true) do
16
+ ::PaperTrail.enabled = true
17
+ end
18
+ end
19
+
20
+ RSpec::Matchers.define :be_versioned do
21
+ # check to see if the model has `has_paper_trail` declared on it
22
+ match { |actual| actual.kind_of?(::PaperTrail::Model::InstanceMethods) }
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ module PaperTrail
2
+ module RSpec
3
+ module Extensions
4
+ # :call-seq:
5
+ # with_versioning
6
+ #
7
+ # enable versioning for specific blocks
8
+
9
+ def with_versioning
10
+ was_enabled = ::PaperTrail.enabled?
11
+ ::PaperTrail.enabled = true
12
+ begin
13
+ yield
14
+ ensure
15
+ ::PaperTrail.enabled = was_enabled
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,31 @@
1
+ module Sinatra
2
+ module PaperTrail
3
+
4
+ # Register this module inside your Sinatra application to gain access to controller-level methods used by PaperTrail
5
+ def self.registered(app)
6
+ app.helpers Sinatra::PaperTrail
7
+ app.before { set_paper_trail_whodunnit }
8
+ end
9
+
10
+ protected
11
+
12
+ # Returns the user who is responsible for any changes that occur.
13
+ # By default this calls `current_user` and returns the result.
14
+ #
15
+ # Override this method in your controller to call a different
16
+ # method, e.g. `current_person`, or anything you like.
17
+ def user_for_paper_trail
18
+ current_user if defined?(current_user)
19
+ end
20
+
21
+ private
22
+
23
+ # Tells PaperTrail who is responsible for any changes that occur.
24
+ def set_paper_trail_whodunnit
25
+ ::PaperTrail.whodunnit = user_for_paper_trail if ::PaperTrail.enabled?
26
+ end
27
+
28
+ end
29
+
30
+ register Sinatra::PaperTrail if defined?(register)
31
+ end