Module: WithoutScope::ActsAsRevisable::Common

Defined in:
lib/acts_as_revisable/acts/common.rb

Overview

This module is mixed into the revision and revisable classes.

Callbacks

  • before_branch is called on the Revisable or Revision that is being branched

  • after_branch is called on the Revisable or Revision that is being branched

Defined Under Namespace

Modules: ClassMethods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object

:nodoc:



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/acts_as_revisable/acts/common.rb', line 12

def self.included(base) #:nodoc:
  base.send(:extend, ClassMethods)
  
  base.class_inheritable_hash :revisable_after_callback_blocks
  base.revisable_after_callback_blocks = {}
  
  base.class_inheritable_hash :revisable_current_states
  base.revisable_current_states = {}
  
  base.instance_eval do
    define_callbacks :before_branch, :after_branch      
    has_many :branches, (revisable_options.revision_association_options || {}).merge({:class_name => base.name, :foreign_key => :revisable_branched_from_id})
              
    belongs_to :branch_source, :class_name => base.name, :foreign_key => :revisable_branched_from_id
    after_save :execute_blocks_after_save
  end        
end

Instance Method Details

#branch(*args, &block) ⇒ Object

Branch the Revisable or Revision and return the new revisable instance. The instance has not been saved yet.

Callbacks

  • before_branch is called on the Revisable or Revision that is being branched

  • after_branch is called on the Revisable or Revision that is being branched

  • after_branch_created is called on the newly created Revisable instance.



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/acts_as_revisable/acts/common.rb', line 58

def branch(*args, &block)
  is_branching!
  
  unless run_callbacks(:before_branch) { |r, o| r == false}
    raise ActiveRecord::RecordNotSaved
  end

  options = args.extract_options!
  options[:revisable_branched_from_id] = self.id
  self.class.column_names.each do |col|
    next unless self.class.revisable_should_clone_column? col
    options[col.to_sym] = self[col] unless options.has_key?(col.to_sym)
  end
  
  br = self.class.revisable_class.new(options)
  br.is_branching!
  
  br.execute_after(:save) do
    begin
      run_callbacks(:after_branch)
      br.run_callbacks(:after_branch_created)
    ensure
      br.is_branching!(false)
      is_branching!(false)
    end
  end
  
  block.call(br) if block_given?
  
  br
end

#branch!(*args) ⇒ Object

Same as #branch except it calls #save! on the new Revisable instance.



91
92
93
94
95
# File 'lib/acts_as_revisable/acts/common.rb', line 91

def branch!(*args)
  branch(*args) do |br|
    br.save!
  end
end

#current_revision?Boolean

Returns true if the instance is the current record and not a revision.

Returns:

  • (Boolean)


143
144
145
# File 'lib/acts_as_revisable/acts/common.rb', line 143

def current_revision?
  self.is_a? self.class.revisable_class
end

#deleted?Boolean

Returns:

  • (Boolean)


165
166
167
# File 'lib/acts_as_revisable/acts/common.rb', line 165

def deleted?
  self.revisable_deleted_at.present?
end

#diffs(what) ⇒ Object



156
157
158
159
160
161
162
163
# File 'lib/acts_as_revisable/acts/common.rb', line 156

def diffs(what)
  what = current_revision.find_revision(what)
  returning({}) do |changes|
    self.class.revisable_class.revisable_watch_columns.each do |c|
      changes[c] = [self[c], what[c]] unless self[c] == what[c]
    end
  end
end

#execute_after(key, &block) ⇒ Object

Stores a block for later execution after a given callback. The parameter key is the callback the block should be executed after.



42
43
44
45
46
# File 'lib/acts_as_revisable/acts/common.rb', line 42

def execute_after(key, &block) #:nodoc:
  return unless block_given?
  revisable_after_callback_blocks[key] ||= []
  revisable_after_callback_blocks[key] << block
end

#execute_blocks_after_saveObject

Executes the blocks stored in an accessor after a save.



31
32
33
34
35
36
37
# File 'lib/acts_as_revisable/acts/common.rb', line 31

def execute_blocks_after_save #:nodoc:
  return unless revisable_after_callback_blocks[:save]
  revisable_after_callback_blocks[:save].each do |block|
    block.call
  end
  revisable_after_callback_blocks.delete(:save)
end

#first_revision?Boolean

Returns true if the instance is the first revision.

Returns:

  • (Boolean)


133
134
135
# File 'lib/acts_as_revisable/acts/common.rb', line 133

def first_revision?
  self.revision_number == 1
end

#get_revisable_state(type) ⇒ Object

Returns the state of the given record.



126
127
128
129
130
# File 'lib/acts_as_revisable/acts/common.rb', line 126

def get_revisable_state(type) #:nodoc:
  key = self.read_attribute(self.class.primary_key)
  revisable_current_states[type] ||= {}
  revisable_current_states[type][key] || revisable_current_states[type][object_id] || false
end

#is_branching!(value = true) ⇒ Object

Globally sets the reverting state of this record.



98
99
100
# File 'lib/acts_as_revisable/acts/common.rb', line 98

def is_branching!(value=true) #:nodoc:
  set_revisable_state(:branching, value)
end

#is_branching?Boolean

Returns true if the record (not just this instance of the record) is currently being branched.

Returns:

  • (Boolean)


104
105
106
# File 'lib/acts_as_revisable/acts/common.rb', line 104

def is_branching?
  get_revisable_state(:branching)
end

#latest_revision?Boolean

Returns true if the instance is the most recent revision.

Returns:

  • (Boolean)


138
139
140
# File 'lib/acts_as_revisable/acts/common.rb', line 138

def latest_revision?
  self.revision_number == self.current_revision.revision_number
end

#original_idObject

When called on a Revision it returns the original id. When called on a Revisable it returns the id.



110
111
112
# File 'lib/acts_as_revisable/acts/common.rb', line 110

def original_id
  self[:revisable_original_id] || self[:id]
end

#revision_numberObject

Accessor for revisable_number just to make external API more pleasant.



148
149
150
# File 'lib/acts_as_revisable/acts/common.rb', line 148

def revision_number
  self[:revisable_number] ||= 0
end

#revision_number=(value) ⇒ Object



152
153
154
# File 'lib/acts_as_revisable/acts/common.rb', line 152

def revision_number=(value)
  self[:revisable_number] = value
end

#set_revisable_state(type, value) ⇒ Object

Globally sets the state for a given record. This is keyed on the primary_key of a saved record or the object_id on a new instance.



117
118
119
120
121
122
123
# File 'lib/acts_as_revisable/acts/common.rb', line 117

def set_revisable_state(type, value) #:nodoc:
  key = self.read_attribute(self.class.primary_key)
  key = object_id if key.nil?
  revisable_current_states[type] ||= {}
  revisable_current_states[type][key] = value
  revisable_current_states[type].delete(key) unless value
end