paper_trail_without_deprecated 3.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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,46 @@
1
+ require 'test_helper'
2
+
3
+ class ProtectedAttrsTest < ActiveSupport::TestCase
4
+ subject { ProtectedWidget.new }
5
+
6
+ if ActiveRecord::VERSION::STRING.to_f < 4.0 # these ActiveModel matchers (provided by shoulda-matchers) only work for Rails 3
7
+ accessible_attrs = ProtectedWidget.accessible_attributes.to_a
8
+ accessible_attrs.each do |attr_name|
9
+ should allow_mass_assignment_of(attr_name.to_sym)
10
+ end
11
+ ProtectedWidget.column_names.reject { |column_name| accessible_attrs.include?(column_name) }.each do |attr_name|
12
+ should_not allow_mass_assignment_of(attr_name.to_sym)
13
+ end
14
+ end
15
+
16
+ context 'A model with `attr_accessible` created' do
17
+ setup do
18
+ @widget = ProtectedWidget.create! :name => 'Henry'
19
+ @initial_attributes = @widget.attributes
20
+ end
21
+
22
+ should 'be `nil` in its previous version' do
23
+ assert_nil @widget.previous_version
24
+ end
25
+
26
+ context 'which is then updated' do
27
+ setup do
28
+ @widget.assign_attributes(:name => 'Jeff', :a_text => 'Short statement')
29
+ @widget.an_integer = 42
30
+ @widget.save!
31
+ end
32
+
33
+ should 'not be `nil` in its previous version' do
34
+ assert_not_nil @widget.previous_version
35
+ end
36
+
37
+ should 'the previous version should contain right attributes' do
38
+ # For some reason this test seems to be broken in JRuby 1.9 mode in the test env even though it works in the console. WTF?
39
+ unless ActiveRecord::VERSION::STRING.to_f >= 4.0 && defined?(JRUBY_VERSION) && RUBY_VERSION.to_f >= 1.9
40
+ assert_equal @widget.previous_version.attributes, @initial_attributes
41
+ end
42
+ end
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,117 @@
1
+ require 'test_helper'
2
+ require 'custom_json_serializer'
3
+
4
+ class SerializerTest < ActiveSupport::TestCase
5
+
6
+ context 'YAML Serializer' do
7
+ setup do
8
+ Fluxor.instance_eval <<-END
9
+ has_paper_trail
10
+ END
11
+
12
+ @fluxor = Fluxor.create :name => 'Some text.'
13
+ @original_fluxor_attributes = @fluxor.send(:item_before_change).attributes # this is exactly what PaperTrail serializes
14
+ @fluxor.update_attributes :name => 'Some more text.'
15
+ end
16
+
17
+ should 'work with the default yaml serializer' do
18
+ # Normal behaviour
19
+ assert_equal 2, @fluxor.versions.length
20
+ assert_nil @fluxor.versions[0].reify
21
+ assert_equal 'Some text.', @fluxor.versions[1].reify.name
22
+
23
+ # Check values are stored as YAML.
24
+ assert_equal @original_fluxor_attributes, YAML.load(@fluxor.versions[1].object)
25
+ # This test can't consistently pass in Ruby1.8 because hashes do no preserve order, which means the order of the
26
+ # attributes in the YAML can't be ensured.
27
+ if RUBY_VERSION.to_f >= 1.9
28
+ assert_equal YAML.dump(@original_fluxor_attributes), @fluxor.versions[1].object
29
+ end
30
+ end
31
+ end
32
+
33
+ context 'JSON Serializer' do
34
+ setup do
35
+ PaperTrail.configure do |config|
36
+ config.serializer = PaperTrail::Serializers::Json
37
+ end
38
+
39
+ Fluxor.instance_eval <<-END
40
+ has_paper_trail
41
+ END
42
+
43
+ @fluxor = Fluxor.create :name => 'Some text.'
44
+ @original_fluxor_attributes = @fluxor.send(:item_before_change).attributes # this is exactly what PaperTrail serializes
45
+ @fluxor.update_attributes :name => 'Some more text.'
46
+ end
47
+
48
+ teardown do
49
+ PaperTrail.config.serializer = PaperTrail::Serializers::Yaml
50
+ end
51
+
52
+ should 'reify with JSON serializer' do
53
+ # Normal behaviour
54
+ assert_equal 2, @fluxor.versions.length
55
+ assert_nil @fluxor.versions[0].reify
56
+ assert_equal 'Some text.', @fluxor.versions[1].reify.name
57
+
58
+ # Check values are stored as JSON.
59
+ assert_equal @original_fluxor_attributes, ActiveSupport::JSON.decode(@fluxor.versions[1].object)
60
+ # This test can't consistently pass in Ruby1.8 because hashes do no preserve order, which means the order of the
61
+ # attributes in the JSON can't be ensured.
62
+ if RUBY_VERSION.to_f >= 1.9
63
+ assert_equal ActiveSupport::JSON.encode(@original_fluxor_attributes), @fluxor.versions[1].object
64
+ end
65
+ end
66
+
67
+ should 'store object_changes' do
68
+ initial_changeset = {"name" => [nil, "Some text."], "id" => [nil, 1]}
69
+ second_changeset = {"name"=>["Some text.", "Some more text."]}
70
+ assert_equal initial_changeset, @fluxor.versions[0].changeset
71
+ assert_equal second_changeset, @fluxor.versions[1].changeset
72
+ end
73
+ end
74
+
75
+ context 'Custom Serializer' do
76
+ setup do
77
+ PaperTrail.configure do |config|
78
+ config.serializer = CustomJsonSerializer
79
+ end
80
+
81
+ Fluxor.instance_eval <<-END
82
+ has_paper_trail
83
+ END
84
+
85
+ @fluxor = Fluxor.create
86
+ @original_fluxor_attributes = @fluxor.send(:item_before_change).attributes.reject { |k,v| v.nil? } # this is exactly what PaperTrail serializes
87
+ @fluxor.update_attributes :name => 'Some more text.'
88
+ end
89
+
90
+ teardown do
91
+ PaperTrail.config.serializer = PaperTrail::Serializers::Yaml
92
+ end
93
+
94
+ should 'reify with custom serializer' do
95
+ # Normal behaviour
96
+ assert_equal 2, @fluxor.versions.length
97
+ assert_nil @fluxor.versions[0].reify
98
+ assert_nil @fluxor.versions[1].reify.name
99
+
100
+ # Check values are stored as JSON.
101
+ assert_equal @original_fluxor_attributes, ActiveSupport::JSON.decode(@fluxor.versions[1].object)
102
+ # This test can't consistently pass in Ruby1.8 because hashes do no preserve order, which means the order of the
103
+ # attributes in the JSON can't be ensured.
104
+ if RUBY_VERSION.to_f >= 1.9
105
+ assert_equal ActiveSupport::JSON.encode(@original_fluxor_attributes), @fluxor.versions[1].object
106
+ end
107
+ end
108
+
109
+ should 'store object_changes' do
110
+ initial_changeset = {"id" => [nil, 1]}
111
+ second_changeset = {"name"=>[nil, "Some more text."]}
112
+ assert_equal initial_changeset, @fluxor.versions[0].changeset
113
+ assert_equal second_changeset, @fluxor.versions[1].changeset
114
+ end
115
+ end
116
+
117
+ end
@@ -0,0 +1,40 @@
1
+ require 'test_helper'
2
+
3
+ class JsonTest < ActiveSupport::TestCase
4
+
5
+ setup do
6
+ # Setup a hash with random values
7
+ @hash = {}
8
+ (1..4).each do |i|
9
+ @hash["key#{i}"] = Faker::Lorem.word
10
+ end
11
+ @hash_as_json = @hash.to_json
12
+ # Setup an array of random words
13
+ @array = []
14
+ (rand(5) + 4).times { @array << Faker::Lorem.word }
15
+ @array_as_json = @array.to_json
16
+ end
17
+
18
+ context '`load` class method' do
19
+ should 'exist' do
20
+ assert PaperTrail::Serializers::Json.respond_to?(:load)
21
+ end
22
+
23
+ should '`deserialize` JSON to Ruby' do
24
+ assert_equal @hash, PaperTrail::Serializers::Json.load(@hash_as_json)
25
+ assert_equal @array, PaperTrail::Serializers::Json.load(@array_as_json)
26
+ end
27
+ end
28
+
29
+ context '`dump` class method' do
30
+ should 'exist' do
31
+ assert PaperTrail::Serializers::Json.respond_to?(:dump)
32
+ end
33
+
34
+ should '`serialize` Ruby to JSON' do
35
+ assert_equal @hash_as_json, PaperTrail::Serializers::Json.dump(@hash)
36
+ assert_equal @array_as_json, PaperTrail::Serializers::Json.dump(@array)
37
+ end
38
+ end
39
+
40
+ end
@@ -0,0 +1,36 @@
1
+ require 'test_helper'
2
+ require 'custom_json_serializer'
3
+
4
+ class MixinJsonTest < ActiveSupport::TestCase
5
+
6
+ setup do
7
+ # Setup a hash with random values, ensuring some values are nil
8
+ @hash = {}
9
+ (1..4).each do |i|
10
+ @hash["key#{i}"] = [Faker::Lorem.word, nil].sample
11
+ end
12
+ @hash['tkey'] = nil
13
+ @hash[''] = 'foo'
14
+ @hash_as_json = @hash.to_json
15
+ end
16
+
17
+ context '`load` class method' do
18
+ should 'exist' do
19
+ assert CustomJsonSerializer.respond_to?(:load)
20
+ end
21
+
22
+ should '`deserialize` JSON to Ruby, removing pairs with `blank` keys or values' do
23
+ assert_equal @hash.reject { |k,v| k.blank? || v.blank? }, CustomJsonSerializer.load(@hash_as_json)
24
+ end
25
+ end
26
+
27
+ context '`dump` class method' do
28
+ should 'exist' do
29
+ assert CustomJsonSerializer.respond_to?(:dump)
30
+ end
31
+
32
+ should '`serialize` Ruby to JSON, removing pairs with `nil` values' do
33
+ assert_equal @hash.reject { |k,v| v.nil? }.to_json, CustomJsonSerializer.dump(@hash)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,49 @@
1
+ require 'test_helper'
2
+
3
+ module CustomYamlSerializer
4
+ extend PaperTrail::Serializers::Yaml
5
+
6
+ def self.load(string)
7
+ parsed_value = super(string)
8
+ parsed_value.is_a?(Hash) ? parsed_value.reject { |k,v| k.blank? || v.blank? } : parsed_value
9
+ end
10
+
11
+ def self.dump(object)
12
+ object.is_a?(Hash) ? super(object.reject { |k,v| v.nil? }) : super
13
+ end
14
+ end
15
+
16
+ class MixinYamlTest < ActiveSupport::TestCase
17
+
18
+ setup do
19
+ # Setup a hash with random values, ensuring some values are nil
20
+ @hash = {}
21
+ (1..4).each do |i|
22
+ @hash["key#{i}"] = [Faker::Lorem.word, nil].sample
23
+ end
24
+ @hash['tkey'] = nil
25
+ @hash[''] = 'foo'
26
+ @hash_as_yaml = @hash.to_yaml
27
+ end
28
+
29
+ context '`load` class method' do
30
+ should 'exist' do
31
+ assert CustomYamlSerializer.respond_to?(:load)
32
+ end
33
+
34
+ should '`deserialize` YAML to Ruby, removing pairs with `blank` keys or values' do
35
+ assert_equal @hash.reject { |k,v| k.blank? || v.blank? }, CustomYamlSerializer.load(@hash_as_yaml)
36
+ end
37
+ end
38
+
39
+ context '`dump` class method' do
40
+ should 'exist' do
41
+ assert CustomYamlSerializer.respond_to?(:dump)
42
+ end
43
+
44
+ should '`serialize` Ruby to YAML, removing pairs with `nil` values' do
45
+ assert_equal @hash.reject { |k,v| v.nil? }.to_yaml, CustomYamlSerializer.dump(@hash)
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,40 @@
1
+ require 'test_helper'
2
+
3
+ class YamlTest < ActiveSupport::TestCase
4
+
5
+ setup do
6
+ # Setup a hash with random values
7
+ @hash = {}
8
+ (1..4).each do |i|
9
+ @hash["key#{i}".to_sym] = Faker::Lorem.word
10
+ end
11
+ @hash_as_yaml = @hash.to_yaml
12
+ # Setup an array of random words
13
+ @array = []
14
+ (rand(5) + 4).times { @array << Faker::Lorem.word }
15
+ @array_as_yaml = @array.to_yaml
16
+ end
17
+
18
+ context '`load` class method' do
19
+ should 'exist' do
20
+ assert PaperTrail::Serializers::Yaml.respond_to?(:load)
21
+ end
22
+
23
+ should '`deserialize` YAML to Ruby' do
24
+ assert_equal @hash, PaperTrail::Serializers::Yaml.load(@hash_as_yaml)
25
+ assert_equal @array, PaperTrail::Serializers::Yaml.load(@array_as_yaml)
26
+ end
27
+ end
28
+
29
+ context '`dump` class method' do
30
+ should 'exist' do
31
+ assert PaperTrail::Serializers::Yaml.respond_to?(:dump)
32
+ end
33
+
34
+ should '`serialize` Ruby to YAML' do
35
+ assert_equal @hash_as_yaml, PaperTrail::Serializers::Yaml.dump(@hash)
36
+ assert_equal @array_as_yaml, PaperTrail::Serializers::Yaml.dump(@array)
37
+ end
38
+ end
39
+
40
+ end
@@ -0,0 +1,44 @@
1
+ require 'test_helper'
2
+
3
+ class TimestampTest < ActiveSupport::TestCase
4
+
5
+ setup do
6
+ PaperTrail.timestamp_field = :custom_created_at
7
+ change_schema
8
+ PaperTrail::Version.connection.schema_cache.clear!
9
+ PaperTrail::Version.reset_column_information
10
+
11
+ Fluxor.instance_eval <<-END
12
+ has_paper_trail
13
+ END
14
+
15
+ @fluxor = Fluxor.create :name => 'Some text.'
16
+ @fluxor.update_attributes :name => 'Some more text.'
17
+ @fluxor.update_attributes :name => 'Even more text.'
18
+ end
19
+
20
+ teardown do
21
+ PaperTrail.timestamp_field = :created_at
22
+ end
23
+
24
+ test 'versions works with custom timestamp field' do
25
+ # Normal behaviour
26
+ assert_equal 3, @fluxor.versions.length
27
+ assert_nil @fluxor.versions[0].reify
28
+ assert_equal 'Some text.', @fluxor.versions[1].reify.name
29
+ assert_equal 'Some more text.', @fluxor.versions[2].reify.name
30
+
31
+ # Tinker with custom timestamps.
32
+ now = Time.now.utc
33
+ @fluxor.versions.reverse.each_with_index do |version, index|
34
+ version.update_attribute :custom_created_at, (now + index.seconds)
35
+ end
36
+
37
+ # Test we are ordering by custom timestamps.
38
+ @fluxor.versions true # reload association
39
+ assert_nil @fluxor.versions[2].reify
40
+ assert_equal 'Some text.', @fluxor.versions[1].reify.name
41
+ assert_equal 'Some more text.', @fluxor.versions[0].reify.name
42
+ end
43
+
44
+ end
@@ -0,0 +1,74 @@
1
+ require 'test_helper'
2
+
3
+ class PaperTrail::VersionTest < ActiveSupport::TestCase
4
+ setup do
5
+ change_schema
6
+ @animal = Animal.create
7
+ assert PaperTrail::Version.creates.present?
8
+ end
9
+
10
+ context "PaperTrail::Version.creates" do
11
+ should "return only create events" do
12
+ PaperTrail::Version.creates.each do |version|
13
+ assert_equal "create", version.event
14
+ end
15
+ end
16
+ end
17
+
18
+ context "PaperTrail::Version.updates" do
19
+ setup {
20
+ @animal.update_attributes(:name => 'Animal')
21
+ assert PaperTrail::Version.updates.present?
22
+ }
23
+
24
+ should "return only update events" do
25
+ PaperTrail::Version.updates.each do |version|
26
+ assert_equal "update", version.event
27
+ end
28
+ end
29
+ end
30
+
31
+ context "PaperTrail::Version.destroys" do
32
+ setup {
33
+ @animal.destroy
34
+ assert PaperTrail::Version.destroys.present?
35
+ }
36
+
37
+ should "return only destroy events" do
38
+ PaperTrail::Version.destroys.each do |version|
39
+ assert_equal "destroy", version.event
40
+ end
41
+ end
42
+ end
43
+
44
+ context "PaperTrail::Version.not_creates" do
45
+ setup {
46
+ @animal.update_attributes(:name => 'Animal')
47
+ @animal.destroy
48
+ assert PaperTrail::Version.not_creates.present?
49
+ }
50
+
51
+ should "return all items except create events" do
52
+ PaperTrail::Version.not_creates.each do |version|
53
+ assert_not_equal "create", version.event
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ class VersionTest < ActiveSupport::TestCase
60
+ # without this, it sometimes picks up the changed schema from the previous test and gets confused
61
+ setup { PaperTrail::Version.reset_column_information }
62
+
63
+ context "Version class" do
64
+ should "be a subclass of the `PaperTrail::Version` class" do
65
+ assert Version < PaperTrail::Version
66
+ end
67
+
68
+ should "act like a `PaperTrail::Version` while warning the user" do
69
+ widget = Widget.create! :name => Faker::Name.name
70
+ widget.update_attributes! :name => Faker::Name.name
71
+ assert_equal Version.last.reify.name, widget.versions.last.reify.name
72
+ end
73
+ end
74
+ end