acts-as-approvable 0.6.1

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 (61) hide show
  1. data/.gitignore +6 -0
  2. data/Appraisals +18 -0
  3. data/CHANGELOG +10 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +50 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +108 -0
  8. data/Rakefile +81 -0
  9. data/VERSION +1 -0
  10. data/acts-as-approvable.gemspec +31 -0
  11. data/gemfiles/rails2.gemfile +7 -0
  12. data/gemfiles/rails2.gemfile.lock +50 -0
  13. data/gemfiles/rails30.gemfile +8 -0
  14. data/gemfiles/rails30.gemfile.lock +90 -0
  15. data/gemfiles/rails31.gemfile +8 -0
  16. data/gemfiles/rails31.gemfile.lock +101 -0
  17. data/gemfiles/rails32.gemfile +8 -0
  18. data/gemfiles/rails32.gemfile.lock +99 -0
  19. data/generators/acts_as_approvable/USAGE +3 -0
  20. data/generators/acts_as_approvable/acts_as_approvable_generator.rb +86 -0
  21. data/generators/acts_as_approvable/templates/approvals_controller.rb +97 -0
  22. data/generators/acts_as_approvable/templates/create_approvals.rb +26 -0
  23. data/generators/acts_as_approvable/templates/initializer.rb +3 -0
  24. data/generators/acts_as_approvable/templates/views/erb/_owner_select.html.erb +4 -0
  25. data/generators/acts_as_approvable/templates/views/erb/_table.html.erb +26 -0
  26. data/generators/acts_as_approvable/templates/views/erb/index.html.erb +15 -0
  27. data/generators/acts_as_approvable/templates/views/haml/_owner_select.html.haml +3 -0
  28. data/generators/acts_as_approvable/templates/views/haml/_table.html.haml +19 -0
  29. data/generators/acts_as_approvable/templates/views/haml/index.html.haml +13 -0
  30. data/init.rb +1 -0
  31. data/lib/acts-as-approvable/version.rb +3 -0
  32. data/lib/acts_as_approvable/acts_as_approvable.rb +291 -0
  33. data/lib/acts_as_approvable/approval.rb +179 -0
  34. data/lib/acts_as_approvable/error.rb +31 -0
  35. data/lib/acts_as_approvable/ownership.rb +117 -0
  36. data/lib/acts_as_approvable/railtie.rb +7 -0
  37. data/lib/acts_as_approvable.rb +66 -0
  38. data/lib/generators/acts_as_approvable/USAGE +1 -0
  39. data/lib/generators/acts_as_approvable/acts_as_approvable_generator.rb +73 -0
  40. data/lib/generators/acts_as_approvable/templates/approvals_controller.rb +97 -0
  41. data/lib/generators/acts_as_approvable/templates/create_approvals.rb +26 -0
  42. data/lib/generators/acts_as_approvable.rb +0 -0
  43. data/lib/generators/erb/acts_as_approvable_generator.rb +44 -0
  44. data/lib/generators/erb/templates/_owner_select.html.erb +4 -0
  45. data/lib/generators/erb/templates/_table.html.erb +26 -0
  46. data/lib/generators/erb/templates/index.html.erb +15 -0
  47. data/lib/generators/haml/acts_as_approvable_generator.rb +44 -0
  48. data/lib/generators/haml/templates/_owner_select.html.haml +3 -0
  49. data/lib/generators/haml/templates/_table.html.haml +19 -0
  50. data/lib/generators/haml/templates/index.html.haml +13 -0
  51. data/lib/tasks/acts_as_approvable.rake +4 -0
  52. data/rails/init.rb +1 -0
  53. data/test/acts_as_approvable_model_test.rb +428 -0
  54. data/test/acts_as_approvable_ownership_test.rb +132 -0
  55. data/test/acts_as_approvable_schema_test.rb +13 -0
  56. data/test/acts_as_approvable_test.rb +8 -0
  57. data/test/database.yml +7 -0
  58. data/test/schema.rb +44 -0
  59. data/test/support.rb +19 -0
  60. data/test/test_helper.rb +60 -0
  61. metadata +225 -0
@@ -0,0 +1,291 @@
1
+ module ActsAsApprovable
2
+ ##
3
+ # The meat of {ActsAsApprovable}. This applies methods for the configured approval events
4
+ # and configures the required relationships.
5
+ module Model
6
+ def self.included(base)
7
+ base.send :extend, ClassMethods
8
+ end
9
+
10
+ ##
11
+ # Class methods added to `ActiveRecord::Base`.
12
+ module ClassMethods
13
+ # Declare this in your model to require approval on new records or changes to fields.
14
+ #
15
+ # @param [Hash] options the options for this models approval workflow.
16
+ # @option options [Symbol,Array] :on The events to require approval on (`:create` or `:update`).
17
+ # @option options [String] :state_field The local field to store `:create` approval state.
18
+ # @option options [Array] :ignore A list of fields to ignore. By default we ignore `:created_at`, `:updated_at` and
19
+ # the field specified in `:state_field`.
20
+ # @option options [Array] :only A list of fields to explicitly require approval on. This list supercedes `:ignore`.
21
+ def acts_as_approvable(options = {})
22
+ include InstanceMethods
23
+
24
+ cattr_accessor :approvable_on
25
+ self.approvable_on = Array.wrap(options.delete(:on) { [:create, :update] })
26
+
27
+ cattr_accessor :approvable_field
28
+ self.approvable_field = options.delete(:state_field)
29
+
30
+ cattr_accessor :approvable_ignore
31
+ ignores = Array.wrap(options.delete(:ignore) { [] })
32
+ ignores.push('created_at', 'updated_at', self.approvable_field)
33
+ self.approvable_ignore = ignores.compact.uniq.map(&:to_s)
34
+
35
+ cattr_accessor :approvable_only
36
+ self.approvable_only = Array.wrap(options.delete(:only) { [] }).uniq.map(&:to_s)
37
+
38
+ cattr_accessor :approvals_active
39
+ self.approvals_active = true
40
+
41
+ has_many :approvals, :as => :item, :dependent => :destroy
42
+
43
+ if self.approvable_on.include?(:update)
44
+ include UpdateInstanceMethods
45
+ before_update :approvable_update, :if => :approvable_update?
46
+ end
47
+
48
+ if self.approvable_on.include?(:create)
49
+ include CreateInstanceMethods
50
+ before_create :approvable_create, :if => :approvable_create?
51
+ end
52
+
53
+ after_save :approvable_save, :if => :approvals_enabled?
54
+ end
55
+
56
+ ##
57
+ # Enable the approval queue for this model.
58
+ def approvals_on
59
+ self.approvals_active = true
60
+ end
61
+
62
+ ##
63
+ # Disable the approval queue for this model.
64
+ def approvals_off
65
+ self.approvals_active = false
66
+ end
67
+
68
+ ##
69
+ # Execute a code block while the approval queue is temporarily disabled. The
70
+ # queue state will be returned to it's previous value, either on or off.
71
+ def without_approval(&block)
72
+ enable = self.approvals_active
73
+ approvals_off
74
+ yield(self)
75
+ ensure
76
+ approvals_on if enable
77
+ end
78
+ end
79
+
80
+ ##
81
+ # Instance methods that apply to the `:create` event specifically.
82
+ module CreateInstanceMethods
83
+ ##
84
+ # Retrieve approval record for the creation event.
85
+ #
86
+ # @return [Approval]
87
+ def approval
88
+ approvals.find_by_event('create')
89
+ end
90
+
91
+ ##
92
+ # Get the approval state of the current record from either the local state
93
+ # field or, if no state field exists, the creation approval object.
94
+ #
95
+ # @return [String] one of `'pending'`, `'approved`' or `'rejected'`.
96
+ def approval_state
97
+ if self.class.approvable_field
98
+ send(self.class.approvable_field)
99
+ else
100
+ approval.state
101
+ end
102
+ end
103
+
104
+ ##
105
+ # Set the records local approval state.
106
+ #
107
+ # @param [String] state one of `'pending'`, `'approved`' or `'rejected'`.
108
+ def set_approval_state(state)
109
+ return unless self.class.approvable_field
110
+ send("#{self.class.approvable_field}=".to_sym, state)
111
+ end
112
+
113
+ ##
114
+ # Returns true if the record is pending approval.
115
+ def pending?
116
+ approval_state == 'pending' or approval.present? and !approved? and !rejected?
117
+ end
118
+
119
+ ##
120
+ # Returns true if the record has been approved.
121
+ def approved?
122
+ approval_state == 'approved' or approval.nil? or approval.approved?
123
+ end
124
+
125
+ ##
126
+ # Returns true if the record has been rejected.
127
+ def rejected?
128
+ approval_state == 'rejected' or approval.present? and approval.rejected?
129
+ end
130
+
131
+ ##
132
+ # Approves the record through {Approval#approve!}
133
+ #
134
+ # @return [Boolean]
135
+ def approve!
136
+ return unless approvable_on?(:create) && approval.present?
137
+ approval.approve!
138
+ end
139
+
140
+ ##
141
+ # Rejects the record through {Approval#reject!}
142
+ #
143
+ # @return [Boolean]
144
+ def reject!
145
+ return unless approvable_on?(:create) && approval.present?
146
+ approval.reject!
147
+ end
148
+
149
+ private
150
+ def approvable_create?
151
+ approvals_enabled? and approvable_on?(:create)
152
+ end
153
+
154
+ def approvable_create
155
+ @approval = approvals.build(:event => 'create', :state => 'pending')
156
+ set_approval_state('pending')
157
+ end
158
+ end
159
+
160
+ ##
161
+ # Instance methods that apply to the :update event specifically.
162
+ module UpdateInstanceMethods
163
+ ##
164
+ # Retrieve all approval records for `:update` events.
165
+ def update_approvals
166
+ approvals.find_all_by_event('update')
167
+ end
168
+
169
+ ##
170
+ # Returns true if the record has any `#update_approvals` that are pending
171
+ # approval.
172
+ def pending_changes?
173
+ !update_approvals.empty?
174
+ end
175
+
176
+ ##
177
+ # Returns true if any notable (eg. not ignored) fields have been changed.
178
+ def changed_notably?
179
+ notably_changed.any?
180
+ end
181
+
182
+ ##
183
+ # Returns an array of any notable (eg. not ignored) fields that have not
184
+ # been changed.
185
+ #
186
+ # @return [Array] a list of changed fields.
187
+ def notably_changed
188
+ unless self.class.approvable_only.empty?
189
+ self.class.approvable_only.select { |field| changed.include?(field) }
190
+ else
191
+ changed - self.class.approvable_ignore
192
+ end
193
+ end
194
+
195
+ private
196
+ def approvable_update?
197
+ approvals_enabled? and approvable_on?(:update) and changed_notably?
198
+ end
199
+
200
+ def approvable_update
201
+ changed = {}
202
+ notably_changed.each do |attr|
203
+ original, changed_to = changes[attr]
204
+
205
+ write_attribute(attr.to_s, original)
206
+ changed[attr] = changed_to
207
+ end
208
+
209
+ @approval = approvals.build(:event => 'update', :state => 'pending', :object => changed)
210
+ end
211
+ end
212
+
213
+ ##
214
+ # Instance methods that apply to both `:update` and `:create` events.
215
+ module InstanceMethods
216
+ ##
217
+ # Returns true if the approval queue is active at both the local and global
218
+ # level. Note that the global level supercedes the local level.
219
+ def approvals_enabled?
220
+ ActsAsApprovable.enabled? and self.class.approvals_active and approvals_on?
221
+ end
222
+
223
+ ##
224
+ # Returns the inverse of `#approvals_enabled?`
225
+ def approvals_disabled?
226
+ !approvals_enabled?
227
+ end
228
+
229
+ def approvals_off
230
+ @approvals_disabled = true
231
+ end
232
+
233
+ def approvals_on
234
+ @approvals_disabled = false
235
+ end
236
+
237
+ def approvals_on?
238
+ not @approvals_disabled
239
+ end
240
+
241
+ ##
242
+ # Returns true if the model is configured to use the approval queue on the
243
+ # given event (`:create` or `:update`).
244
+ def approvable_on?(event)
245
+ self.class.approvable_on.include?(event)
246
+ end
247
+
248
+ ##
249
+ # A filter that is run before the record can be approved. Returning false
250
+ # stops the approval process from completing.
251
+ def before_approve(approval); end
252
+
253
+ ##
254
+ # A filter that is run after the record has been approved.
255
+ def after_approve(approval); end
256
+
257
+ ##
258
+ # A filter that is run before the record can be rejected. Returning false
259
+ # stops the rejection process from completing.
260
+ def before_reject(approval); end
261
+
262
+ ##
263
+ # A filter that is run after the record has been rejected.
264
+ def after_reject(approval); end
265
+
266
+ ##
267
+ # Execute a code block while the approval queue is temporarily disabled. The
268
+ # queue state will be returned to it's previous value, either on or off.
269
+ def without_approval(&block)
270
+ enable = approvals_on? # If we use #approvals_enabled? the global state might be incorrectly applied.
271
+ approvals_off
272
+ yield(self)
273
+ ensure
274
+ approvals_on if enable
275
+ end
276
+
277
+ def save_without_approval(*args)
278
+ without_approval { |i| save(*args) }
279
+ end
280
+
281
+ def save_without_approval!(*args)
282
+ without_approval { |i| save!(*args) }
283
+ end
284
+
285
+ private
286
+ def approvable_save
287
+ @approval.save if @approval.present? && @approval.new_record?
288
+ end
289
+ end
290
+ end
291
+ end
@@ -0,0 +1,179 @@
1
+ class Approval < ActiveRecord::Base
2
+ ##
3
+ # Enumeration of available states.
4
+ STATES = %w(pending approved rejected)
5
+
6
+ belongs_to :item, :polymorphic => true
7
+
8
+ validates_presence_of :item
9
+ validates_inclusion_of :event, :in => %w(create update)
10
+ validates_numericality_of :state, :greater_than_or_equal_to => 0, :less_than => STATES.length
11
+
12
+ serialize :object
13
+
14
+ before_save :can_save?
15
+
16
+ ##
17
+ # Find the enumerated value for a given state.
18
+ #
19
+ # @return [Integer]
20
+ def self.enumerate_state(state)
21
+ enumerate_states(state).first
22
+ end
23
+
24
+ ##
25
+ # Find the enumerated values for a list of states.
26
+ #
27
+ # @return [Array]
28
+ def self.enumerate_states(*states)
29
+ states.map { |name| STATES.index(name) }.compact
30
+ end
31
+
32
+ ##
33
+ # Build an array of states usable by Rails' `#options_for_select`.
34
+ def self.options_for_state
35
+ options = [['All', -1]]
36
+ STATES.each_index { |x| options << [STATES[x].capitalize, x] }
37
+ options
38
+ end
39
+
40
+ ##
41
+ # Build an array of types usable by Rails' `#options_for_select`.
42
+ def self.options_for_type(with_prompt = false)
43
+ types = all(:select => 'DISTINCT(item_type)').map { |row| row.item_type }
44
+ types.unshift(['All Types', nil]) if with_prompt
45
+ types
46
+ end
47
+
48
+ ##
49
+ # Get the current state of the approval. Converts from integer via {STATES} constant.
50
+ def state
51
+ STATES[(read_attribute(:state) || 0)]
52
+ end
53
+
54
+ ##
55
+ # Get the previous state of the approval. Converts from integer via {STATES} constant.
56
+ def state_was
57
+ STATES[(changed_attributes[:state] || 0)]
58
+ end
59
+
60
+ ##
61
+ # Set the state of the approval. Converts from string to integer via {STATES} constant.
62
+ def state=(state)
63
+ state = self.class.enumerate_state(state) if state.is_a?(String)
64
+ write_attribute(:state, state)
65
+ end
66
+
67
+ ##
68
+ # Returns true if the approval is still pending.
69
+ def pending?
70
+ state == 'pending'
71
+ end
72
+
73
+ ##
74
+ # Returns true if the approval has been approved.
75
+ def approved?
76
+ state == 'approved'
77
+ end
78
+
79
+ ##
80
+ # Returns true if the approval has been rejected.
81
+ def rejected?
82
+ state == 'rejected'
83
+ end
84
+
85
+ ##
86
+ # Returns true if the approval has been approved or rejected.
87
+ def locked?
88
+ approved? or rejected?
89
+ end
90
+
91
+ ##
92
+ # Returns true if the approval has not been approved or rejected.
93
+ def unlocked?
94
+ not locked?
95
+ end
96
+
97
+ ##
98
+ # Returns true if the approval able to be saved. This requires an unlocked
99
+ # approval, or an approval just leaving the 'pending' state.
100
+ def can_save?
101
+ unlocked? or state_was == 'pending'
102
+ end
103
+
104
+ ##
105
+ # Returns true if the affected item has been updated since this approval was
106
+ # created.
107
+ def stale?
108
+ unlocked? and item.has_attribute?(:updated_at) and created_at < item.updated_at
109
+ end
110
+
111
+ ##
112
+ # Returns true if the affected item has not been updated since this approval
113
+ # was created.
114
+ def fresh?
115
+ not stale?
116
+ end
117
+
118
+ ##
119
+ # Returns true if this is an `:update` approval event.
120
+ def update?
121
+ event == 'update'
122
+ end
123
+
124
+ ##
125
+ # Returns true if this is a `:create` approval event.
126
+ def create?
127
+ event == 'create'
128
+ end
129
+
130
+ ##
131
+ # Attempt to approve the record change.
132
+ #
133
+ # @param [Boolean] force if the approval record is stale force the acceptance.
134
+ # @raise [ActsAsApprovable::Error::Locked] raised if the record is {#locked? locked}.
135
+ # @raise [ActsAsApprovable::Error::Stale] raised if the record is {#stale? stale} and `force` is false.
136
+ def approve!(force = false)
137
+ raise ActsAsApprovable::Error::Locked if locked?
138
+ raise ActsAsApprovable::Error::Stale if stale? and !force
139
+ return unless run_item_callback(:before_approve)
140
+
141
+ if update?
142
+ data = {}
143
+ object.each do |attr, value|
144
+ data[attr] = value if item.attribute_names.include?(attr)
145
+ end
146
+
147
+ item.attributes = data
148
+ elsif create?
149
+ item.set_approval_state('approved')
150
+ end
151
+
152
+ item.save_without_approval!
153
+ update_attributes!(:state => 'approved')
154
+ run_item_callback(:after_approve)
155
+ end
156
+
157
+ ##
158
+ # Attempt to reject the record change.
159
+ #
160
+ # @param [String] reason a reason for rejecting the change.
161
+ # @raise [ActsAsApprovable::Error::Locked] raised if the record is {#locked? locked}.
162
+ def reject!(reason = nil)
163
+ raise ActsAsApprovable::Error::Locked if locked?
164
+ return unless run_item_callback(:before_reject)
165
+
166
+ if create?
167
+ item.set_approval_state('rejected')
168
+ end
169
+
170
+ item.save_without_approval!
171
+ update_attributes!(:state => 'rejected', :reason => reason)
172
+ run_item_callback(:after_reject)
173
+ end
174
+
175
+ private
176
+ def run_item_callback(callback)
177
+ item.send(callback, self) != false
178
+ end
179
+ end
@@ -0,0 +1,31 @@
1
+ module ActsAsApprovable
2
+ class Error < RuntimeError
3
+ ##
4
+ # Raised when a locked approval is accepted or rejected.
5
+ class Locked < ActsAsApprovable::Error
6
+ def initialize(*args)
7
+ args[0] = 'this approval is locked'
8
+ super(*args)
9
+ end
10
+ end
11
+
12
+ ##
13
+ # Raised when a stale approval is accepted.
14
+ class Stale < ActsAsApprovable::Error
15
+ def initialize(*args)
16
+ args[0] = 'this approval is stale and should not be approved'
17
+ super(*args)
18
+ end
19
+ end
20
+
21
+ ##
22
+ # Raised when a record is assigned as owner that is not found in
23
+ # {ActsAsApprovable::Ownership::ClassMethods#available_owners}.
24
+ class InvalidOwner < ActsAsApprovable::Error
25
+ def initialize(*args)
26
+ args[0] = 'this record cannot be assigned as an owner'
27
+ super(*args)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,117 @@
1
+ module ActsAsApprovable
2
+ ##
3
+ # This module provides the {Approval} class with the ability to assign records
4
+ # as an "owner" of the approval. This is especially useful for tracking purposes
5
+ # when you require it, and can be beneficial when you have an approval queue with
6
+ # a high rate of insertions.
7
+ #
8
+ # By default the ownership functionality will reference a model named `User` and
9
+ # will allow any user to take ownership of an approval.
10
+ module Ownership
11
+ ##
12
+ # Configure approvals to allow ownership by a User model.
13
+ #
14
+ # If a block is given it will be applied to Approval at the class level,
15
+ # allowing you to override functionality on the fly.
16
+ #
17
+ # @param [Hash] options a hash of options for configuration
18
+ # @option options [Object] :model the model being used for Approval records (defaults to `Approval`).
19
+ # @option options [Object] :owner the model being used for owner records (defaults to `User`).
20
+ def self.configure(options = {}, &block)
21
+ approval = options.delete(:model) { Approval }
22
+ owner = options.delete(:owner) { User }
23
+
24
+ approval.send(:include, self)
25
+
26
+ ActsAsApprovable.owner_class = owner
27
+ approval.send(:belongs_to, :owner, :class_name => owner.to_s, :foreign_key => :owner_id)
28
+
29
+ approval.class_exec(&block) if block
30
+ end
31
+
32
+ def self.included(base)
33
+ base.send(:include, InstanceMethods)
34
+ base.extend(ClassMethods)
35
+ end
36
+
37
+ ##
38
+ # Instance methods for approval ownership.
39
+ module InstanceMethods
40
+ ##
41
+ # Set the owner and save the record.
42
+ #
43
+ # @return [Boolean]
44
+ def assign(owner)
45
+ raise ActsAsApprovable::Error::InvalidOwner unless self.class.available_owners.include?(owner)
46
+ self.owner = owner
47
+ save
48
+ end
49
+
50
+ ##
51
+ # Removed any assigned owner and save the record.
52
+ #
53
+ # @return [Boolean]
54
+ def unassign
55
+ self.owner = nil
56
+ save
57
+ end
58
+ end
59
+
60
+ ##
61
+ # Class methods for approval ownership.
62
+ module ClassMethods
63
+ ##
64
+ # Get the model that represents an owner.
65
+ #
66
+ # @see ActsAsApprovable::Ownership.configure
67
+ def owner_class
68
+ ActsAsApprovable.owner_class
69
+ end
70
+
71
+ ##
72
+ # A list of records that can be assigned to an approval. This should be
73
+ # overridden in {ActsAsApprovable::Ownership.configure} to return only the
74
+ # records you wish to manage approvals.
75
+ def available_owners
76
+ owner_class.all
77
+ end
78
+
79
+ ##
80
+ # Build an array from {#available_owners} usable by Rails' `#options_for_select`.
81
+ # Each element in the array is built with {#option_for_owner}.
82
+ #
83
+ # @return [Array]
84
+ def options_for_available_owners(with_prompt = false)
85
+ owners = available_owners.map { |owner| option_for_owner(owner) }
86
+ owners.unshift(['(none)', nil]) if with_prompt
87
+ owners
88
+ end
89
+
90
+ ##
91
+ # A list of owners that have assigned approvals.
92
+ def assigned_owners
93
+ all(:select => 'DISTINCT(owner_id)', :conditions => 'owner_id IS NOT NULL', :include => :owner).map(&:owner)
94
+ end
95
+
96
+ ##
97
+ # Build an array from {#assigned_owners} usable by Rails' `#options_for_select`.
98
+ # Each element in the array is built with {#option_for_owner}.
99
+ #
100
+ # @return [Array]
101
+ def options_for_assigned_owners(with_prompt = false)
102
+ owners = assigned_owners.map { |owner| option_for_owner(owner) }
103
+ owners.unshift(['All Users', nil]) if with_prompt
104
+ owners
105
+ end
106
+
107
+ ##
108
+ # Helper method that takes an owner record and returns an array for Rails'
109
+ # `#options_for_select`.
110
+ #
111
+ # @return [Array] a 2-index array with a display string and value.
112
+ def option_for_owner(owner)
113
+ [owner.to_str, owner.id]
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,7 @@
1
+ module ActsAsApprovable
2
+ class Railtie < Rails::Railtie
3
+ initializer 'acts_as_approvable.configure_rails_initialization' do |app|
4
+ ActiveRecord::Base.send :include, ActsAsApprovable::Model
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,66 @@
1
+ require 'active_record'
2
+
3
+ require 'acts_as_approvable/acts_as_approvable'
4
+ require 'acts_as_approvable/approval'
5
+ require 'acts_as_approvable/error'
6
+ require 'acts_as_approvable/ownership'
7
+ require 'acts-as-approvable/version'
8
+
9
+ if defined?(Rails) && Rails.version =~ /^3\./
10
+ require 'acts_as_approvable/railtie'
11
+ elsif defined?(ActiveRecord)
12
+ ActiveRecord::Base.send :include, ActsAsApprovable::Model
13
+ end
14
+
15
+ module ActsAsApprovable
16
+ ##
17
+ # Enable the approval queue at a global level.
18
+ def self.enable
19
+ @enabled = true
20
+ end
21
+
22
+ ##
23
+ # Disable the approval queue at a global level.
24
+ def self.disable
25
+ @enabled = false
26
+ end
27
+
28
+ ##
29
+ # Returns true if the approval queue is enabled globally.
30
+ def self.enabled?
31
+ @enabled = true if @enabled.nil?
32
+ @enabled
33
+ end
34
+
35
+ ##
36
+ # Set the referenced Owner class to be used by generic finders.
37
+ #
38
+ # @see Ownership
39
+ def self.owner_class=(klass)
40
+ @owner_class = klass
41
+ end
42
+
43
+ ##
44
+ # Get the referenced Owner class to be used by generic finders.
45
+ #
46
+ # @see Ownership
47
+ def self.owner_class
48
+ @owner_class
49
+ end
50
+
51
+ ##
52
+ # Set the engine used for rendering view files.
53
+ def self.view_language=(lang)
54
+ @lang = lang
55
+ end
56
+
57
+ ##
58
+ # Get the engine used for rendering view files. Defaults to 'erb'
59
+ def self.view_language
60
+ if Rails.version =~ /^3\./
61
+ Rails.configuration.generators.rails[:template_engine].try(:to_s) || 'erb'
62
+ else
63
+ @lang || 'erb'
64
+ end
65
+ end
66
+ end
@@ -0,0 +1 @@
1
+ Generates ApprovalsController, a migration the create the Approval table, and an initializer for the plugin.