Skip to content

Commit

Permalink
Lifecycle improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
pyromaniac committed Feb 17, 2014
1 parent 2c1e19c commit 518e00b
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 12 deletions.
28 changes: 22 additions & 6 deletions lib/active_data/model/associations/embeds_many.rb
Expand Up @@ -56,6 +56,10 @@ def concat *objects

private

def read_source
super || []
end

def concat_objects objects
objects.each { |object| push_object object }
result = objects.all?(&:save)
Expand All @@ -78,17 +82,29 @@ def load_target!
def setup_performers! object
association = self

object.define_save do
data = association.send(:read_source) || []
index = association.reader.select { |object| !object.destroyed? }.index { |object| object === self }
object.define_create do
data = association.send(:read_source)
index = association.reader.select do |object|
object.persisted? || object === self
end.index { |object| object === self }

data.insert(index, attributes)
association.send(:write_source, data)
end

object.define_update do
data = association.send(:read_source)
index = association.reader.select(&:persisted?).index { |object| object === self }

data[index] = attributes
association.send(:write_source, data)
end

object.define_destroy do
data = association.send(:read_source) || []
index = association.reader.select { |object| !object.destroyed? }.index { |object| object === self }
data.delete_at(index)
data = association.send(:read_source)
index = association.reader.select(&:persisted?).index { |object| object === self }

data.delete_at(index) if index
association.send(:write_source, data)
end
end
Expand Down
9 changes: 6 additions & 3 deletions lib/active_data/model/lifecycle.rb
Expand Up @@ -237,7 +237,7 @@ def save! options = {}, &block
def destroy &block
raise ActiveData::UndestroyableObject unless block || destroyable?
destroy_object(&block)
freeze
self
end

# Destroys object by calling the destroy performer.
Expand All @@ -257,7 +257,7 @@ def destroy &block
def destroy! &block
raise ActiveData::UndestroyableObject unless block || destroyable?
destroy_object(&block) or raise ActiveData::ObjectNotDestroyed
freeze
self
end

private
Expand All @@ -268,7 +268,10 @@ def savable?

def save_object &block
result = persisted? ? update_object(&block) : create_object(&block)
@persisted = true if result
if result
@destroyed = false
@persisted = true
end
!!result
end

Expand Down
42 changes: 42 additions & 0 deletions spec/lib/active_data/model/associations/embeds_many_spec.rb
Expand Up @@ -26,6 +26,48 @@
specify { association.should == user.association(:projects) }
end

context 'performers' do
let(:user) { User.new(projects: [Project.new(title: 'Project 1')]) }

specify do
p2 = user.projects.build(title: 'Project 2')
p3 = user.projects.build(title: 'Project 3')
p4 = user.projects.create(title: 'Project 4')
user.read_attribute(:projects).should == [{'title' => 'Project 1'}, {'title' => 'Project 4'}]
p2.save!
user.read_attribute(:projects).should == [
{'title' => 'Project 1'}, {'title' => 'Project 2'}, {'title' => 'Project 4'}]
p2.destroy!.destroy!
user.read_attribute(:projects).should == [{'title' => 'Project 1'}, {'title' => 'Project 4'}]
p5 = user.projects.create(title: 'Project 5')
user.read_attribute(:projects).should == [
{'title' => 'Project 1'}, {'title' => 'Project 4'}, {"title" => "Project 5"}]
p3.destroy!
user.projects.first.destroy!
user.read_attribute(:projects).should == [{'title' => 'Project 4'}, {"title" => "Project 5"}]
p4.destroy!.save!
user.read_attribute(:projects).should == [{'title' => 'Project 4'}, {"title" => "Project 5"}]
user.projects.count.should == 5
user.projects.map(&:save!)
user.read_attribute(:projects).should == [
{'title' => 'Project 1'}, {'title' => 'Project 2'}, {'title' => 'Project 3'},
{'title' => 'Project 4'}, {"title" => "Project 5"}]
user.projects.map(&:destroy!)
user.read_attribute(:projects).should == []
user.projects.first(2).map(&:save!)
user.read_attribute(:projects).should == [{'title' => 'Project 1'}, {'title' => 'Project 2'}]
user.projects.reload.count.should == 2
p3 = user.projects.create!(title: 'Project 3')
user.read_attribute(:projects).should == [
{'title' => 'Project 1'}, {'title' => 'Project 2'}, {'title' => 'Project 3'}]
p3.destroy!
user.read_attribute(:projects).should == [{'title' => 'Project 1'}, {'title' => 'Project 2'}]
p4 = user.projects.create(title: 'Project 4')
user.read_attribute(:projects).should == [
{'title' => 'Project 1'}, {'title' => 'Project 2'}, {'title' => 'Project 4'}]
end
end

describe '#build' do
specify { association.build.should be_a Project }
specify { association.build.should_not be_persisted }
Expand Down
34 changes: 31 additions & 3 deletions spec/lib/active_data/model/lifecycle_spec.rb
Expand Up @@ -4,9 +4,7 @@
describe ActiveData::Model::Lifecycle do
context do
before do
stub_model(:user) do
include ActiveData::Model::Lifecycle
end
stub_model(:user)
end

subject { User.new }
Expand Down Expand Up @@ -70,6 +68,36 @@
end
end
end

context 'performers execution' do
before do
stub_model(:user) do
include ActiveData::Model::Callbacks

attribute :actions, type: Array, default: []

def append action
self.actions = actions + [action]
end

define_create { append :create }
define_update { append :update }
define_destroy { append :destroy }
end
end

subject { User.new }

specify do
subject.destroy
subject.save
subject.save
subject.destroy
subject.destroy
subject.save
subject.actions.should == [:destroy, :create, :update, :destroy, :destroy, :create]
end
end
end

context 'destroy' do
Expand Down

0 comments on commit 518e00b

Please sign in to comment.