draftsman 0.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.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +3 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +97 -0
- data/LICENSE +20 -0
- data/README.md +506 -0
- data/Rakefile +6 -0
- data/draftsman.gemspec +33 -0
- data/lib/draftsman/config.rb +13 -0
- data/lib/draftsman/draft.rb +289 -0
- data/lib/draftsman/frameworks/cucumber.rb +7 -0
- data/lib/draftsman/frameworks/rails.rb +58 -0
- data/lib/draftsman/frameworks/rspec.rb +16 -0
- data/lib/draftsman/frameworks/sinatra.rb +31 -0
- data/lib/draftsman/model.rb +428 -0
- data/lib/draftsman/serializers/json.rb +17 -0
- data/lib/draftsman/serializers/yaml.rb +17 -0
- data/lib/draftsman/version.rb +3 -0
- data/lib/draftsman.rb +101 -0
- data/lib/generators/draftsman/install_generator.rb +27 -0
- data/lib/generators/draftsman/templates/add_object_changes_column_to_drafts.rb +9 -0
- data/lib/generators/draftsman/templates/config/initializers/draftsman.rb +11 -0
- data/lib/generators/draftsman/templates/create_drafts.rb +22 -0
- data/spec/controllers/informants_controller_spec.rb +27 -0
- data/spec/controllers/users_controller_spec.rb +23 -0
- data/spec/controllers/whodunnits_controller_spec.rb +24 -0
- data/spec/draftsman_spec.rb +19 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/images/rails.png +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +20 -0
- data/spec/dummy/app/controllers/informants_controller.rb +8 -0
- data/spec/dummy/app/controllers/users_controller.rb +8 -0
- data/spec/dummy/app/controllers/whodunnits_controller.rb +8 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/helpers/messages_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/bastard.rb +3 -0
- data/spec/dummy/app/models/child.rb +4 -0
- data/spec/dummy/app/models/parent.rb +5 -0
- data/spec/dummy/app/models/trashable.rb +3 -0
- data/spec/dummy/app/models/vanilla.rb +3 -0
- data/spec/dummy/app/models/whitelister.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +15 -0
- data/spec/dummy/config/application.rb +37 -0
- data/spec/dummy/config/boot.rb +6 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +32 -0
- data/spec/dummy/config/environments/production.rb +73 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +6 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20110208155312_set_up_test_tables.rb +86 -0
- data/spec/dummy/db/schema.rb +106 -0
- data/spec/dummy/db/seeds.rb +7 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/lib/tasks/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/models/child_spec.rb +205 -0
- data/spec/models/draft_spec.rb +297 -0
- data/spec/models/parent_spec.rb +191 -0
- data/spec/models/trashable_spec.rb +164 -0
- data/spec/models/vanilla_spec.rb +201 -0
- data/spec/models/whitelister_spec.rb +262 -0
- data/spec/spec_helper.rb +52 -0
- metadata +304 -0
data/draftsman.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
2
|
+
require 'draftsman/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'draftsman'
|
6
|
+
s.version = Draftsman::VERSION
|
7
|
+
s.summary = "Create draft versions of your ActiveRecord models' data."
|
8
|
+
s.description = s.summary
|
9
|
+
s.homepage = 'https://github.com/minimalorange/draftsman'
|
10
|
+
s.authors = ['Chris Peters']
|
11
|
+
s.email = 'chris@minimalorange.com'
|
12
|
+
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
+
s.require_paths = ['lib']
|
17
|
+
|
18
|
+
s.add_dependency 'activerecord', ['>= 3.0', '< 5.0']
|
19
|
+
|
20
|
+
s.add_development_dependency 'capybara'
|
21
|
+
s.add_development_dependency 'rake'
|
22
|
+
s.add_development_dependency 'railties', ['>= 3.0', '< 5.0']
|
23
|
+
s.add_development_dependency 'sinatra', '~> 1.0'
|
24
|
+
s.add_development_dependency 'rspec-rails'
|
25
|
+
s.add_development_dependency 'shoulda-matchers'
|
26
|
+
|
27
|
+
# JRuby support for the test ENV
|
28
|
+
if defined?(JRUBY_VERSION)
|
29
|
+
s.add_development_dependency 'activerecord-jdbcsqlite3-adapter', ['>= 1.3.0.rc1', '< 1.4']
|
30
|
+
else
|
31
|
+
s.add_development_dependency 'sqlite3', '~> 1.2'
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,289 @@
|
|
1
|
+
class Draftsman::Draft < ActiveRecord::Base
|
2
|
+
# Mass assignment (for <= ActiveRecord 3.x)
|
3
|
+
if Draftsman.active_record_protected_attributes?
|
4
|
+
attr_accessible :item_type, :item_id, :event, :whodunnit, :object, :object_changes
|
5
|
+
end
|
6
|
+
|
7
|
+
# Associations
|
8
|
+
belongs_to :item, :polymorphic => true
|
9
|
+
|
10
|
+
# Validations
|
11
|
+
validates_presence_of :event
|
12
|
+
|
13
|
+
def self.with_item_keys(item_type, item_id)
|
14
|
+
scoped :conditions => { :item_type => item_type, :item_id => item_id }
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.creates
|
18
|
+
where :event => 'create'
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.destroys
|
22
|
+
where :event => 'destroy'
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.updates
|
26
|
+
where :event => 'update'
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns what changed in this draft. Similar to `ActiveModel::Dirty#changes`.
|
30
|
+
# Returns `nil` if your `drafts` table does not have an `object_changes` text column.
|
31
|
+
def changeset
|
32
|
+
return nil unless self.class.column_names.include? 'object_changes'
|
33
|
+
|
34
|
+
HashWithIndifferentAccess.new(Draftsman.serializer.load(object_changes)).tap do |changes|
|
35
|
+
item_type.constantize.unserialize_draft_attribute_changes(changes)
|
36
|
+
end
|
37
|
+
rescue
|
38
|
+
{}
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns whether or not this is a `create` event.
|
42
|
+
def create?
|
43
|
+
self.event == 'create'
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns whether or not this is a `destroy` event.
|
47
|
+
def destroy?
|
48
|
+
self.event == 'destroy'
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns related draft dependencies that would be along for the ride for a `publish!` action.
|
52
|
+
def draft_publication_dependencies
|
53
|
+
dependencies = []
|
54
|
+
|
55
|
+
case self.event
|
56
|
+
when 'create', 'update'
|
57
|
+
associations = self.item.class.reflect_on_all_associations(:belongs_to)
|
58
|
+
|
59
|
+
associations.each do |association|
|
60
|
+
association_class =
|
61
|
+
if association.polymorphic?
|
62
|
+
self.item.send(association.foreign_key.sub('_id', '_type')).constantize
|
63
|
+
else
|
64
|
+
association.klass
|
65
|
+
end
|
66
|
+
|
67
|
+
if association_class.draftable? && association.name != association_class.draft_association_name.to_sym
|
68
|
+
dependency = self.item.send(association.name)
|
69
|
+
dependencies << dependency.draft if dependency.present? && dependency.draft? && dependency.draft.create?
|
70
|
+
end
|
71
|
+
end
|
72
|
+
when 'destroy'
|
73
|
+
associations = self.item.class.reflect_on_all_associations(:has_one) + self.item.class.reflect_on_all_associations(:has_many)
|
74
|
+
|
75
|
+
associations.each do |association|
|
76
|
+
if association.klass.draftable?
|
77
|
+
# Reconcile different association types into an array, even if `has_one` produces a single-item
|
78
|
+
associated_dependencies =
|
79
|
+
case association.macro
|
80
|
+
when :has_one
|
81
|
+
self.item.send(association.name).present? ? [self.item.send(association.name)] : []
|
82
|
+
when :has_many
|
83
|
+
self.item.send(association.name)
|
84
|
+
end
|
85
|
+
|
86
|
+
associated_dependencies.each do |dependency|
|
87
|
+
dependencies << dependency.draft if dependency.draft?
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
dependencies
|
94
|
+
end
|
95
|
+
|
96
|
+
# Returns related draft dependencies that would be along for the ride for a `revert!` action.
|
97
|
+
def draft_reversion_dependencies
|
98
|
+
dependencies = []
|
99
|
+
|
100
|
+
case self.event
|
101
|
+
when 'create'
|
102
|
+
associations = self.item.class.reflect_on_all_associations(:has_one) + self.item.class.reflect_on_all_associations(:has_many)
|
103
|
+
|
104
|
+
associations.each do |association|
|
105
|
+
if association.klass.draftable?
|
106
|
+
# Reconcile different association types into an array, even if `has_one` produces a single-item
|
107
|
+
associated_dependencies =
|
108
|
+
case association.macro
|
109
|
+
when :has_one
|
110
|
+
self.item.send(association.name).present? ? [self.item.send(association.name)] : []
|
111
|
+
when :has_many
|
112
|
+
self.item.send(association.name)
|
113
|
+
end
|
114
|
+
|
115
|
+
associated_dependencies.each do |dependency|
|
116
|
+
dependencies << dependency.draft if dependency.draft?
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
when 'destroy'
|
121
|
+
associations = self.item.class.reflect_on_all_associations(:belongs_to)
|
122
|
+
|
123
|
+
associations.each do |association|
|
124
|
+
association_class =
|
125
|
+
if association.polymorphic?
|
126
|
+
self.item.send(association.foreign_key.sub('_id', '_type')).constantize
|
127
|
+
else
|
128
|
+
association.klass
|
129
|
+
end
|
130
|
+
|
131
|
+
if association_class.draftable? && association_class.trashable? && association.name != association_class.draft_association_name.to_sym
|
132
|
+
dependency = self.item.send(association.name)
|
133
|
+
dependencies << dependency.draft if dependency.present? && dependency.draft? && dependency.draft.destroy?
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
dependencies
|
139
|
+
end
|
140
|
+
|
141
|
+
# Publishes this draft's associated `item`, publishes its `item`'s dependencies, and destroys itself.
|
142
|
+
# - For `create` drafts, adds a value for the `published_at` timestamp on the item and destroys the draft.
|
143
|
+
# - For `update` drafts, applies the drafted changes to the item and destroys the draft.
|
144
|
+
# - For `destroy` drafts, destroys the item and the draft.
|
145
|
+
def publish!
|
146
|
+
ActiveRecord::Base.transaction do
|
147
|
+
case self.event
|
148
|
+
when 'create', 'update'
|
149
|
+
# Parents must be published too
|
150
|
+
self.draft_publication_dependencies.each { |dependency| dependency.publish! }
|
151
|
+
|
152
|
+
# Update drafts need to copy over data to main record
|
153
|
+
self.item.attributes = self.reify.attributes if self.update?
|
154
|
+
|
155
|
+
# Write `published_at` attribute
|
156
|
+
self.item.send "#{self.item.class.published_at_attribute_name}=", Time.now
|
157
|
+
|
158
|
+
# Clear out draft
|
159
|
+
self.item.send "#{self.item.class.draft_association_name}_id=", nil
|
160
|
+
|
161
|
+
# Determine which columns should be updated
|
162
|
+
only = self.item.class.draftsman_options[:only]
|
163
|
+
ignore = self.item.class.draftsman_options[:ignore]
|
164
|
+
skip = self.item.class.draftsman_options[:skip]
|
165
|
+
attributes_to_change = only.any? ? only : self.item.attribute_names
|
166
|
+
attributes_to_change = attributes_to_change - ignore + ['published_at', "#{self.item.class.draft_association_name}_id"] - skip
|
167
|
+
|
168
|
+
# Save without validations or callbacks
|
169
|
+
self.item.update_columns self.item.attributes.slice(*attributes_to_change)
|
170
|
+
self.item.reload
|
171
|
+
|
172
|
+
# Destroy draft
|
173
|
+
self.destroy
|
174
|
+
when 'destroy'
|
175
|
+
self.item.destroy
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# Returns instance of item restored to its pre-draft state.
|
181
|
+
#
|
182
|
+
# Example usage:
|
183
|
+
#
|
184
|
+
# `@category = @category.reify if @category.draft?`
|
185
|
+
def reify
|
186
|
+
without_identity_map do
|
187
|
+
unless self.object.nil?
|
188
|
+
# This appears to be necessary if for some reason the draft's model hasn't been loaded (such as when done in the console).
|
189
|
+
require self.item_type.underscore
|
190
|
+
|
191
|
+
model = item.reload
|
192
|
+
|
193
|
+
Draftsman.serializer.load(self.object).each do |key, value|
|
194
|
+
# Skip counter_cache columns
|
195
|
+
if model.respond_to?("#{key}=") && !key.end_with?('_count')
|
196
|
+
model.send "#{key}=", value
|
197
|
+
elsif !key.end_with?('_count')
|
198
|
+
logger.warn "Attribute #{key} does not exist on #{item_type} (Draft ID: #{id})."
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
model.send "#{model.class.draft_association_name}=", self
|
203
|
+
model
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# Reverts this draft.
|
209
|
+
# - For create drafts, destroys the draft and the item.
|
210
|
+
# - For update drafts, destyors the draft only.
|
211
|
+
# - For destroy drafts, destroys the draft and undoes the `trashed_at` timestamp on the item. If a draft was drafted
|
212
|
+
# for destroy, restores the draft.
|
213
|
+
def revert!
|
214
|
+
ActiveRecord::Base.transaction do
|
215
|
+
case self.event
|
216
|
+
when 'create'
|
217
|
+
self.item.destroy
|
218
|
+
self.destroy
|
219
|
+
when 'update'
|
220
|
+
self.item.class.where(:id => self.item).update_all("#{self.item.class.draft_association_name}_id".to_sym => nil)
|
221
|
+
self.destroy
|
222
|
+
when 'destroy'
|
223
|
+
# Parents must be restored too
|
224
|
+
self.draft_reversion_dependencies.each { |dependency| dependency.revert! }
|
225
|
+
|
226
|
+
# Restore previous draft if one was stashed away
|
227
|
+
if self.previous_draft.present?
|
228
|
+
prev_draft = reify_previous_draft
|
229
|
+
self.item.class.where(:id => self.item).update_all "#{self.item.class.draft_association_name}_id".to_sym => prev_draft.id,
|
230
|
+
self.item.class.trashed_at_attribute_name => nil
|
231
|
+
else
|
232
|
+
self.item.class.where(:id => self.item).update_all "#{self.item.class.draft_association_name}_id".to_sym => nil,
|
233
|
+
self.item.class.trashed_at_attribute_name => nil
|
234
|
+
end
|
235
|
+
|
236
|
+
self.destroy
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
# Returns whether or not this is an `update` event.
|
242
|
+
def update?
|
243
|
+
self.event == 'update'
|
244
|
+
end
|
245
|
+
|
246
|
+
private
|
247
|
+
|
248
|
+
# Restores previous draft and returns it.
|
249
|
+
def reify_previous_draft
|
250
|
+
draft = self.class.new
|
251
|
+
|
252
|
+
without_identity_map do
|
253
|
+
Draftsman.serializer.load(self.previous_draft).each do |key, value|
|
254
|
+
if key.to_sym != :id && draft.respond_to?("#{key}=")
|
255
|
+
draft.send "#{key}=", value
|
256
|
+
elsif key.to_sym != :id
|
257
|
+
logger.warn "Attribute #{key} does not exist on #{item_type} (Draft ID: #{self.id})."
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
draft.save!
|
263
|
+
draft
|
264
|
+
end
|
265
|
+
|
266
|
+
# Saves associated draft dependencies by reflecting `belongs_to` associations and identifying which ones are
|
267
|
+
# draftable.
|
268
|
+
#def save_draft_dependencies
|
269
|
+
# self.item.class.reflect_on_all_associations(:belongs_to).each do |association|
|
270
|
+
# associated_object = self.item.send(association.name)
|
271
|
+
#
|
272
|
+
# if associated_object.present? && associated_object.respond_to?(:draft?)
|
273
|
+
# if associated_object.reload.draft?
|
274
|
+
# Draftsman::DraftDependency.create(:draft_id => self.id, :dependency_id => associated_object.id)
|
275
|
+
# else
|
276
|
+
# Draftsman::DraftDependency.where(:draft_id => self.id, :dependency_id => associated_object.id).delete_all
|
277
|
+
# end
|
278
|
+
# end
|
279
|
+
# end
|
280
|
+
#end
|
281
|
+
|
282
|
+
def without_identity_map(&block)
|
283
|
+
if defined?(ActiveRecord::IdentityMap) && ActiveRecord::IdentityMap.respond_to?(:without)
|
284
|
+
ActiveRecord::IdentityMap.without &block
|
285
|
+
else
|
286
|
+
block.call
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Draftsman
|
2
|
+
module Rails
|
3
|
+
module Controller
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
if defined?(ActionController) && base == ActionController::Base
|
7
|
+
base.before_filter :set_draftsman_whodunnit, :set_draftsman_controller_info
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
# Returns the user who is responsible for any changes that occur.
|
14
|
+
# By default this calls `current_user` and returns the result.
|
15
|
+
#
|
16
|
+
# Override this method in your controller to call a different
|
17
|
+
# method, e.g. `current_person`, or anything you like.
|
18
|
+
def user_for_draftsman
|
19
|
+
current_user if defined?(current_user)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns any information about the controller or request that you
|
23
|
+
# want Draftsman to store alongside any changes that occur. By
|
24
|
+
# default, this returns an empty hash.
|
25
|
+
#
|
26
|
+
# Override this method in your controller to return a hash of any
|
27
|
+
# information you need. The hash's keys must correspond to columns
|
28
|
+
# in your `drafts` table, so don't forget to add any new columns
|
29
|
+
# you need.
|
30
|
+
#
|
31
|
+
# For example:
|
32
|
+
#
|
33
|
+
# {:ip => request.remote_ip, :user_agent => request.user_agent}
|
34
|
+
#
|
35
|
+
# The columns `ip` and `user_agent` must exist in your `drafts` # table.
|
36
|
+
#
|
37
|
+
# Use the `:meta` option to `Draftsman::Model::ClassMethods.has_drafts`
|
38
|
+
# to store any extra model-level data you need.
|
39
|
+
def info_for_draftsman
|
40
|
+
{}
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
# Tells Draftsman who is responsible for any changes that occur.
|
46
|
+
def set_draftsman_whodunnit
|
47
|
+
::Draftsman.whodunnit = user_for_draftsman
|
48
|
+
end
|
49
|
+
|
50
|
+
# Tells Draftsman any information from the controller you want
|
51
|
+
# to store alongside any changes that occur.
|
52
|
+
def set_draftsman_controller_info
|
53
|
+
::Draftsman.controller_info = info_for_draftsman
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
if defined? RSpec
|
2
|
+
require 'rspec/core'
|
3
|
+
require 'rspec/matchers'
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
config.before(:each) do
|
7
|
+
::Draftsman.whodunnit = nil
|
8
|
+
::Draftsman.controller_info = {} if defined?(::Rails) && defined?(::RSpec::Rails)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
RSpec::Matchers.define :be_draftable do
|
13
|
+
# check to see if the model has `has_drafts` declared on it
|
14
|
+
match { |actual| actual.kind_of?(::Draftsman::Model::InstanceMethods) }
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Sinatra
|
2
|
+
module Draftsman
|
3
|
+
|
4
|
+
# Register this module inside your Sinatra application to gain access to controller-level methods used by Draftsman
|
5
|
+
def self.registered(app)
|
6
|
+
app.helpers Sinatra::Draftsman
|
7
|
+
app.before { set_draftsman_whodunnit }
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
|
12
|
+
# Returns the user who is responsible for any changes that occur.
|
13
|
+
# By default this calls `current_user` and returns the result.
|
14
|
+
#
|
15
|
+
# Override this method in your controller to call a different
|
16
|
+
# method, e.g. `current_person`, or anything you like.
|
17
|
+
def user_for_draftsman
|
18
|
+
current_user if defined?(current_user)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
# Tells Draftsman who is responsible for any changes that occur.
|
24
|
+
def set_draftsman_whodunnit
|
25
|
+
::Draftsman.whodunnit = user_for_draftsman
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
register Sinatra::Draftsman if defined?(register)
|
31
|
+
end
|