kb-acts_as_revisable 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,491 @@
1
+ module WithoutScope
2
+ module ActsAsRevisable
3
+
4
+ # This module is mixed into the revision classes.
5
+ #
6
+ # ==== Callbacks
7
+ #
8
+ # * +before_revise+ is called before the record is revised.
9
+ # * +after_revise+ is called after the record is revised.
10
+ # * +before_revert+ is called before the record is reverted.
11
+ # * +after_revert+ is called after the record is reverted.
12
+ # * +before_changeset+ is called before a changeset block is called.
13
+ # * +after_changeset+ is called after a changeset block is called.
14
+ # * +after_branch_created+ is called on the new revisable instance
15
+ # created by branching after it's been created.
16
+ module Revisable
17
+ def self.included(base) #:nodoc:
18
+ base.send(:extend, ClassMethods)
19
+
20
+ class << base
21
+ attr_accessor :revisable_revision_class, :revisable_columns
22
+ end
23
+
24
+ base.class_inheritable_hash :revisable_shared_objects
25
+ base.revisable_shared_objects = {}
26
+
27
+ base.instance_eval do
28
+ attr_accessor :revisable_new_params, :revisable_revision
29
+
30
+ define_callbacks :before_revise, :after_revise, :before_revert, :after_revert, :before_changeset, :after_changeset, :after_branch_created
31
+
32
+ before_create :before_revisable_create
33
+ before_update :before_revisable_update
34
+ after_update :after_revisable_update
35
+ after_save :clear_revisable_shared_objects!, :unless => :is_reverting?
36
+
37
+ default_scope :conditions => {:revisable_is_current => true}
38
+
39
+ [:revisions, revisions_association_name.to_sym].each do |assoc|
40
+ has_many assoc, (revisable_options.revision_association_options || {}).merge({:class_name => revision_class_name, :foreign_key => :revisable_original_id, :order => "#{quoted_table_name}.#{connection.quote_column_name(:revisable_number)} DESC", :dependent => :destroy})
41
+ end
42
+ end
43
+
44
+ if !Object.const_defined?(base.revision_class_name) && base.revisable_options.generate_revision_class?
45
+ Object.const_set(base.revision_class_name, Class.new(ActiveRecord::Base)).class_eval do
46
+ acts_as_revision
47
+ end
48
+ end
49
+ end
50
+
51
+ # Finds a specific revision of self.
52
+ #
53
+ # The +by+ parameter can be a revision_class instance,
54
+ # the symbols :first, :previous or :last, a Time instance
55
+ # or an Integer.
56
+ #
57
+ # When passed a revision_class instance, this method
58
+ # simply returns it. This is used primarily by revert_to!.
59
+ #
60
+ # When passed :first it returns the first revision created.
61
+ #
62
+ # When passed :previous or :last it returns the last revision
63
+ # created.
64
+ #
65
+ # When passed a Time instance it returns the revision that
66
+ # was the current record at the given time.
67
+ #
68
+ # When passed an Integer it returns the revision with that
69
+ # revision_number.
70
+ def find_revision(by)
71
+ by = Integer(by) if by.is_a?(String) && by.match(/[0-9]+/)
72
+
73
+ case by
74
+ when self.class
75
+ by
76
+ when self.class.revision_class
77
+ by
78
+ when :first
79
+ revisions.last
80
+ when :previous
81
+ revisions.first
82
+ when Time
83
+ revisions.find(:first, :conditions => ["? >= ? and ? <= ?", :revisable_revised_at, by, :revisable_current_at, by])
84
+ when self.revisable_number
85
+ self
86
+ else
87
+ revisions.find_by_revisable_number(by)
88
+ end
89
+ end
90
+
91
+ # Returns a revisable_class instance initialized with the record
92
+ # found using find_revision.
93
+ #
94
+ # The +what+ parameter is simply passed to find_revision and the
95
+ # returned record forms the basis of the reverted record.
96
+ #
97
+ # ==== Callbacks
98
+ #
99
+ # * +before_revert+ is called before the record is reverted.
100
+ # * +after_revert+ is called after the record is reverted.
101
+ #
102
+ # If :without_revision => true has not been passed the
103
+ # following callbacks are also called:
104
+ #
105
+ # * +before_revise+ is called before the record is revised.
106
+ # * +after_revise+ is called after the record is revised.
107
+ def revert_to(what, *args, &block) #:yields:
108
+ is_reverting!
109
+
110
+ unless run_callbacks(:before_revert) { |r, o| r == false}
111
+ raise ActiveRecord::RecordNotSaved
112
+ end
113
+
114
+ options = args.extract_options!
115
+
116
+ rev = find_revision(what)
117
+ self.reverting_to, self.reverting_from = rev, self
118
+
119
+ unless rev.run_callbacks(:before_restore) { |r, o| r == false}
120
+ raise ActiveRecord::RecordNotSaved
121
+ end
122
+
123
+ self.class.column_names.each do |col|
124
+ next unless self.class.revisable_should_clone_column? col
125
+ self[col] = rev[col]
126
+ end
127
+
128
+ self.no_revision! if options.delete :without_revision
129
+ self.revisable_new_params = options
130
+
131
+ yield(self) if block_given?
132
+ rev.run_callbacks(:after_restore)
133
+ run_callbacks(:after_revert)
134
+ self
135
+ ensure
136
+ is_reverting!(false)
137
+ clear_revisable_shared_objects!
138
+ end
139
+
140
+ # Same as revert_to except it also saves the record.
141
+ def revert_to!(what, *args)
142
+ revert_to(what, *args) do
143
+ self.no_revision? ? save! : revise!
144
+ end
145
+ end
146
+
147
+ # Equivalent to:
148
+ # revert_to(:without_revision => true)
149
+ def revert_to_without_revision(*args)
150
+ options = args.extract_options!
151
+ options.update({:without_revision => true})
152
+ revert_to(*(args << options))
153
+ end
154
+
155
+ # Equivalent to:
156
+ # revert_to!(:without_revision => true)
157
+ def revert_to_without_revision!(*args)
158
+ options = args.extract_options!
159
+ options.update({:without_revision => true})
160
+ revert_to!(*(args << options))
161
+ end
162
+
163
+ # Globally sets the reverting state of this record.
164
+ def is_reverting!(val=true) #:nodoc:
165
+ set_revisable_state(:reverting, val)
166
+ end
167
+
168
+ # Returns true if the _record_ (not just this instance
169
+ # of the record) is currently being reverted.
170
+ def is_reverting?
171
+ get_revisable_state(:reverting) || false
172
+ end
173
+
174
+ # Sets whether or not to force a revision.
175
+ def force_revision!(val=true) #:nodoc:
176
+ set_revisable_state(:force_revision, val)
177
+ end
178
+
179
+ # Returns true if a revision should be forced.
180
+ def force_revision? #:nodoc:
181
+ get_revisable_state(:force_revision) || false
182
+ end
183
+
184
+ # Sets whether or not a revision should be created.
185
+ def no_revision!(val=true) #:nodoc:
186
+ set_revisable_state(:no_revision, val)
187
+ end
188
+
189
+ # Returns true if no revision should be created.
190
+ def no_revision? #:nodoc:
191
+ get_revisable_state(:no_revision) || false
192
+ end
193
+
194
+ # Force an immediate revision whether or
195
+ # not any columns have been modified.
196
+ #
197
+ # The +args+ catch-all argument is not used. It's primarily
198
+ # there to allow +revise!+ to be used directly as an association
199
+ # callback since association callbacks are passed an argument.
200
+ #
201
+ # ==== Callbacks
202
+ #
203
+ # * +before_revise+ is called before the record is revised.
204
+ # * +after_revise+ is called after the record is revised.
205
+ def revise!(*args)
206
+ return if in_revision?
207
+
208
+ begin
209
+ force_revision!
210
+ in_revision!
211
+ save!
212
+ ensure
213
+ in_revision!(false)
214
+ force_revision!(false)
215
+ end
216
+ end
217
+
218
+ # Groups statements that could trigger several revisions into
219
+ # a single revision. The revision is created once #save is called.
220
+ #
221
+ # ==== Example
222
+ #
223
+ # @project.revision_number # => 1
224
+ # @project.changeset do |project|
225
+ # # each one of the following statements would
226
+ # # normally trigger a revision
227
+ # project.update_attribute(:name, "new name")
228
+ # project.revise!
229
+ # project.revise!
230
+ # end
231
+ # @project.save
232
+ # @project.revision_number # => 2
233
+ #
234
+ # ==== Callbacks
235
+ #
236
+ # * +before_changeset+ is called before a changeset block is called.
237
+ # * +after_changeset+ is called after a changeset block is called.
238
+ def changeset(&block)
239
+ return unless block_given?
240
+
241
+ return yield(self) if in_revision?
242
+
243
+ unless run_callbacks(:before_changeset) { |r, o| r == false}
244
+ raise ActiveRecord::RecordNotSaved
245
+ end
246
+
247
+ begin
248
+ force_revision!
249
+ in_revision!
250
+
251
+ returning(yield(self)) do
252
+ run_callbacks(:after_changeset)
253
+ end
254
+ ensure
255
+ in_revision!(false)
256
+ end
257
+ end
258
+
259
+ # Same as +changeset+ except it also saves the record.
260
+ def changeset!(&block)
261
+ changeset do
262
+ block.call(self)
263
+ save!
264
+ end
265
+ end
266
+
267
+ def without_revisions!
268
+ return if in_revision? || !block_given?
269
+
270
+ begin
271
+ no_revision!
272
+ in_revision!
273
+ yield
274
+ save!
275
+ ensure
276
+ in_revision!(false)
277
+ no_revision!(false)
278
+ end
279
+ end
280
+
281
+ # acts_as_revisable's override for ActiveRecord::Base's #save!
282
+ def save!(*args) #:nodoc:
283
+ self.revisable_new_params ||= args.extract_options!
284
+ self.no_revision! if self.revisable_new_params.delete :without_revision
285
+ super
286
+ end
287
+
288
+ # acts_as_revisable's override for ActiveRecord::Base's #save
289
+ def save(*args) #:nodoc:
290
+ self.revisable_new_params ||= args.extract_options!
291
+ self.no_revision! if self.revisable_new_params.delete :without_revision
292
+ super(args)
293
+ end
294
+
295
+ # Set some defaults for a newly created +Revisable+ instance.
296
+ def before_revisable_create #:nodoc:
297
+ self[:revisable_is_current] = true
298
+ self.revision_number ||= 0
299
+ end
300
+
301
+ # Checks whether or not a +Revisable+ should be revised.
302
+ def should_revise? #:nodoc:
303
+ return false if new_record?
304
+ return true if force_revision?
305
+ return false if no_revision?
306
+ return false unless self.changed?
307
+ !(self.changed.map(&:downcase) & self.class.revisable_watch_columns).blank?
308
+ end
309
+
310
+ # Checks whether or not a revision should be stored.
311
+ # If it should be, it initialized the revision_class
312
+ # and stores it in an accessor for later saving.
313
+ def before_revisable_update #:nodoc:
314
+ return unless should_revise?
315
+ in_revision!
316
+
317
+ unless run_callbacks(:before_revise) { |r, o| r == false}
318
+ in_revision!(false)
319
+ return false
320
+ end
321
+
322
+ self.revisable_revision = self.to_revision
323
+ end
324
+
325
+ # Checks if an initialized revision_class has been stored
326
+ # in the accessor. If it has been, this instance is saved.
327
+ def after_revisable_update #:nodoc:
328
+ if no_revision? # check and see if no_revision! was called in a callback
329
+ self.revisable_revision = nil
330
+ return true
331
+ elsif self.revisable_revision
332
+ if self.class.revision_class.respond_to?(:without_stamps)
333
+ self.class.revision_class.without_stamps do
334
+ self.revisable_revision.save
335
+ end
336
+ else
337
+ self.revisable_revision.save
338
+ end
339
+ revisions.reload
340
+ run_callbacks(:after_revise)
341
+ end
342
+ in_revision!(false)
343
+ force_revision!(false)
344
+ true
345
+ end
346
+
347
+ # Returns true if the _record_ (not just this instance
348
+ # of the record) is currently being revised.
349
+ def in_revision?
350
+ get_revisable_state(:revision)
351
+ end
352
+
353
+ # Manages the internal state of a +Revisable+ controlling
354
+ # whether or not a record is being revised. This works across
355
+ # instances and is keyed on primary_key.
356
+ def in_revision!(val=true) #:nodoc:
357
+ set_revisable_state(:revision, val)
358
+ end
359
+
360
+ # This returns a new +Revision+ instance with all the appropriate
361
+ # values initialized.
362
+ def to_revision #:nodoc:
363
+ rev = self.class.revision_class.new(self.revisable_new_params)
364
+
365
+ rev.revisable_original_id = self.id
366
+
367
+ new_revision_number = revisions.maximum(:revisable_number) + 1 rescue self.revision_number
368
+ rev.revision_number = new_revision_number
369
+ self.revision_number = new_revision_number + 1
370
+
371
+ self.class.column_names.each do |col|
372
+ next unless self.class.revisable_should_clone_column? col
373
+ val = self.send("#{col}_changed?") ? self.send("#{col}_was") : self.send(col)
374
+ rev.send("#{col}=", val)
375
+ end
376
+
377
+ self.revisable_new_params = nil
378
+
379
+ rev
380
+ end
381
+
382
+ # This returns
383
+ def current_revision
384
+ self
385
+ end
386
+
387
+ def for_revision
388
+ key = self.read_attribute(self.class.primary_key)
389
+ self.class.revisable_shared_objects[key] ||= {}
390
+ end
391
+
392
+ def reverting_to
393
+ for_revision[:reverting_to]
394
+ end
395
+
396
+ def reverting_to=(val)
397
+ for_revision[:reverting_to] = val
398
+ end
399
+
400
+ def reverting_from
401
+ for_revision[:reverting_from]
402
+ end
403
+
404
+ def reverting_from=(val)
405
+ for_revision[:reverting_from] = val
406
+ end
407
+
408
+ def clear_revisable_shared_objects!
409
+ key = self.read_attribute(self.class.primary_key)
410
+ self.class.revisable_shared_objects.delete(key)
411
+ end
412
+
413
+ module ClassMethods
414
+ # acts_as_revisable's override for with_scope that allows for
415
+ # including revisions in the scope.
416
+ #
417
+ # ==== Example
418
+ #
419
+ # with_scope(:with_revisions => true) do
420
+ # ...
421
+ # end
422
+ def with_scope(*args, &block) #:nodoc:
423
+ options = (args.grep(Hash).first || {})[:find]
424
+
425
+ if options && options.delete(:with_revisions)
426
+ with_exclusive_scope do
427
+ super(*args, &block)
428
+ end
429
+ else
430
+ super(*args, &block)
431
+ end
432
+ end
433
+
434
+ # acts_as_revisable's override for find that allows for
435
+ # including revisions in the find.
436
+ #
437
+ # ==== Example
438
+ #
439
+ # find(:all, :with_revisions => true)
440
+ def find(*args) #:nodoc:
441
+ options = args.grep(Hash).first
442
+
443
+ if options && options.delete(:with_revisions)
444
+ with_exclusive_scope do
445
+ super(*args)
446
+ end
447
+ else
448
+ super(*args)
449
+ end
450
+ end
451
+
452
+ # Returns the +revision_class_name+ as configured in
453
+ # +acts_as_revisable+.
454
+ def revision_class_name #:nodoc:
455
+ self.revisable_options.revision_class_name || "#{self.class_name}Revision"
456
+ end
457
+
458
+ # Returns the actual +Revision+ class based on the
459
+ # #revision_class_name.
460
+ def revision_class #:nodoc:
461
+ self.revisable_revision_class ||= self.revision_class_name.constantize
462
+ end
463
+
464
+ # Returns the revisable_class which in this case is simply +self+.
465
+ def revisable_class #:nodoc:
466
+ self
467
+ end
468
+
469
+ # Returns the name of the association acts_as_revisable
470
+ # creates.
471
+ def revisions_association_name #:nodoc:
472
+ revision_class_name.pluralize.underscore
473
+ end
474
+
475
+ # Returns an Array of the columns that are watched for changes.
476
+ def revisable_watch_columns #:nodoc:
477
+ return self.revisable_columns unless self.revisable_columns.blank?
478
+ return self.revisable_columns ||= [] if self.revisable_options.except == :all
479
+ return self.revisable_columns ||= [self.revisable_options.only].flatten.map(&:to_s).map(&:downcase) unless self.revisable_options.only.blank?
480
+
481
+ except = [self.revisable_options.except].flatten || []
482
+ except += REVISABLE_SYSTEM_COLUMNS
483
+ except += REVISABLE_UNREVISABLE_COLUMNS
484
+ except.uniq!
485
+
486
+ self.revisable_columns ||= (column_names - except.map(&:to_s)).flatten.map(&:downcase)
487
+ end
488
+ end
489
+ end
490
+ end
491
+ end
@@ -0,0 +1,149 @@
1
+ module WithoutScope
2
+ module ActsAsRevisable
3
+ # This module is mixed into the revision classes.
4
+ #
5
+ # ==== Callbacks
6
+ #
7
+ # * +before_restore+ is called on the revision class before it is
8
+ # restored as the current record.
9
+ # * +after_restore+ is called on the revision class after it is
10
+ # restored as the current record.
11
+ module Revision
12
+ def self.included(base) #:nodoc:
13
+ base.send(:extend, ClassMethods)
14
+
15
+ class << base
16
+ attr_accessor :revisable_revisable_class, :revisable_cloned_associations
17
+ end
18
+
19
+ base.instance_eval do
20
+ set_table_name(revisable_class.table_name)
21
+ default_scope :conditions => {:revisable_is_current => false}
22
+
23
+ define_callbacks :before_restore, :after_restore
24
+ before_create :revision_setup
25
+ after_create :grab_my_branches
26
+
27
+ named_scope :deleted, :conditions => ["? is not null", :revisable_deleted_at]
28
+
29
+ [:current_revision, revisable_association_name.to_sym].each do |a|
30
+ belongs_to a, :class_name => revisable_class_name, :foreign_key => :revisable_original_id
31
+ end
32
+
33
+ [[:ancestors, "<"], [:descendants, ">"]].each do |a|
34
+ # Jumping through hoops here to try and make sure the
35
+ # :finder_sql is cross-database compatible. :finder_sql
36
+ # in a plugin is evil but, I see no other option.
37
+ has_many a.first, :class_name => revision_class_name, :finder_sql => "select * from #{quoted_table_name} where #{quote_bound_value(:revisable_original_id)} = \#{revisable_original_id} and #{quote_bound_value(:revisable_number)} #{a.last} \#{revisable_number} and #{quote_bound_value(:revisable_is_current)} = #{quote_value(false)} order by #{quote_bound_value(:revisable_number)} #{(a.last.eql?("<") ? "DESC" : "ASC")}"
38
+ end
39
+ end
40
+ end
41
+
42
+ def find_revision(*args)
43
+ current_revision.find_revision(*args)
44
+ end
45
+
46
+ # Return the revision prior to this one.
47
+ def previous_revision
48
+ self.class.find(:first, :conditions => {:revisable_original_id => revisable_original_id, :revisable_number => revisable_number - 1})
49
+ end
50
+
51
+ # Return the revision after this one.
52
+ def next_revision
53
+ self.class.find(:first, :conditions => {:revisable_original_id => revisable_original_id, :revisable_number => revisable_number + 1})
54
+ end
55
+
56
+ # Setter for revisable_name just to make external API more pleasant.
57
+ def revision_name=(val) #:nodoc:
58
+ self[:revisable_name] = val
59
+ end
60
+
61
+ # Accessor for revisable_name just to make external API more pleasant.
62
+ def revision_name #:nodoc:
63
+ self[:revisable_name]
64
+ end
65
+
66
+ # Sets some initial values for a new revision.
67
+ def revision_setup #:nodoc:
68
+ now = Time.zone.now
69
+ prev = current_revision.revisions.first
70
+ prev.update_attribute(:revisable_revised_at, now) if prev
71
+ self[:revisable_current_at] = now + 1.second
72
+ self[:revisable_is_current] = false
73
+ self[:revisable_branched_from_id] = current_revision[:revisable_branched_from_id]
74
+ self[:revisable_type] = current_revision[:type]
75
+ self[:revisable_number] = (self.class.maximum(:revisable_number, :conditions => {:revisable_original_id => self[:revisable_original_id]}) || 0) + 1
76
+ end
77
+
78
+ def grab_my_branches
79
+ self.class.revisable_class.update_all(["revisable_branched_from_id = ?", self[:id]], ["revisable_branched_from_id = ?", self[:revisable_original_id]])
80
+ end
81
+
82
+ def from_revisable
83
+ current_revision.for_revision
84
+ end
85
+
86
+ def reverting_from
87
+ from_revisable[:reverting_from]
88
+ end
89
+
90
+ def reverting_from=(val)
91
+ from_revisable[:reverting_from] = val
92
+ end
93
+
94
+ def reverting_to
95
+ from_revisable[:reverting_to]
96
+ end
97
+
98
+ def reverting_to=(val)
99
+ from_revisable[:reverting_to] = val
100
+ end
101
+
102
+ module ClassMethods
103
+ # Returns the +revisable_class_name+ as configured in
104
+ # +acts_as_revisable+.
105
+ def revisable_class_name #:nodoc:
106
+ self.revisable_options.revisable_class_name || self.class_name.gsub(/Revision/, '')
107
+ end
108
+
109
+ # Returns the actual +Revisable+ class based on the
110
+ # #revisable_class_name.
111
+ def revisable_class #:nodoc:
112
+ self.revisable_revisable_class ||= self.revisable_class_name.constantize
113
+ end
114
+
115
+ # Returns the revision_class which in this case is simply +self+.
116
+ def revision_class #:nodoc:
117
+ self
118
+ end
119
+
120
+ def revision_class_name #:nodoc:
121
+ self.name
122
+ end
123
+
124
+ # Returns the name of the association acts_as_revision
125
+ # creates.
126
+ def revisable_association_name #:nodoc:
127
+ revisable_class_name.underscore
128
+ end
129
+
130
+ # Returns an array of the associations that should be cloned.
131
+ def revision_cloned_associations #:nodoc:
132
+ clone_associations = self.revisable_options.clone_associations
133
+
134
+ self.revisable_cloned_associations ||= if clone_associations.blank?
135
+ []
136
+ elsif clone_associations.eql? :all
137
+ revisable_class.reflect_on_all_associations.map(&:name)
138
+ elsif clone_associations.is_a? [].class
139
+ clone_associations
140
+ elsif clone_associations[:only]
141
+ [clone_associations[:only]].flatten
142
+ elsif clone_associations[:except]
143
+ revisable_class.reflect_on_all_associations.map(&:name) - [clone_associations[:except]].flatten
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,52 @@
1
+ require 'acts_as_revisable/options'
2
+ require 'acts_as_revisable/quoted_columns'
3
+ require 'acts_as_revisable/acts/common'
4
+ require 'acts_as_revisable/acts/revision'
5
+ require 'acts_as_revisable/acts/revisable'
6
+ require 'acts_as_revisable/acts/deletable'
7
+
8
+ module WithoutScope
9
+ # define the columns used internall by AAR
10
+ REVISABLE_SYSTEM_COLUMNS = %w(revisable_original_id revisable_branched_from_id revisable_number revisable_name revisable_type revisable_current_at revisable_revised_at revisable_deleted_at revisable_is_current)
11
+
12
+ # define the ActiveRecord magic columns that should not be monitored
13
+ REVISABLE_UNREVISABLE_COLUMNS = %w(id type created_at updated_at)
14
+
15
+ module ActsAsRevisable
16
+ def self.included(base)
17
+ base.send(:extend, ClassMethods)
18
+ end
19
+
20
+ module ClassMethods
21
+
22
+ # This +acts_as+ extension provides for making a model the
23
+ # revisable model in an acts_as_revisable pair.
24
+ def acts_as_revisable(*args, &block)
25
+ revisable_shared_setup(args, block)
26
+ self.send(:include, Revisable)
27
+ self.send(:include, Deletable) if self.revisable_options.on_delete == :revise
28
+ end
29
+
30
+ # This +acts_as+ extension provides for making a model the
31
+ # revision model in an acts_as_revisable pair.
32
+ def acts_as_revision(*args, &block)
33
+ revisable_shared_setup(args, block)
34
+ self.send(:include, Revision)
35
+ end
36
+
37
+ private
38
+ # Performs the setup needed for both kinds of acts_as_revisable
39
+ # models.
40
+ def revisable_shared_setup(args, block)
41
+ class << self
42
+ attr_accessor :revisable_options
43
+ end
44
+ options = args.extract_options!
45
+ self.revisable_options = Options.new(options, &block)
46
+
47
+ self.send(:include, Common)
48
+ self.send(:include, WithoutScope::QuotedColumnConditions)
49
+ end
50
+ end
51
+ end
52
+ end