secretary-rails 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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