Skip to content

Commit

Permalink
Merge pull request #1 from chargify/rails-4
Browse files Browse the repository at this point in the history
Rails 4.0-related changes
  • Loading branch information
speric committed Feb 18, 2016
2 parents 0b321f9 + 17b71a8 commit f616698
Show file tree
Hide file tree
Showing 9 changed files with 184 additions and 163 deletions.
8 changes: 8 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ GEM
multi_json (~> 1.0)
arel (3.0.2)
builder (3.0.0)
coderay (1.0.8)
diff-lcs (1.1.3)
ffi (1.0.11)
growl (1.0.3)
Expand All @@ -34,7 +35,12 @@ GEM
rb-fchange (~> 0.0.5)
rb-fsevent (~> 0.9.1)
rb-inotify (~> 0.8.8)
method_source (0.8.1)
multi_json (1.3.6)
pry (0.9.10)
coderay (~> 1.0.5)
method_source (~> 0.8)
slop (~> 3.3.1)
rake (0.9.2.2)
rb-fchange (0.0.5)
ffi
Expand All @@ -49,6 +55,7 @@ GEM
rspec-expectations (2.10.0)
diff-lcs (~> 1.1.3)
rspec-mocks (2.10.1)
slop (3.3.3)
sqlite3 (1.3.6)
thor (0.15.3)
tzinfo (0.3.33)
Expand All @@ -60,6 +67,7 @@ DEPENDENCIES
acts_as_revisable!
growl (~> 1.0.3)
guard-rspec (~> 1.1.0)
pry
rake (~> 0.9.2)
rb-fsevent (~> 0.9.1)
rspec (~> 2.10.0)
Expand Down
1 change: 1 addition & 0 deletions acts_as_revisable.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ Gem::Specification.new do |s|
s.add_development_dependency('growl', '~> 1.0.3')
s.add_development_dependency('rb-fsevent', '~> 0.9.1')
s.add_development_dependency('sqlite3', '~> 1.3.6')
s.add_development_dependency('pry')
end
102 changes: 49 additions & 53 deletions lib/acts_as_revisable/acts/common.rb
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
module WithoutScope
module ActsAsRevisable
# This module is mixed into the revision and revisable classes.
#
#
# ==== Callbacks
#
# * +before_branch+ is called on the +Revisable+ or +Revision+ that is
#
# * +before_branch+ is called on the +Revisable+ or +Revision+ that is
# being branched
# * +after_branch+ is called on the +Revisable+ or +Revision+ that is
# * +after_branch+ is called on the +Revisable+ or +Revision+ that is
# being branched
module Common
def self.included(base) #:nodoc:
base.send(:extend, ClassMethods)

base.class_attribute :revisable_after_callback_blocks
base.revisable_after_callback_blocks = {}

base.class_attribute :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})
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)

after_save :execute_blocks_after_save
end
end

# Executes the blocks stored in an accessor after a save.
def execute_blocks_after_save #:nodoc:
return unless revisable_after_callback_blocks[:save]
Expand All @@ -34,29 +34,29 @@ def execute_blocks_after_save #:nodoc:
end
revisable_after_callback_blocks.delete(:save)
end

# Stores a block for later execution after a given callback.
# The parameter +key+ is the callback the block should be
# The parameter +key+ is the callback the block should be
# executed after.
def execute_after(key, &block) #:nodoc:
return unless block_given?
revisable_after_callback_blocks[key] ||= []
revisable_after_callback_blocks[key] << block
end
# Branch the +Revisable+ or +Revision+ and return the new

# 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
# * +before_branch+ is called on the +Revisable+ or +Revision+ that is
# being branched
# * +after_branch+ is called on the +Revisable+ or +Revision+ that is
# * +after_branch+ is called on the +Revisable+ or +Revision+ that is
# being branched
# * +after_branch_created+ is called on the newly created
# * +after_branch_created+ is called on the newly created
# +Revisable+ instance.
def branch(*args, &block)
is_branching!

unless run_callbacks(:before_branch)
raise ActiveRecord::RecordNotSaved
end
Expand All @@ -67,10 +67,10 @@ def branch(*args, &block)
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)
Expand All @@ -80,48 +80,44 @@ def branch(*args, &block)
is_branching!(false)
end
end

block.call(br) if block_given?

br
end

# Same as #branch except it calls #save! on the new +Revisable+ instance.
def branch!(*args)
branch(*args) do |br|
br.save!
end
end

# Globally sets the reverting state of this record.
def is_branching!(value=true) #:nodoc:
set_revisable_state(:branching, value)
end

# XXX: This should be done with a "belongs_to" but the default
# scope on the target class prevents the find with revisions.
def branch_source
self[:branch_source] ||= if self[:revisable_branched_from_id]
self.class.find(self[:revisable_branched_from_id],
:with_revisions => true)
else
nil
end

end

# Returns true if the _record_ (not just this instance
self.class.where(:id => self[:revisable_branched_from_id]).with_revisions
else
nil
end
end

# Returns true if the _record_ (not just this instance
# of the record) is currently being branched.
def is_branching?
get_revisable_state(:branching)
end

# When called on a +Revision+ it returns the original id. When
# called on a +Revisable+ it returns the id.
def original_id
self[:revisable_original_id] || self[:id]
end

# 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.
Expand All @@ -132,38 +128,38 @@ def set_revisable_state(type, value) #:nodoc:
revisable_current_states[type][key] = value
revisable_current_states[type].delete(key) unless value
end

# Returns the state of the given record.
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

# Returns true if the instance is the first revision.
def first_revision?
self.revision_number == 1
end

# Returns true if the instance is the most recent revision.
def latest_revision?
self.revision_number == self.current_revision.revision_number
end

# Returns true if the instance is the current record and not a revision.
def current_revision?
self.is_a? self.class.revisable_class
end

# Accessor for revisable_number just to make external API more pleasant.
def revision_number
self[:revisable_number] ||= 0
end

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

def diffs(what)
what = current_revision.find_revision(what)
returning({}) do |changes|
Expand All @@ -172,27 +168,27 @@ def diffs(what)
end
end
end

def deleted?
self.revisable_deleted_at.present?
end
module ClassMethods
# Returns true if the revision should clone the given column.

module ClassMethods
# Returns true if the revision should clone the given column.
def revisable_should_clone_column?(col) #:nodoc:
return false if (REVISABLE_SYSTEM_COLUMNS + REVISABLE_UNREVISABLE_COLUMNS).member? col
true
end

# acts_as_revisable's override for instantiate so we can
# return the appropriate type of model based on whether
# or not the record is the current record.
def instantiate(record) #:nodoc:
def instantiate(record, column_types = {}) #:nodoc:
is_current = columns_hash["revisable_is_current"].type_cast(
record["revisable_is_current"])

if (is_current && self == self.revisable_class) || (!is_current && self == self.revision_class)
return super(record)
return super(record, column_types)
end

object = if is_current
Expand All @@ -212,7 +208,7 @@ def instantiate(record) #:nodoc:
object.send(:callback, :after_initialize)
end

object
object
end
end
end
Expand Down
Loading

0 comments on commit f616698

Please sign in to comment.