Module: DraftApprove::DraftChangesProxy
- Included in:
- Serialization::Json::DraftChangesProxy
- Defined in:
- lib/draft_approve/draft_changes_proxy.rb
Overview
Mixin wrapper for Draft
and acts_as_draftable
objects, such that both have a consistent API to get current and new values within the context of a specific DraftTransaction
.
References to other objects returned by methods from this class are also wrapped in a DraftChangesProxy
, meaning it is relatively easy to chain and navigate complex association trees within the context of a DraftTransaction
.
This can be useful, for example, to display all changes that will occur on an object, including changes to all it’s associated ‘child’ objects.
It is often most convenient to use the DraftTransaction#draft_proxy_for method to construct a DraftApproveProxy
instance. This will ensure the correct implementation of DraftApproveProxy
is used.
Classes which include this module must implement the instance methods new_value
, association_changed?
, associations_added
, associations_updated
, associations_removed
.
Instance Attribute Summary collapse
-
#draft ⇒ Object
readonly
Returns the value of attribute draft.
-
#draft_transaction ⇒ Object
readonly
Returns the value of attribute draft_transaction.
-
#draftable ⇒ Object
readonly
Returns the value of attribute draftable.
-
#draftable_class ⇒ Object
readonly
Returns the value of attribute draftable_class.
Instance Method Summary collapse
-
#association_changed?(association_name) ⇒ Boolean
Whether any changes will occur to the given association of the proxied
Draft
or draftable object. -
#associations_added(association_name) ⇒ Array<DraftChangesProxy>
All associated objects which will be added to the given association of the proxied
Draft
or draftable object. -
#associations_removed(association_name) ⇒ Array<DraftChangesProxy>
All associated objects which will be removed from the given association of the proxied
Draft
or draftable object. -
#associations_updated(association_name) ⇒ Array<DraftChangesProxy>
All associated objects which have been updated, but remain the proxied
Draft
or draftable object. -
#changed ⇒ Array<String>
List of attributes on the proxied
Draft
or draftable object which have changes. -
#changed? ⇒ Boolean
Whether or not the proxied
Draft
or draftable object has any changes. -
#changes ⇒ Hash<String, Array>
Hash of changes on the proxied
Draft
or draftable object which have changes. -
#create? ⇒ Boolean
true
if thisDraft
is to create a new record,false
otherwise. -
#current_to_s(include_class_and_id: false) ⇒ String
Returns a string representing the current value of the proxied object.
-
#current_value(attribute_name) ⇒ Object?
The currently persisted value for the given attribute on the proxied
Draft
or draftable object. -
#delete? ⇒ Boolean
true
if thisDraft
is to delete an existing record,false
otherwise. -
#initialize(object, transaction = nil) ⇒ Object
Creates a new DraftChangesProxy.
-
#new_value(attribute_name) ⇒ Object?
The new, drafted value for the given attribute on the proxied
Draft
or draftable object.
Instance Attribute Details
#draft ⇒ Object (readonly)
Returns the value of attribute draft.
26 27 28 |
# File 'lib/draft_approve/draft_changes_proxy.rb', line 26 def draft @draft end |
#draft_transaction ⇒ Object (readonly)
Returns the value of attribute draft_transaction.
26 27 28 |
# File 'lib/draft_approve/draft_changes_proxy.rb', line 26 def draft_transaction @draft_transaction end |
#draftable ⇒ Object (readonly)
Returns the value of attribute draftable.
26 27 28 |
# File 'lib/draft_approve/draft_changes_proxy.rb', line 26 def draftable @draftable end |
#draftable_class ⇒ Object (readonly)
Returns the value of attribute draftable_class.
26 27 28 |
# File 'lib/draft_approve/draft_changes_proxy.rb', line 26 def draftable_class @draftable_class end |
Instance Method Details
#association_changed?(association_name) ⇒ Boolean
Whether any changes will occur to the given association of the proxied Draft
or draftable object.
190 191 192 |
# File 'lib/draft_approve/draft_changes_proxy.rb', line 190 def association_changed?(association_name) raise "#association_changed? has not been implemented in #{self.class.name}" end |
#associations_added(association_name) ⇒ Array<DraftChangesProxy>
All associated objects which will be added to the given association of the proxied Draft
or draftable object.
201 202 203 |
# File 'lib/draft_approve/draft_changes_proxy.rb', line 201 def associations_added(association_name) raise "#associations_added has not been implemented in #{self.class.name}" end |
#associations_removed(association_name) ⇒ Array<DraftChangesProxy>
All associated objects which will be removed from the given association of the proxied Draft
or draftable object.
223 224 225 |
# File 'lib/draft_approve/draft_changes_proxy.rb', line 223 def associations_removed(association_name) raise "#associations_removed has not been implemented in #{self.class.name}" end |
#associations_updated(association_name) ⇒ Array<DraftChangesProxy>
All associated objects which have been updated, but remain the proxied Draft
or draftable object.
212 213 214 |
# File 'lib/draft_approve/draft_changes_proxy.rb', line 212 def associations_updated(association_name) raise "#associations_updated has not been implemented in #{self.class.name}" end |
#changed ⇒ Array<String>
List of attributes on the proxied Draft
or draftable object which have changes.
Note, this method only considers changes to attributes and changes to any belongs_to
references. Any added / changed / deleted has_many
or has_one
associations are not considered.
108 109 110 111 112 113 114 |
# File 'lib/draft_approve/draft_changes_proxy.rb', line 108 def changed if @draft.blank? [] # No draft for this object, so no attributes have changed else @draft.draft_changes.keys end end |
#changed? ⇒ Boolean
Whether or not the proxied Draft
or draftable object has any changes.
Note, this method only considers changes to attributes and changes to any belongs_to
references. Any added / changed / deleted has_many
or has_one
associations are not considered.
91 92 93 94 95 96 97 |
# File 'lib/draft_approve/draft_changes_proxy.rb', line 91 def changed? if @draft.blank? false # No draft for this object, so nothing changed else @draft.draft_changes.present? end end |
#changes ⇒ Hash<String, Array>
Hash of changes on the proxied Draft
or draftable object which have changes.
Note, this method only considers changes to attributes and changes to any belongs_to
references. Any added / changed / deleted has_many
or has_one
associations are not considered.
125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/draft_approve/draft_changes_proxy.rb', line 125 def changes @changes_memo ||= begin # Memoize result if @draft.blank? {} # No draft for this object, so no attributes have changed else @draft.draft_changes.each_with_object({}) do |(k,v), new_hash| new_hash[k] = [current_value(k), new_value(k)] end end end end |
#create? ⇒ Boolean
Returns true
if this Draft
is to create a new record, false
otherwise.
73 74 75 |
# File 'lib/draft_approve/draft_changes_proxy.rb', line 73 def create? @draft.present? && @draft.create? end |
#current_to_s(include_class_and_id: false) ⇒ String
Returns a string representing the current value of the proxied object.
252 253 254 255 256 257 258 259 260 261 |
# File 'lib/draft_approve/draft_changes_proxy.rb', line 252 def current_to_s(include_class_and_id: false) if @draftable.present? && include_class_and_id return "#{@draftable.to_s} <#{@draftable_class} ##{@draftable.id}>" elsif @draftable.present? return @draftable.to_s else # No current draftable return "New #{@draftable_class}" end end |
#current_value(attribute_name) ⇒ Object?
The currently persisted value for the given attribute on the proxied Draft
or draftable object.
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/draft_approve/draft_changes_proxy.rb', line 144 def current_value(attribute_name) # Create hash with default block for auto-memoization @current_values_memo ||= Hash.new do |hash, attribute| hash[attribute] = begin if @draftable.present? # Current value is what's on the draftable object draft_proxy_for(@draftable.public_send(attribute)) else # No draftable exists, so this must be a CREATE draft, meaning # there's no 'old' value... association = @draftable_class.reflect_on_association(attribute) if (association.blank? || association.belongs_to? || association.has_one?) nil # Not an association, or links to a single object else [] # Is a has_many association end end end end # Get memoized value, or calculate and store it @current_values_memo[attribute_name.to_s] end |
#delete? ⇒ Boolean
Returns true
if this Draft
is to delete an existing record, false
otherwise.
79 80 81 |
# File 'lib/draft_approve/draft_changes_proxy.rb', line 79 def delete? @draft.present? && @draft.delete? end |
#initialize(object, transaction = nil) ⇒ Object
Creates a new DraftChangesProxy
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/draft_approve/draft_changes_proxy.rb', line 37 def initialize(object, transaction = nil) if object.blank? raise(ArgumentError, "object is required") end if object.new_record? raise(ArgumentError, "object #{object} must already be persisted") end if object.is_a? Draft if transaction.present? && object.draft_transaction != transaction raise(ArgumentError, "draft_transaction for #{object} is inconsistent with given draft_transaction #{transaction}") end # Construct DraftableProxy from a draft # Note that @draftable may be nil (if this is a CREATE draft) @draft = object @draftable = (object.draftable.present? && object.draftable.persisted?) ? object.draftable : nil @draftable_class = Object.const_get(object.draftable_type) @draft_transaction = object.draft_transaction else if transaction.blank? raise(ArgumentError, "draft_transaction is required when object is a draftable") end # Construct DraftableProxy from a draftable # Note that @draft may be nil (if the draftable has no changes within the scope of this transaction) @draft = transaction.drafts.find_by(draftable: object) @draftable = object @draftable_class = object.class @draft_transaction = transaction end end |
#new_value(attribute_name) ⇒ Object?
The new, drafted value for the given attribute on the proxied Draft
or draftable object. If no changes have been drafted for the given attribute, then returns the currently persisted value for the attribute.
178 179 180 |
# File 'lib/draft_approve/draft_changes_proxy.rb', line 178 def new_value(attribute_name) raise "#new_value has not been implemented in #{self.class.name}" end |