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 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
- In an initializer (may we suggest `secretary.rb`?), add:
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
@@ -0,0 +1,11 @@
1
+ module Secretary
2
+ module UserActivityAssociation
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ has_many :activities,
7
+ :class_name => "Secretary::Version",
8
+ :foreign_key => "user_id"
9
+ end
10
+ end
11
+ end
@@ -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 #{attributes.to_sentence}"
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/create_versions"
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
@@ -0,0 +1,4 @@
1
+ Secretary.configure do |config|
2
+ # config.user_class = "::User"
3
+ # config.ignored_attributes = ["id", "created_at", "updated_at"]
4
+ end
@@ -4,7 +4,7 @@ class SecretaryCreateVersions < ActiveRecord::Migration
4
4
  t.integer "version_number"
5
5
  t.string "versioned_type"
6
6
  t.integer "versioned_id"
7
- t.string "user_id"
7
+ t.integer "user_id"
8
8
  t.text "description"
9
9
  t.text "object_changes"
10
10
  t.datetime "created_at"
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Secretary
2
- GEM_VERSION = "1.0.0"
2
+ GEM_VERSION = "1.1.0"
3
3
  end
@@ -3,19 +3,33 @@ module Secretary
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  module ClassMethods
6
- # (Boolean) Check if a class is versioned
7
- # Story.has_secretary? # => true or false
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 shoudl be versioned.
13
- #
14
- # Options:
15
- # * `on` : Array of Strings which specifies which attributes should be
16
- # versioned.
17
- # * `except` : Array of Strings which specifies which attributes should
18
- # NOT be versioned.
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
- # Example:
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. `versioned_attributes`
60
- # calls `self.column_names`, which requires the table to exist.
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 updating versioned attributes. #{e}"
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
- # Example:
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
- self.column_names -
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
 
@@ -1,6 +1,4 @@
1
1
  class User < ActiveRecord::Base
2
- has_many :activities, :class_name => "Secretary::Version"
3
-
4
2
  has_many :story_users
5
3
  has_many :stories, :through => :story_users
6
4
  end
@@ -0,0 +1,3 @@
1
+ test:
2
+ adapter: postgresql
3
+ database: combustion_test