Skip to content

Instantly share code, notes, and snippets.

@aaronjensen
Last active December 16, 2015 22:29
Show Gist options
  • Select an option

  • Save aaronjensen/5507445 to your computer and use it in GitHub Desktop.

Select an option

Save aaronjensen/5507445 to your computer and use it in GitHub Desktop.
module EnableModelSync
extend ActiveSupport::Concern
included do
around_filter :enable_sync
end
def enable_sync
ModelSync.enable(self) do
yield
end
end
end
module ModelSync
extend ActiveSupport::Concern
include Sync::Actions
def self.enabled?
Thread.current["model_sync_enabled"]
end
def self.context
Thread.current["model_sync_context"]
end
def self.enable!(context = nil)
Thread.current["model_sync_enabled"] = true
Thread.current["model_sync_context"] = context
end
def self.disable!
Thread.current["model_sync_enabled"] = false
Thread.current["model_sync_context"] = nil
end
def self.enable(context = nil)
enable!(context)
yield
ensure
disable!
end
module ClassMethods
attr_accessor :sync_parent
def sync(*actions, parent: nil)
include Model
@sync_parent = parent
actions = [:create, :update, :destroy] if actions.include? :all
actions.flatten!
after_create :sync_after_create if actions.include? :create
after_update :sync_after_update if actions.include? :update
after_destroy :sync_after_destroy if actions.include? :destroy
end
end
module Model
def sync_parent
return nil unless self.class.sync_parent
send self.class.sync_parent
end
def sync_context
ModelSync.context || self
end
def sync_after_create
return unless ModelSync.enabled?
sync_context.sync_new self, scope: sync_parent if ModelSync.enabled?
end
def sync_after_update
return unless ModelSync.enabled?
if sync_parent
sync_context.sync_update [self, sync_parent.reload]
else
sync_context.sync_update self
end
end
def sync_after_destroy
return unless ModelSync.enabled?
sync_context.sync_destroy self
sync_context.sync_update sync_parent.reload if sync_parent
end
end
end
require 'spec_helper'
describe ModelSync do
it 'can is disabled by default' do
ModelSync.should_not be_enabled
end
it 'can be enabled and disabled' do
ModelSync.enable!
ModelSync.should be_enabled
ModelSync.disable!
ModelSync.should_not be_enabled
end
it 'can be given a block to have things enabled in' do
ModelSync.enable do
ModelSync.should be_enabled
end
ModelSync.should_not be_enabled
end
class FakeModel < ActiveRecord::Base
include ModelSync
self.table_name = 'tags'
sync :all
end
let(:model) { FakeModel.new name: "Foo" }
it 'can be mixed in to a model to allow sync' do
model.stub(:sync_new)
model.stub(:sync_update)
model.stub(:sync_destroy)
ModelSync.enable do
model.save!
model.should have_received(:sync_new).with(model, scope: nil)
model.save!
model.should have_received(:sync_update).with(model)
model.destroy!
model.should have_received(:sync_destroy).with(model)
end
end
it 'does not have a sync parent if it is not specified' do
model.sync_parent.should_not be
end
it 'does not sync if sync is not enabled' do
model = FakeModel.new name: "Foo"
model.stub(:sync_new)
model.save!
model.should_not have_received(:sync_new).with(model)
end
class FakeModelWithParent < ActiveRecord::Base
include ModelSync
self.table_name = 'tags'
sync :all, parent: :my_parent
end
it 'can have a parent specified when mixed into the model' do
model = FakeModelWithParent.new
parent = double("Parent")
model.stub(:sync_new)
model.stub(:sync_update)
model.stub(:sync_destroy)
model.stub(:my_parent) { parent }
parent.stub(:reload) { parent }
model.sync_parent.should == parent
ModelSync.enable do
model.save!
model.should have_received(:sync_new).with(model, scope: parent)
model.save!
model.should have_received(:sync_update).with([model, parent])
parent.should have_received(:reload)
model.destroy!
model.should have_received(:sync_destroy).with(model)
model.should have_received(:sync_update).with(parent)
parent.should have_received(:reload).twice
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment