mirror of
https://github.com/paper-trail-gem/paper_trail.git
synced 2022-11-09 11:33:19 -05:00
Condensing code for Hash args to the :ignore and :only options; also clarifying README
This commit is contained in:
parent
567f21b5a7
commit
22dd0cc69d
4 changed files with 50 additions and 48 deletions
|
@ -1,5 +1,7 @@
|
|||
## 3.0.0 (Unreleased)
|
||||
|
||||
- [#273](https://github.com/airblade/paper_trail/pull/273) - Make the `only` and `ignore` options accept `Hash` arguments;
|
||||
allows for conditional tracking.
|
||||
- [#264](https://github.com/airblade/paper_trail/pull/264) - Allow unwrapped symbol to be passed in to the `on` option.
|
||||
- [#224](https://github.com/airblade/paper_trail/issues/224)/[#236](https://github.com/airblade/paper_trail/pull/236) -
|
||||
Fixed compatibility with [ActsAsTaggableOn](https://github.com/mbleigh/acts-as-taggable-on).
|
||||
|
|
40
README.md
40
README.md
|
@ -268,7 +268,7 @@ You can ignore changes to certain attributes like this:
|
|||
|
||||
```ruby
|
||||
class Article < ActiveRecord::Base
|
||||
has_paper_trail :ignore => [:title, :rating => Proc.new { |obj| obj.raiting == 0 } ]
|
||||
has_paper_trail :ignore => [:title, :rating]
|
||||
end
|
||||
```
|
||||
|
||||
|
@ -277,13 +277,10 @@ This means that changes to just the `title` or `rating` will not store another v
|
|||
```ruby
|
||||
>> a = Article.create
|
||||
>> a.versions.length # 1
|
||||
>> a.update_attributes :title => 'My Title', :rating => 0
|
||||
>> a.versions.length # 1
|
||||
>> a.update_attributes :title => 'My Title', :rating => 3
|
||||
>> a.versions.length # 2
|
||||
>> a.previous_version.raiting # nil
|
||||
>> a.versions.length # 1
|
||||
>> a.update_attributes :title => 'Greeting', :content => 'Hello'
|
||||
>> a.versions.length # 3
|
||||
>> a.versions.length # 2
|
||||
>> a.previous_version.title # 'My Title'
|
||||
```
|
||||
|
||||
|
@ -291,11 +288,11 @@ Or, you can specify a list of all attributes you care about:
|
|||
|
||||
```ruby
|
||||
class Article < ActiveRecord::Base
|
||||
has_paper_trail :only => [:title, :author => Proc.new { |obj| obj.author.present? }]
|
||||
has_paper_trail :only => [:title]
|
||||
end
|
||||
```
|
||||
|
||||
This means that only changes to the `title` and non-empty `author` will save a version of the article:
|
||||
This means that only changes to the `title` will save a version of the article:
|
||||
|
||||
```ruby
|
||||
>> a = Article.create
|
||||
|
@ -305,11 +302,31 @@ This means that only changes to the `title` and non-empty `author` will save a v
|
|||
>> a.update_attributes :content => 'Hello'
|
||||
>> a.versions.length # 2
|
||||
>> a.previous_version.content # nil
|
||||
>> a.update_attributes :author => 'Me'
|
||||
```
|
||||
|
||||
The `:ignore` and `:only` options can also accept `Hash` arguments, where the :
|
||||
|
||||
```ruby
|
||||
class Article < ActiveRecord::Base
|
||||
has_paper_trail :only => [:title => Proc.new { |obj| !obj.title.blank? } ]
|
||||
end
|
||||
```
|
||||
|
||||
This means that if the `title` is not blank, then only changes to the `title` will save a version of the article:
|
||||
|
||||
```ruby
|
||||
>> a = Article.create
|
||||
>> a.versions.length # 1
|
||||
>> a.update_attributes :content => 'Hello'
|
||||
>> a.versions.length # 2
|
||||
>> a.update_attributes :title => 'My Title'
|
||||
>> a.versions.length # 3
|
||||
>> a.update_attributes :author => ''
|
||||
>> a.update_attributes :content => 'Hai'
|
||||
>> a.versions.length # 3
|
||||
>> a.previous_version.author # 'Me'
|
||||
>> a.previous_version.content # "Hello"
|
||||
>> a.update_attributes :title => 'Dif Title'
|
||||
>> a.versions.length # 4
|
||||
>> a.previous_version.content # "Hai"
|
||||
```
|
||||
|
||||
Passing both `:ignore` and `:only` options will result in the article being saved if a changed attribute is included in `:only` but not in `:ignore`.
|
||||
|
@ -973,6 +990,7 @@ Many thanks to:
|
|||
* [Bradley Priest](https://github.com/bradleypriest)
|
||||
* [David Butler](https://github.com/dwbutler)
|
||||
* [Paul Belt](https://github.com/belt)
|
||||
* [Vlad Bokov](https://github.com/razum2um)
|
||||
|
||||
|
||||
## Inspirations
|
||||
|
|
|
@ -15,12 +15,12 @@ module PaperTrail
|
|||
# `:create`, `:update`, `:destroy` as desired.
|
||||
# :class_name the name of a custom Version class. This class should inherit from Version.
|
||||
# :ignore an array of attributes for which a new `Version` will not be created if only they change.
|
||||
# it can also has a Hash as an item: the key is the attribute to ignore, the value - a Proc
|
||||
# given a current state of object before save, only if it results in true - attribute will be ignored
|
||||
# it can also aceept a Hash as an argument where the key is the attribute to ignore (a `String` or `Symbol`),
|
||||
# which will only be ignored if the value is a `Proc` which returns truthily.
|
||||
# :if, :unless Procs that allow to specify conditions when to save versions for an object
|
||||
# :only inverse of `ignore` - a new `Version` will be created only for these attributes if supplied
|
||||
# it can also has a Hash as an item: the key is the attribute to track, the value - a Proc
|
||||
# given a current state of object before save, only if it results in true - attribute will create a version
|
||||
# it can also aceept a Hash as an argument where the key is the attribute to track (a `String` or `Symbol`),
|
||||
# which will only be counted if the value is a `Proc` which returns truthily.
|
||||
# :skip fields to ignore completely. As with `ignore`, updates to these fields will not create
|
||||
# a new `Version`. In addition, these fields will not be included in the serialized versions
|
||||
# of the object whenever a new `Version` is created.
|
||||
|
@ -50,15 +50,7 @@ module PaperTrail
|
|||
|
||||
[:ignore, :skip, :only].each do |k|
|
||||
paper_trail_options[k] =
|
||||
([paper_trail_options[k]].flatten.compact || []).map do |attr|
|
||||
if attr.is_a? Hash
|
||||
Hash[attr.map do |attr_name, condition|
|
||||
[attr_name.to_s, condition]
|
||||
end]
|
||||
else
|
||||
attr.to_s
|
||||
end
|
||||
end
|
||||
([paper_trail_options[k]].flatten.compact || []).map { |attr| attr.is_a?(Hash) ? attr.stringify_keys : attr.to_s }
|
||||
end
|
||||
|
||||
paper_trail_options[:meta] ||= {}
|
||||
|
@ -285,7 +277,7 @@ module PaperTrail
|
|||
end
|
||||
|
||||
def object_to_string(object)
|
||||
_attrs = object.attributes.except(*self.class.paper_trail_options[:skip]).tap do |attributes|
|
||||
_attrs = object.attributes.except(*self.paper_trail_options[:skip]).tap do |attributes|
|
||||
self.class.serialize_attributes_for_paper_trail attributes
|
||||
end
|
||||
PaperTrail.serializer.dump(_attrs)
|
||||
|
@ -296,31 +288,21 @@ module PaperTrail
|
|||
end
|
||||
|
||||
def notably_changed
|
||||
only = []
|
||||
self.class.paper_trail_options[:only].each do |attr|
|
||||
if attr.is_a? Hash
|
||||
attr.each do |attr_name, condition|
|
||||
only << attr_name if condition.respond_to?(:call) && condition.call(self)
|
||||
end
|
||||
else
|
||||
only << attr
|
||||
end
|
||||
only = self.paper_trail_options[:only].dup
|
||||
# remove Hash arguments and then evaluate whether the attributes (the keys of the hash) should also get pushed into the collection
|
||||
only.delete_if do |obj|
|
||||
obj.is_a?(Hash) && obj.each { |attr, condition| only << attr if condition.respond_to?(:call) && condition.call(self) }
|
||||
end
|
||||
only.empty? ? changed_and_not_ignored : (changed_and_not_ignored & only)
|
||||
end
|
||||
|
||||
def changed_and_not_ignored
|
||||
ignore = []
|
||||
self.class.paper_trail_options[:ignore].each do |attr|
|
||||
if attr.is_a? Hash
|
||||
attr.each do |attr_name, condition|
|
||||
ignore << attr_name if condition.respond_to?(:call) && condition.call(self)
|
||||
ignore = self.paper_trail_options[:ignore].dup
|
||||
# remove Hash arguments and then evaluate whether the attributes (the keys of the hash) should also get pushed into the collection
|
||||
ignore.delete_if do |obj|
|
||||
obj.is_a?(Hash) && obj.each { |attr, condition| ignore << attr if condition.respond_to?(:call) && condition.call(self) }
|
||||
end
|
||||
else
|
||||
ignore << attr
|
||||
end
|
||||
end
|
||||
skip = self.class.paper_trail_options[:skip]
|
||||
skip = self.paper_trail_options[:skip]
|
||||
changed - ignore - skip
|
||||
end
|
||||
|
||||
|
@ -329,8 +311,8 @@ module PaperTrail
|
|||
end
|
||||
|
||||
def save_version?
|
||||
if_condition = self.class.paper_trail_options[:if]
|
||||
unless_condition = self.class.paper_trail_options[:unless]
|
||||
if_condition = self.paper_trail_options[:if]
|
||||
unless_condition = self.paper_trail_options[:unless]
|
||||
(if_condition.blank? || if_condition.call(self)) && !unless_condition.try(:call, self)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
class Article < ActiveRecord::Base
|
||||
has_paper_trail :ignore => [:title, { :abstract => Proc.new { |obj| ['ignore abstract', 'Other abstract'].include? obj.abstract } }],
|
||||
:only => [:content, { :abstract => Proc.new { |obj| obj.abstract.present? } }],
|
||||
has_paper_trail :ignore => [:title, :abstract => Proc.new { |obj| ['ignore abstract', 'Other abstract'].include? obj.abstract } ],
|
||||
:only => [:content, :abstract => Proc.new { |obj| obj.abstract.present? } ],
|
||||
:skip => [:file_upload],
|
||||
:meta => {
|
||||
:answer => 42,
|
||||
|
|
Loading…
Reference in a new issue