secretary-rails 1.0.0 → 1.1.0
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.
- data/README.md +4 -10
- data/app/models/concerns/secretary/user_activity_association.rb +11 -0
- data/app/models/secretary/version.rb +3 -1
- data/lib/generators/secretary/install_generator.rb +5 -1
- data/lib/generators/secretary/templates/secretary_config.rb +4 -0
- data/lib/generators/secretary/templates/versions_migration.rb +1 -1
- data/lib/secretary/engine.rb +10 -0
- data/lib/secretary/gem_version.rb +1 -1
- data/lib/secretary/has_secretary.rb +25 -9
- data/lib/secretary/tracks_association.rb +19 -5
- data/lib/secretary/versioned_attributes.rb +23 -2
- data/spec/internal/app/models/user.rb +0 -2
- data/spec/internal/config/database.yml +3 -0
- data/spec/internal/db/combustion_test.sqlite +0 -0
- data/spec/internal/log/test.log +11353 -0
- data/spec/lib/generators/secretary/install_generator_spec.rb +6 -1
- data/spec/lib/secretary/dirty_singular_association_spec.rb +28 -11
- data/spec/lib/secretary/user_activity_association.rb +8 -0
- data/spec/models/secretary/version_spec.rb +16 -2
- data/spec/tmp/config/initializers/secretary.rb +4 -0
- data/spec/tmp/db/migrate/{20131119071129_create_versions.rb → 20140320004842_secretary_create_versions.rb} +1 -1
- metadata +57 -78
- checksums.yaml +0 -7
data/README.md
CHANGED
@@ -162,6 +162,8 @@ class ArticlesController < ApplicationControler
|
|
162
162
|
end
|
163
163
|
```
|
164
164
|
|
165
|
+
**Protip**: Using `outpost-secretary`? This is taken care of for you. Just be sure to add the `logged_user_id` to your Strong Parameters.
|
166
|
+
|
165
167
|
### Viewing Diffs
|
166
168
|
The `Secretary::Version` model allows you to see unix-style diffs of the
|
167
169
|
changes, using the [`diffy`](http://rubygems.org/gems/diffy) gem. The diffs
|
@@ -196,15 +198,7 @@ Diffy also provides several other output formats. See
|
|
196
198
|
[diffy's README](https://github.com/samg/diffy/tree/master) for more options.
|
197
199
|
|
198
200
|
### Configuration
|
199
|
-
|
200
|
-
|
201
|
-
```ruby
|
202
|
-
# This is a list of all the possible configurations and their defaults.
|
203
|
-
Secretary.configure do |config|
|
204
|
-
config.user_class = "::User"
|
205
|
-
config.ignored_attributes = ["id", "created_at", "updated_at"]
|
206
|
-
end
|
207
|
-
```
|
201
|
+
The install task will create an initializer for you with the following options:
|
208
202
|
|
209
203
|
* **user_class** - The class for your user model.
|
210
204
|
* **ignored_attributes** - The attributes which should always be ignored
|
@@ -249,7 +243,7 @@ class Article < ActiveRecord::Base
|
|
249
243
|
end
|
250
244
|
|
251
245
|
Article.versioned_attributes # => ["headline", "images"]
|
252
|
-
```
|
246
|
+
```
|
253
247
|
|
254
248
|
#### Changes vs. Versions
|
255
249
|
There is one aspect that may seem a bit confusing. The behavior of
|
@@ -33,11 +33,13 @@ module Secretary
|
|
33
33
|
private
|
34
34
|
|
35
35
|
def generate_description(object, attributes)
|
36
|
+
changed_attributes = attributes.map(&:humanize).to_sentence
|
37
|
+
|
36
38
|
if was_created?(object)
|
37
39
|
"Created #{object.class.name.titleize} ##{object.id}"
|
38
40
|
|
39
41
|
elsif was_updated?(object)
|
40
|
-
"Changed #{
|
42
|
+
"Changed #{changed_attributes}"
|
41
43
|
|
42
44
|
else
|
43
45
|
"Generated Version"
|
@@ -17,7 +17,11 @@ module Secretary
|
|
17
17
|
source_root File.expand_path("../templates", __FILE__)
|
18
18
|
|
19
19
|
def copy_migration
|
20
|
-
migration_template "versions_migration.rb", "db/migrate/
|
20
|
+
migration_template "versions_migration.rb", "db/migrate/secretary_create_versions"
|
21
|
+
end
|
22
|
+
|
23
|
+
def copy_config
|
24
|
+
template "secretary_config.rb", "config/initializers/secretary.rb"
|
21
25
|
end
|
22
26
|
end
|
23
27
|
end
|
data/lib/secretary/engine.rb
CHANGED
@@ -1,4 +1,14 @@
|
|
1
1
|
module Secretary
|
2
2
|
class Engine < ::Rails::Engine
|
3
|
+
# This is necessary to support rails 3, which doesn't autoload
|
4
|
+
# the concerns directory
|
5
|
+
config.autoload_paths << File.expand_path(
|
6
|
+
"../../../app/models/concerns", __FILE__)
|
7
|
+
|
8
|
+
config.to_prepare do
|
9
|
+
Secretary.config.user_class.constantize.instance_eval do
|
10
|
+
include Secretary::UserActivityAssociation
|
11
|
+
end
|
12
|
+
end
|
3
13
|
end
|
4
14
|
end
|
@@ -3,19 +3,33 @@ module Secretary
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
module ClassMethods
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# Check if a class is versioned
|
7
|
+
#
|
8
|
+
# Example
|
9
|
+
#
|
10
|
+
# Story.has_secretary? # => true or false
|
11
|
+
#
|
12
|
+
# Returns boolean
|
8
13
|
def has_secretary?
|
9
14
|
!!@_has_secretary
|
10
15
|
end
|
11
16
|
|
12
|
-
# Declare that this class
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
17
|
+
# Declare that this class should be versioned.
|
18
|
+
#
|
19
|
+
# Arguments
|
20
|
+
#
|
21
|
+
# * options (Hash) -
|
22
|
+
# * `on` (Array) - Array of Strings which specifies which
|
23
|
+
# attributes should be versioned.
|
24
|
+
# * `except` (Array) - Array of Strings which specifies which
|
25
|
+
# attributes should NOT be versioned.
|
26
|
+
#
|
27
|
+
# Examples
|
28
|
+
#
|
29
|
+
# has_secretary on: ["published_at", "user_id"]
|
30
|
+
# has_secretary except: ["id", "created_at"]
|
31
|
+
#
|
32
|
+
# Returns nothing
|
19
33
|
def has_secretary(options={})
|
20
34
|
@_has_secretary = true
|
21
35
|
Secretary.versioned_models.push self.name
|
@@ -42,6 +56,8 @@ module Secretary
|
|
42
56
|
|
43
57
|
module InstanceMethodsOnActivation
|
44
58
|
# Generate a version for this object.
|
59
|
+
#
|
60
|
+
# Returns nothing
|
45
61
|
def generate_version
|
46
62
|
Version.generate(self)
|
47
63
|
end
|
@@ -8,7 +8,12 @@ module Secretary
|
|
8
8
|
# the saved record will get a new version, with association
|
9
9
|
# diffs and everything.
|
10
10
|
#
|
11
|
-
#
|
11
|
+
# Arguments
|
12
|
+
#
|
13
|
+
# associations - (Symbols) A variable number of association
|
14
|
+
# names to track
|
15
|
+
#
|
16
|
+
# Example
|
12
17
|
#
|
13
18
|
# has_secretary
|
14
19
|
#
|
@@ -25,7 +30,7 @@ module Secretary
|
|
25
30
|
# in, for example, form params). This also lets you easily share this
|
26
31
|
# method with `accepts_nested_attributes_for`.
|
27
32
|
#
|
28
|
-
# Example
|
33
|
+
# Example
|
29
34
|
#
|
30
35
|
# class Person < ActiveRecord::Base
|
31
36
|
# has_secretary
|
@@ -41,6 +46,8 @@ module Secretary
|
|
41
46
|
# attributes['name'].blank?
|
42
47
|
# end
|
43
48
|
# end
|
49
|
+
#
|
50
|
+
# Returns nothing
|
44
51
|
def tracks_association(*associations)
|
45
52
|
if !self.has_secretary?
|
46
53
|
raise NotVersionedError, self.name
|
@@ -56,8 +63,9 @@ module Secretary
|
|
56
63
|
end
|
57
64
|
|
58
65
|
# If the environment is loaded, the following line will be
|
59
|
-
# evaluated for any `tracks_association` calls.
|
60
|
-
# calls `self.column_names`,
|
66
|
+
# evaluated for any `tracks_association` calls.
|
67
|
+
# `versioned_attributes` calls `self.column_names`,
|
68
|
+
# which requires the table to exist.
|
61
69
|
#
|
62
70
|
# So the problem is that if our database or table doesn't exist,
|
63
71
|
# we can't load the environment, and the environment needs to be
|
@@ -66,8 +74,14 @@ module Secretary
|
|
66
74
|
# So, we rescue! And warn.
|
67
75
|
begin
|
68
76
|
self.versioned_attributes << name.to_s
|
77
|
+
|
78
|
+
if reflection.macro == :belongs_to
|
79
|
+
self.versioned_attributes << reflection.foreign_key
|
80
|
+
end
|
81
|
+
|
69
82
|
rescue => e
|
70
|
-
warn "Caught an error while
|
83
|
+
warn "[secretary-rails] Caught an error while loading " \
|
84
|
+
"#{self.name}. #{e}"
|
71
85
|
end
|
72
86
|
|
73
87
|
define_dirty_association_methods(name, reflection)
|
@@ -6,7 +6,11 @@ module Secretary
|
|
6
6
|
class << self
|
7
7
|
# Set the attributes which Secretary should keep track of.
|
8
8
|
#
|
9
|
-
#
|
9
|
+
# Arguments
|
10
|
+
#
|
11
|
+
# * attributes - (Hash) The attributes that should be versioned.
|
12
|
+
#
|
13
|
+
# Example
|
10
14
|
#
|
11
15
|
# class Article < ActiveRecord::Base
|
12
16
|
# self.versioned_attributes = [:id, :created_at]
|
@@ -17,14 +21,21 @@ module Secretary
|
|
17
21
|
# which attributes to ignore.
|
18
22
|
#
|
19
23
|
# Each takes an array of column names *as strings*.
|
24
|
+
#
|
25
|
+
# Returns Hash
|
20
26
|
def versioned_attributes=(attributes)
|
21
27
|
verify_strings!(attributes)
|
22
28
|
@versioned_attributes = attributes
|
23
29
|
end
|
24
30
|
|
31
|
+
|
32
|
+
# We need to rescue here because this method might be called when
|
33
|
+
# running a database task, before the table has been created.
|
34
|
+
# Since we're calling `column_names`, which checks the database
|
35
|
+
# directly, it will throw an error if the table doesn't exist.
|
25
36
|
def versioned_attributes
|
26
37
|
@versioned_attributes ||=
|
27
|
-
|
38
|
+
__safe_column_names -
|
28
39
|
Secretary.config.ignored_attributes -
|
29
40
|
unversioned_attributes
|
30
41
|
end
|
@@ -34,6 +45,7 @@ module Secretary
|
|
34
45
|
self.versioned_attributes -= attributes
|
35
46
|
end
|
36
47
|
|
48
|
+
|
37
49
|
private
|
38
50
|
|
39
51
|
def unversioned_attributes
|
@@ -46,6 +58,15 @@ module Secretary
|
|
46
58
|
"Versioned attributes must be declared as strings."
|
47
59
|
end
|
48
60
|
end
|
61
|
+
|
62
|
+
def __safe_column_names
|
63
|
+
begin
|
64
|
+
self.column_names
|
65
|
+
rescue ActiveRecord::StatementInvalid => e
|
66
|
+
warn "Caught an error when loading #{self.name}: #{e}\n"
|
67
|
+
return []
|
68
|
+
end
|
69
|
+
end
|
49
70
|
end
|
50
71
|
end
|
51
72
|
|
Binary file
|