kentouzu 0.1.2 → 0.2.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b39f53d72a27a2ab22bc2d2ac95627e62ca349c5
4
+ data.tar.gz: 075eee3f632a1a30b30b7ba06f4d36e9ba4da7f9
5
+ SHA512:
6
+ metadata.gz: b1c4405b4bf4d4997fd1ec9195ea3ef9bc7df25e30e3ef7f7501cfa92646a5d107a8dda00a12c92bf789c648c6d45a1076d8b0e67dddb7af1b2015cc2ca07336
7
+ data.tar.gz: fce154503e796c800a21b5186fac0deab7d89b2f8a357696d745258314bbe2493b95d57126b641f417b79ff12d5c8db82d125efec580bdb10d4b4c71b0a25664
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 1.9.3-p392
1
+ 2.1.3
data/CHANGELOG.md CHANGED
@@ -1,6 +1,19 @@
1
+ ## v0.2.0
2
+
3
+ * Breaking changes to the way objects are serialized and deserialized.
4
+ * `has_many` associations are now serialized along with the object.
5
+ * Deprecated `drafts_on` and `drafts_off` in favor of `drafts_on!` and `drafts_off!`.
6
+ * Added `Kentouzu.enabled_for_model` and `Kentouzu.enabled_for_model?`.
7
+ * Added `Kentouzu.active_record_protected_attributes?` to enable handling of attr_accessible.
8
+ * Attempt to load `protected_attributes` gem if it's available.
9
+ * Added `Draft.with_source_keys`.
10
+ * Deprecated `Draft#approve` and `Draft#reject`.
11
+ * Added override for `save!`.
12
+
1
13
  ## v0.1.2
2
14
 
3
15
  * Added callbacks for `before_draft_save`, `after_draft_save`, and `around_draft_save`.
16
+ * Fixed a bug where invalid attributes were merged from controller options when saving a draft.
4
17
 
5
18
  ## v0.1.1
6
19
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kentouzu (0.1.2)
4
+ kentouzu (0.2.0)
5
5
  activerecord (>= 3.0)
6
6
  railties (>= 3.0)
7
7
 
data/kentouzu.gemspec CHANGED
@@ -1,17 +1,14 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path('../lib', __FILE__)
1
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
3
2
  require 'kentouzu/version'
4
3
 
5
4
  Gem::Specification.new do |s|
6
5
  s.name = 'kentouzu'
7
6
  s.version = Kentouzu::VERSION
8
- s.authors = ['Sean Eshbaugh']
9
- s.email = ['seaneshbaugh@gmail.com']
10
- s.homepage = 'https://github.com/seaneshbaugh/kentouzu'
11
7
  s.summary = 'Add drafts to ActiveRecord models.'
12
- s.description = 'Add drafts to ActiveRecord models.'
13
-
14
- s.rubyforge_project = 'kentouzu'
8
+ s.description = s.summary
9
+ s.homepage = 'https://github.com/seaneshbaugh/kentouzu'
10
+ s.authors = ['Sean Eshbaugh']
11
+ s.email = 'seaneshbaugh@gmail.com'
15
12
 
16
13
  s.files = `git ls-files`.split("\n")
17
14
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -9,7 +9,6 @@ module Kentouzu
9
9
  source_root File.expand_path('../templates', __FILE__)
10
10
 
11
11
  desc 'Generates (but does not run) a migration to add a drafts table.'
12
-
13
12
  def create_migration_file
14
13
  migration_template 'create_drafts.rb', 'db/migrate/create_drafts.rb'
15
14
  end
@@ -17,21 +17,21 @@ module Kentouzu
17
17
  end
18
18
 
19
19
  def drafts_enabled_for_controller
20
- true
20
+ Kentouzu.enabled?
21
21
  end
22
22
 
23
23
  private
24
24
 
25
25
  def set_drafts_source
26
- ::Kentouzu.source = user_for_drafts
26
+ Kentouzu.source = user_for_drafts
27
27
  end
28
28
 
29
29
  def set_drafts_controller_info
30
- ::Kentouzu.controller_info = info_for_drafts
30
+ Kentouzu.controller_info = info_for_drafts
31
31
  end
32
32
 
33
33
  def set_drafts_enabled_for_controller
34
- ::Kentouzu.enabled_for_controller = drafts_enabled_for_controller
34
+ Kentouzu.enabled_for_controller = drafts_enabled_for_controller
35
35
  end
36
36
  end
37
37
  end
@@ -1,4 +1,8 @@
1
1
  class Draft < ActiveRecord::Base
2
+ if Kentouzu.active_record_protected_attributes?
3
+ attr_accessible :item_type, :item_id, :event, :source_type, :source_id, :object
4
+ end
5
+
2
6
  belongs_to :item, :polymorphic => true
3
7
 
4
8
  belongs_to :source, :polymorphic => true
@@ -6,7 +10,11 @@ class Draft < ActiveRecord::Base
6
10
  validates_presence_of :event
7
11
 
8
12
  def self.with_item_keys(item_type, item_id)
9
- scoped :conditions => { :item_type => item_type, :item_id => item_id }
13
+ where :item_type => item_type, :item_id => item_id
14
+ end
15
+
16
+ def self.with_source_keys(source_type, source_id)
17
+ where :source_type => source_type, :source_id => source_id
10
18
  end
11
19
 
12
20
  def self.creates
@@ -17,57 +25,97 @@ class Draft < ActiveRecord::Base
17
25
  where :event => 'update'
18
26
  end
19
27
 
20
- scope :subsequent, lambda { |draft| where(["#{self.primary_key} > ?", draft]).order("#{self.primary_key} ASC") }
28
+ def subsequent(obj, timestamp_arg = false)
29
+ if timestamp_arg != true && self.primary_key_is_int?
30
+ where(arel_table[primary_key].gt(obj.id)).order(arel_table[primary_key].asc)
31
+ else
32
+ obj = obj.send(Kentouzu.timestamp_field) if obj.is_a?(self)
21
33
 
22
- scope :preceding, lambda { |draft| where(["#{self.primary_key} < ?}", draft]).order("#{self.primary_key} DESC") }
34
+ where(arel_table[Kentouzu.timestamp_field].gt(obj)).order(self.timestamp_sort_order)
35
+ end
36
+ end
23
37
 
24
- scope :following, lambda { |timestamp| where(["#{Kentouzu.timestamp_field} > ?"], timestamp).order("#{Kentouzu.timestamp_field} ASC, #{self.primary_key} ASC") }
38
+ def preceding(obj, timestamp_arg = false)
39
+ if timestamp_arg != true && self.primary_key_is_int?
40
+ where(arel_table[primary_key].lt(obj.id)).order(arel_table[primary_key].asc)
41
+ else
42
+ obj = obj.send(Kentouzu.timestamp_field) if obj.is_a?(self)
25
43
 
26
- scope :between, lambda { |start_time, end_time| where(["#{Kentouzu.timestamp_field} > ? AND #{Kentouzu.timestamp_field} < ?", start_time, end_time]).order("#{Kentouzu.timestamp_field} ASC, #{self.primary_key} ASC") }
44
+ where(arel_table[Kentouzu.timestamp_field].lt(obj)).order(self.timestamp_sort_order)
45
+ end
46
+ end
47
+
48
+ def following(timestamp)
49
+ where(arel_table[Kentouzu.timestamp_field].gt(timestamp)).order(self.timestamp_sort_order)
50
+ end
51
+
52
+ def between(start_time, end_time)
53
+ where(arel_tabl[Kentouzu.timestamp_field].gt(start_time).and(arel_table[Kentouzu.timestamp_field].lt(end_time))).order(self.timestamp_sort_order)
54
+ end
55
+
56
+ def timestamp_sort_order(direction = 'asc')
57
+ [arel_table[Kentouzu.timestamp_field].send(direction.downcase)].tap do |array|
58
+ array << arel_table[primary_key].send(direction.downcase) if self.primary_key_is_int?
59
+ end
60
+ end
27
61
 
62
+ # Restore the item from this draft.
63
+ #
64
+ # Options:
65
+ # :has_one Set to `false` to disable has_one reification.
66
+ # Set to a float to change the lookback time.
28
67
  def reify(options = {})
68
+ return nil if object.nil?
69
+
29
70
  without_identity_map do
30
71
  options[:has_one] = 3 if options[:has_one] == true
72
+
31
73
  options.reverse_merge! :has_one => false
32
74
 
33
- unless object.nil?
34
- #This appears to be necessary if for some reason the draft's model hasn't been loaded (such as when done in the console).
35
- require self.item_type.underscore
75
+ #This appears to be necessary if for some reason the draft's model hasn't been loaded (such as when done in the console).
76
+ require self.item_type.underscore
36
77
 
37
- loaded_object = YAML::load object
78
+ loaded_object = YAML::load object
38
79
 
39
- if item
40
- model = item
41
- else
42
- inheritance_column_name = item_type.constantize.inheritance_column
80
+ if item
81
+ model = item
82
+ else
83
+ inheritance_column_name = item_type.constantize.inheritance_column
43
84
 
44
- class_name = loaded_object.respond_to?(inheritance_column_name.to_sym) && loaded_object.send(inheritance_column_name.to_sym).present? ? loaded_object.send(inheritance_column_name.to_sym) : item_type
85
+ class_name = loaded_object.respond_to?(inheritance_column_name.to_sym) && loaded_object.send(inheritance_column_name.to_sym).present? ? loaded_object.send(inheritance_column_name.to_sym) : item_type
45
86
 
46
- klass = class_name.constantize
87
+ klass = class_name.constantize
47
88
 
48
- model = klass.new
49
- end
89
+ model = klass.new
90
+ end
50
91
 
51
- loaded_object.attributes.each do |key, value|
52
- if model.respond_to?("#{key}=")
53
- model.send :write_attribute, key.to_sym, value
92
+ has_many_associations = model.class.reflect_on_all_associations(:has_many).reject { |association| association.name == :drafts }.map { |association| association.name }
93
+
94
+ loaded_object.each do |key, value|
95
+ if model.respond_to?("#{key}=")
96
+ if has_many_associations.include?(key.to_sym)
97
+ model.send "#{key}=".to_sym, value.map { |v| model.send(key.to_sym).proxy_association.klass.new(v) }
54
98
  else
55
- logger.warn "Attribute #{key} does not exist on #{item_type} (Draft ID: #{id})."
99
+ model.send :write_attribute, key.to_sym, value
56
100
  end
101
+ else
102
+ logger.warn "Attribute #{key} does not exist on #{item_type} (Draft ID: #{id})."
57
103
  end
104
+ end
58
105
 
59
- model.send "#{model.class.draft_association_name}=", self
60
-
61
- unless options[:has_one] == false
62
- reify_has_ones model, options[:has_one]
63
- end
106
+ model.send "#{model.class.draft_association_name}=", self
64
107
 
65
- model
108
+ unless options[:has_one] == false
109
+ reify_has_ones model, options[:has_one]
66
110
  end
111
+
112
+ model
67
113
  end
68
114
  end
69
115
 
70
116
  def approve
117
+ warn 'DEPRECATED: `approve` should be handled by your application, not Kentouzu. Will be removed in Kentouzu 0.3.0.'
118
+
71
119
  model = self.reify
72
120
 
73
121
  if model
@@ -88,9 +136,17 @@ class Draft < ActiveRecord::Base
88
136
  end
89
137
 
90
138
  def reject
139
+ warn 'DEPRECATED: `reject` should be handled by your application, not Kentouzu. Will be removed in Kentouzu 0.3.0.'
140
+
91
141
  self.destroy
92
142
  end
93
143
 
144
+ def primary_key_is_int?
145
+ @primary_key_is_int ||= columns_hash[primary_key].type == :integer
146
+ rescue
147
+ true
148
+ end
149
+
94
150
  private
95
151
 
96
152
  def without_identity_map(&block)
@@ -5,41 +5,59 @@ module Kentouzu
5
5
  end
6
6
 
7
7
  module ClassMethods
8
+ # By calling this in your model all subsequent calls to save will instead create a draft.
9
+ # Drafts are available through the `drafts` association.
10
+ #
11
+ # Options:
12
+ # :class_name The name of a custom Draft class. Should inherit from `Kentouzu::Draft`.
13
+ # Default is `'Draft'`.
14
+ # :draft The name for the method which returns the draft the instance was reified from.
15
+ # Default is `:draft`.
16
+ # :drafts The name to use for the drafts association.
17
+ # Default is `:drafts`.
18
+ # :if Proc that allows you to specify the conditions under which drafts are made.
19
+ # :ignore An Array of attributes that will be ignored when creating a `Draft`.
20
+ # Can also accept a Has as an argument where each key is the attribute to ignore (either
21
+ # a `String` or `Symbol`) and each value is a `Proc` whose return value, `true` or
22
+ # `false`, determines if it is ignored.
23
+ # :meta A hash of extra data to store. Each key in the hash (either a `String` or `Symbol`)
24
+ # must be a column on the `drafts` table, otherwise it is ignored. You must add these
25
+ # columns yourself. The values are either objects or procs (which are called with `self`,
26
+ # i.e. the model the draft is being made from).
27
+ # :on An array of events that will cause a draft to be created.
28
+ # Defaults to `[:create, :update, :destroy]`.
29
+ # :only Inverse of the `:ignore` option. Only the attributes supplied will be passed along to
30
+ # the draft.
31
+ # :unless Proc that allows you to specify the conditions under which drafts are not made.
8
32
  def has_drafts(options = {})
33
+ # Only include the instance methods when this `has_drafts` is called to avoid cluttering up models.
9
34
  send :include, InstanceMethods
10
35
 
36
+ # Add `before_draft_save`, `after_draft_save`, and `around_draft_save` callbacks.
11
37
  send :define_model_callbacks, :draft_save
12
38
 
13
39
  class_attribute :draft_association_name
14
40
  self.draft_association_name = options[:draft] || :draft
15
41
 
42
+ # The draft this instance was reified from.
16
43
  attr_accessor self.draft_association_name
17
44
 
18
45
  class_attribute :draft_class_name
19
46
  self.draft_class_name = options[:class_name] || 'Draft'
20
47
 
21
- class_attribute :ignore
22
- self.ignore = ([options[:ignore]].flatten.compact || []).map &:to_s
48
+ class_attribute :draft_options
49
+ self.draft_options = options.dup
23
50
 
24
- class_attribute :if_condition
25
- self.if_condition = options[:if]
26
-
27
- class_attribute :unless_condition
28
- self.unless_condition = options[:unless]
29
-
30
- class_attribute :skip
31
- self.skip = ([options[:skip]].flatten.compact || []).map &:to_s
32
-
33
- class_attribute :only
34
- self.only = ([options[:only]].flatten.compact || []).map &:to_s
51
+ [:ignore, :only].each do |option|
52
+ draft_options[option] = [draft_options[option]].flatten.compact.map { |attr| attr.is_a?(Hash) ? attr.stringify_keys : attr.to_s }
53
+ end
35
54
 
36
- class_attribute :drafts_enabled_for_model
37
- self.drafts_enabled_for_model = true
55
+ draft_options[:meta] ||= {}
38
56
 
39
57
  class_attribute :drafts_association_name
40
58
  self.drafts_association_name = options[:drafts] || :drafts
41
59
 
42
- if ActiveRecord::VERSION::STRING.to_f >= 4.0 # `has_many` syntax for specifying order uses a lambda in Rails 4
60
+ if ActiveRecord::VERSION::MAJOR >= 4 # `has_many` syntax for specifying order uses a lambda in Rails 4
43
61
  has_many self.drafts_association_name,
44
62
  lambda { order("#{Kentouzu.timestamp_field} ASC, #{self.primary_key} ASC") },
45
63
  :class_name => draft_class_name,
@@ -49,7 +67,7 @@ module Kentouzu
49
67
  has_many self.drafts_association_name,
50
68
  :class_name => draft_class_name,
51
69
  :as => :item,
52
- :order => "#{Kentouzu.timestamp_field} ASC, #{self.draft_class_name.constantize.primary_key} ASC",
70
+ :order => "#{Kentouzu.timestamp_field} ASC, #{self.draft_class.primary_key} ASC",
53
71
  :dependent => :destroy
54
72
  end
55
73
 
@@ -58,7 +76,7 @@ module Kentouzu
58
76
  end
59
77
 
60
78
  define_singleton_method "all_with_reified_#{drafts_association_name.to_s}".to_sym do |order_by = Kentouzu.timestamp_field, &block|
61
- existing_drafts = Draft.where("`drafts`.`item_type` = \"#{self.base_class.name}\" AND `drafts`.`item_id` IS NOT NULL").group_by { |draft| draft.item_id }.map { |k, v| v.sort_by { |draft| draft.created_at }.last }
79
+ existing_drafts = Draft.where("`drafts`.`item_type` = \"#{self.base_class.name}\" AND `drafts`.`item_id` IS NOT NULL").group_by { |draft| draft.item_id }.map { |_, v| v.sort_by { |draft| draft.created_at }.last }
62
80
 
63
81
  new_drafts = Draft.where("`drafts`.`item_type` = \"#{self.base_class.name}\" AND `drafts`.`item_id` IS NULL")
64
82
 
@@ -83,42 +101,59 @@ module Kentouzu
83
101
  all_objects
84
102
  end
85
103
 
104
+ def drafts_off!
105
+ Kentouzu.enabled_for_model(self, false)
106
+ end
107
+
86
108
  def drafts_off
87
- self.drafts_enabled_for_model = false
109
+ warn 'DEPRECATED: use `drafts_off!` instead of `drafts_off`. Will be removed in Kentouzu 0.3.0.'
110
+
111
+ self.drafts_off!
112
+ end
113
+
114
+ def drafts_on!
115
+ Kentouzu.enabled_for_model(self, true)
88
116
  end
89
117
 
90
118
  def drafts_on
91
- self.drafts_enabled_for_model = true
119
+ warn 'DEPRECATED: use `drafts_on!` instead of `drafts_on`. Will be removed in Kentouzu 0.3.0.'
120
+
121
+ self.drafts_on!
122
+ end
123
+
124
+ def drafts_enabled_for_model?
125
+ Kentouzu.enabled_for_model?(self)
126
+ end
127
+
128
+ def draft_class
129
+ @draft_class ||= draft_class_name.constantize
92
130
  end
93
131
  end
94
132
  end
95
133
 
96
134
  module InstanceMethods
135
+ # Override the default `save` method and replace it with one that checks to see if a draft should be saved.
136
+ # If a draft should be saved the original object instance is left untouched and a new draft is created.
97
137
  def self.included(base)
98
138
  default_save = base.instance_method(:save)
99
139
 
100
140
  base.send :define_method, :save do
101
141
  if switched_on? && save_draft?
102
- data = {
103
- :item_type => self.class.base_class.to_s,
104
- :item_id => self.id,
105
- :event => self.persisted? ? 'update' : 'create',
106
- :source_type => Kentouzu.source.present? ? Kentouzu.source.class.to_s : nil,
107
- :source_id => Kentouzu.source.present? ? Kentouzu.source.id : nil,
108
- :object => self.to_yaml
109
- }
110
-
111
- data.merge!(Kentouzu.controller_info.slice(:item_type, :item_id, :event, :source_type, :source_id) || {})
112
-
113
- draft = Draft.new(data)
114
-
115
- run_callbacks :draft_save do
116
- draft.save
117
- end
142
+ save_draft
118
143
  else
119
144
  default_save.bind(self).call
120
145
  end
121
146
  end
147
+
148
+ default_save_with_bang = base.instance_method(:save!)
149
+
150
+ base.send :define_method, :save! do
151
+ if switched_on? && save_draft?
152
+ save_draft
153
+ else
154
+ default_save_with_bang.bind(self).call
155
+ end
156
+ end
122
157
  end
123
158
 
124
159
  def live?
@@ -151,6 +186,10 @@ module Kentouzu
151
186
  self.class.drafts_on if drafts_were_enabled
152
187
  end
153
188
 
189
+ def drafts_enabled_for_model?
190
+ self.class.drafts_enabled_for_model?
191
+ end
192
+
154
193
  private
155
194
 
156
195
  def draft_class
@@ -161,12 +200,61 @@ module Kentouzu
161
200
  send self.class.draft_association_name
162
201
  end
163
202
 
203
+ def merge_metadata(data)
204
+ draft_options[:meta].each do |key, value|
205
+ if value.respond_to?(:call)
206
+ data[key] = value.call(self)
207
+ elsif value.is_a?(Symbol) && respond_to?(value)
208
+ data[key] = send(value)
209
+ else
210
+ data[key] = value
211
+ end
212
+ end
213
+
214
+ (Kentouzu.controller_info || {}).each do |key, value|
215
+ if value.respond_to?(:call)
216
+ data[key] = value.call(self)
217
+ elsif value.is_a?(Symbol) && respond_to?(value)
218
+ data[key] = send(value)
219
+ end
220
+ end
221
+
222
+ data
223
+ end
224
+
225
+ def save_draft
226
+ data = {
227
+ :item_type => self.class.base_class.to_s,
228
+ :item_id => self.id,
229
+ :event => draft_event.to_s,
230
+ :source_type => Kentouzu.source.present? ? Kentouzu.source.class.to_s : nil,
231
+ :source_id => Kentouzu.source.present? ? Kentouzu.source.id : nil,
232
+ :object => self.as_json(include: self.class.reflect_on_all_associations(:has_many).map { |a| a.name }.reject { |a| a == :drafts }).to_yaml
233
+ }
234
+
235
+ draft = Draft.new(merge_metadata(data))
236
+
237
+ run_callbacks :draft_save do
238
+ draft.save
239
+ end
240
+ end
241
+
242
+ def draft_event
243
+ @draft_event ||= self.persisted? ? :update : :create
244
+ end
245
+
164
246
  def switched_on?
165
- Kentouzu.enabled? && Kentouzu.enabled_for_controller? && self.class.drafts_enabled_for_model
247
+ Kentouzu.enabled? && Kentouzu.enabled_for_controller? && self.drafts_enabled_for_model?
166
248
  end
167
249
 
168
250
  def save_draft?
169
- (if_condition.blank? || if_condition.call(self)) && !unless_condition.try(:call, self)
251
+ on_events = Array(self.draft_options[:on])
252
+
253
+ if_condition = self.draft_options[:if]
254
+
255
+ unless_condition = self.draft_options[:unless]
256
+
257
+ (on_events.empty? || on_events.include?(draft_event)) && (if_condition.blank? || if_condition.call(self)) && !unless_condition.try(:call, self)
170
258
  end
171
259
  end
172
260
  end
@@ -1,3 +1,3 @@
1
1
  module Kentouzu
2
- VERSION = '0.1.2'
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/kentouzu.rb CHANGED
@@ -4,64 +4,110 @@ require 'yaml'
4
4
  require 'kentouzu/config'
5
5
  require 'kentouzu/controller'
6
6
  require 'kentouzu/has_drafts'
7
- require 'kentouzu/draft'
8
7
 
9
8
  module Kentouzu
9
+ # Switches Kentouzu on or off globally.
10
10
  def self.enabled=(value)
11
11
  Kentouzu.config.enabled = value
12
12
  end
13
13
 
14
+ # Returns `true` if Kentouzu is enabled globally, `false` otherwise.
15
+ # Kentouzu is enabled by default.
14
16
  def self.enabled?
15
17
  !!Kentouzu.config.enabled
16
18
  end
17
19
 
20
+ # Switches Kentouzu on or off for the current request.
18
21
  def self.enabled_for_controller=(value)
19
22
  drafts_store[:request_enabled_for_controller] = value
20
23
  end
21
24
 
25
+ # Returns `true` if Kentouzu is enabled for the current request, `false` otherwise.
22
26
  def self.enabled_for_controller?
23
27
  !!drafts_store[:request_enabled_for_controller]
24
28
  end
25
29
 
30
+ # Switches Kentouzu on or off for the model for the current request.
31
+ def self.enabled_for_model(model, value)
32
+ drafts_store[:"enabled_for_#{model}"] = value
33
+ end
34
+
35
+ # Returns `true` if Kentouzu is enabled for the model for the current request, `false` otherwise.
36
+ def self.enabled_for_model?(model)
37
+ !!drafts_store.fetch(:"enabled_for_#{model}", true)
38
+ end
39
+
40
+ # Set the field which records when a draft was created.
26
41
  def self.timestamp_field=(field_name)
27
42
  Kentouzu.config.timestamp_field = field_name
28
43
  end
29
44
 
45
+ # Returns the field which records when a draft was created.
30
46
  def self.timestamp_field
31
47
  Kentouzu.config.timestamp_field
32
48
  end
33
49
 
50
+ # Sets who is responsible for creating the draft.
51
+ # Inside of a controller this will automatically be set to `current_user`.
52
+ # Outside of a controller it will need to be set manually.
34
53
  def self.source=(value)
35
54
  drafts_store[:source] = value
36
55
  end
37
56
 
57
+ # Returns who is responsible for creating the draft.
38
58
  def self.source
39
59
  drafts_store[:source]
40
60
  end
41
61
 
62
+ # Sets any information from the controller that you want Kentouzu to store.
42
63
  def self.controller_info=(value)
43
64
  drafts_store[:controller_info] = value
44
65
  end
45
66
 
67
+ # Returns any information from the controller that you want Kentouzu to store.
46
68
  def self.controller_info
47
69
  drafts_store[:controller_info]
48
70
  end
49
71
 
72
+ # Returns `true` if ActiveRecord requires mass assigned attributes to be whitelisted via `attr_accessible`, `false` otherwise.
73
+ def self.active_record_protected_attributes?
74
+ @active_record_protected_attributes ||= ActiveRecord::VERSION::MAJOR < 4 || !!defined?(ProtectedAttributes)
75
+ end
76
+
50
77
  private
51
78
 
79
+ # Thread-safe hash to hold Kentouzu's data.
80
+ # Initialized to enable Kentouzu for all controllers.
52
81
  def self.drafts_store
53
82
  Thread.current[:draft] ||= { :request_enabled_for_controller => true }
54
83
  end
55
84
 
85
+ # Returns Kentouzu's configuration object.
56
86
  def self.config
57
87
  @@config ||= Kentouzu::Config.instance
58
88
  end
59
89
  end
60
90
 
91
+ require 'kentouzu/draft'
92
+
93
+ # Ensure `protected_attributes` gem gets required if it is available before the `Draft` class is loaded.
94
+ unless Kentouzu.active_record_protected_attributes?
95
+ Kentouzu.send(:remove_instance_variable, :@active_record_protected_attributes)
96
+
97
+ begin
98
+ require 'protected_attributes'
99
+ rescue LoadError
100
+ # Don't blow up if the `protected_attributes` gem is not available.
101
+ nil
102
+ end
103
+ end
104
+
105
+ # Include `Kentouzu::Model` into `ActiveRecord::Base`
61
106
  ActiveSupport.on_load(:active_record) do
62
107
  include Kentouzu::Model
63
108
  end
64
109
 
110
+ # Include `Kentouzu::Controller` into `ActionController::Base`
65
111
  ActiveSupport.on_load(:action_controller) do
66
112
  include Kentouzu::Controller
67
113
  end
metadata CHANGED
@@ -1,187 +1,165 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kentouzu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
5
- prerelease:
4
+ version: 0.2.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Sean Eshbaugh
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-10-17 00:00:00.000000000 Z
11
+ date: 2014-10-21 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: railties
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
19
  version: '3.0'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - ">="
28
25
  - !ruby/object:Gem::Version
29
26
  version: '3.0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: activerecord
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - ">="
36
32
  - !ruby/object:Gem::Version
37
33
  version: '3.0'
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - ">="
44
39
  - !ruby/object:Gem::Version
45
40
  version: '3.0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: capybara
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - ">="
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - ">="
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: database_cleaner
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ! '>='
59
+ - - ">="
68
60
  - !ruby/object:Gem::Version
69
61
  version: '0'
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ! '>='
66
+ - - ">="
76
67
  - !ruby/object:Gem::Version
77
68
  version: '0'
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: jquery-rails
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ! '>='
73
+ - - ">="
84
74
  - !ruby/object:Gem::Version
85
75
  version: '0'
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ! '>='
80
+ - - ">="
92
81
  - !ruby/object:Gem::Version
93
82
  version: '0'
94
83
  - !ruby/object:Gem::Dependency
95
84
  name: rake
96
85
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
86
  requirements:
99
- - - ! '>='
87
+ - - ">="
100
88
  - !ruby/object:Gem::Version
101
89
  version: '0'
102
90
  type: :development
103
91
  prerelease: false
104
92
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
93
  requirements:
107
- - - ! '>='
94
+ - - ">="
108
95
  - !ruby/object:Gem::Version
109
96
  version: '0'
110
97
  - !ruby/object:Gem::Dependency
111
98
  name: rails
112
99
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
100
  requirements:
115
- - - ! '>='
101
+ - - ">="
116
102
  - !ruby/object:Gem::Version
117
103
  version: '3.2'
118
104
  type: :development
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
107
  requirements:
123
- - - ! '>='
108
+ - - ">="
124
109
  - !ruby/object:Gem::Version
125
110
  version: '3.2'
126
111
  - !ruby/object:Gem::Dependency
127
112
  name: rspec-rails
128
113
  requirement: !ruby/object:Gem::Requirement
129
- none: false
130
114
  requirements:
131
- - - ! '>='
115
+ - - ">="
132
116
  - !ruby/object:Gem::Version
133
117
  version: '0'
134
118
  type: :development
135
119
  prerelease: false
136
120
  version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
121
  requirements:
139
- - - ! '>='
122
+ - - ">="
140
123
  - !ruby/object:Gem::Version
141
124
  version: '0'
142
125
  - !ruby/object:Gem::Dependency
143
126
  name: shoulda-matchers
144
127
  requirement: !ruby/object:Gem::Requirement
145
- none: false
146
128
  requirements:
147
- - - ! '>='
129
+ - - ">="
148
130
  - !ruby/object:Gem::Version
149
131
  version: '0'
150
132
  type: :development
151
133
  prerelease: false
152
134
  version_requirements: !ruby/object:Gem::Requirement
153
- none: false
154
135
  requirements:
155
- - - ! '>='
136
+ - - ">="
156
137
  - !ruby/object:Gem::Version
157
138
  version: '0'
158
139
  - !ruby/object:Gem::Dependency
159
140
  name: sqlite3
160
141
  requirement: !ruby/object:Gem::Requirement
161
- none: false
162
142
  requirements:
163
- - - ! '>='
143
+ - - ">="
164
144
  - !ruby/object:Gem::Version
165
145
  version: '0'
166
146
  type: :development
167
147
  prerelease: false
168
148
  version_requirements: !ruby/object:Gem::Requirement
169
- none: false
170
149
  requirements:
171
- - - ! '>='
150
+ - - ">="
172
151
  - !ruby/object:Gem::Version
173
152
  version: '0'
174
153
  description: Add drafts to ActiveRecord models.
175
- email:
176
- - seaneshbaugh@gmail.com
154
+ email: seaneshbaugh@gmail.com
177
155
  executables: []
178
156
  extensions: []
179
157
  extra_rdoc_files: []
180
158
  files:
181
- - .gitignore
182
- - .rspec
183
- - .ruby-gemset
184
- - .ruby-version
159
+ - ".gitignore"
160
+ - ".rspec"
161
+ - ".ruby-gemset"
162
+ - ".ruby-version"
185
163
  - CHANGELOG.md
186
164
  - Gemfile
187
165
  - Gemfile.lock
@@ -247,33 +225,26 @@ files:
247
225
  - spec/spec_helper.rb
248
226
  homepage: https://github.com/seaneshbaugh/kentouzu
249
227
  licenses: []
228
+ metadata: {}
250
229
  post_install_message:
251
230
  rdoc_options: []
252
231
  require_paths:
253
232
  - lib
254
233
  required_ruby_version: !ruby/object:Gem::Requirement
255
- none: false
256
234
  requirements:
257
- - - ! '>='
235
+ - - ">="
258
236
  - !ruby/object:Gem::Version
259
237
  version: '0'
260
- segments:
261
- - 0
262
- hash: -3194602278824882459
263
238
  required_rubygems_version: !ruby/object:Gem::Requirement
264
- none: false
265
239
  requirements:
266
- - - ! '>='
240
+ - - ">="
267
241
  - !ruby/object:Gem::Version
268
242
  version: '0'
269
- segments:
270
- - 0
271
- hash: -3194602278824882459
272
243
  requirements: []
273
- rubyforge_project: kentouzu
274
- rubygems_version: 1.8.25
244
+ rubyforge_project:
245
+ rubygems_version: 2.2.2
275
246
  signing_key:
276
- specification_version: 3
247
+ specification_version: 4
277
248
  summary: Add drafts to ActiveRecord models.
278
249
  test_files:
279
250
  - spec/dummy/Rakefile