spec/graph_persistence_spec.rb in terrestrial-0.1.1 vs spec/graph_persistence_spec.rb in terrestrial-0.3.0
- old
+ new
@@ -1,30 +1,28 @@
require "spec_helper"
require "support/have_persisted_matcher"
-require "support/mapper_setup"
-require "support/sequel_persistence_setup"
+require "support/object_store_setup"
require "support/seed_data_setup"
require "terrestrial"
RSpec.describe "Graph persistence" do
- include_context "mapper setup"
- include_context "sequel persistence setup"
+ include_context "object store setup"
include_context "seed data setup"
- subject(:mapper) { mappers.fetch(:users) }
+ subject(:user_store) { object_store.fetch(:users) }
let(:user) {
- mapper.where(id: "users/1").first
+ user_store.where(id: "users/1").first
}
context "without associations" do
- let(:modified_email) { "bestie+modified@gmail.com" }
+ let(:modified_email) { "hasel+modified@gmail.com" }
it "saves the root object" do
user.email = modified_email
- mapper.save(user)
+ user_store.save(user)
expect(datastore).to have_persisted(
:users,
hash_including(
id: "users/1",
@@ -33,11 +31,11 @@
)
end
it "doesn't send associated objects to the database as columns" do
user.email = modified_email
- mapper.save(user)
+ user_store.save(user)
expect(datastore).not_to have_persisted(
:users,
hash_including(
posts: anything,
@@ -48,11 +46,11 @@
# TODO move to a dirty tracking spec?
context "when mutating entity fields in place" do
it "saves the object" do
user.email << "MUTATED"
- mapper.save(user)
+ user_store.save(user)
expect(datastore).to have_persisted(
:users,
hash_including(
id: "users/1",
@@ -67,11 +65,11 @@
let(:post) { user.posts.first }
let(:modified_post_body) { "modified ur body" }
it "saves the associated object" do
post.body = modified_post_body
- mapper.save(user)
+ user_store.save(user)
expect(datastore).to have_persisted(
:posts,
hash_including(
id: post.id,
@@ -90,11 +88,11 @@
let(:modified_comment_body) { "body moving, body moving" }
it "saves the associated object" do
comment.body = modified_comment_body
- mapper.save(user)
+ user_store.save(user)
expect(datastore).to have_persisted(
:comments,
hash_including(
{
@@ -131,21 +129,33 @@
end
it "persists the object" do
user.posts.push(new_post)
- mapper.save(user)
+ user_store.save(user)
expect(datastore).to have_persisted(
:posts,
hash_including(
id: "posts/neu",
author_id: user.id,
subject: "I am new",
)
)
end
+
+ context "when the collection is not loaded until the new object is persisted" do
+ it "is consistent with the datastore" do
+ user.posts.push(new_post)
+
+ user_store.save(user)
+
+ expect(user.posts.to_a.map(&:id)).to eq(
+ ["posts/1", "posts/2", "posts/neu"]
+ )
+ end
+ end
end
context "delete an object from a has many association" do
let(:post) { user.posts.first }
@@ -155,11 +165,11 @@
expect(user.posts.map(&:id)).not_to include(post.id)
end
it "delete the object from the datastore on save" do
user.posts.delete(post)
- mapper.save(user)
+ user_store.save(user)
expect(datastore).not_to have_persisted(
:posts,
hash_including(
id: post.id,
@@ -180,11 +190,11 @@
end
it "deletes the 'join table' record" do
category = post.categories.first
post.categories.delete(category)
- mapper.save(user)
+ user_store.save(user)
expect(datastore).not_to have_persisted(
:categories_to_posts,
{
post_id: post.id,
@@ -194,11 +204,11 @@
end
it "does not delete the object" do
category = post.categories.first
post.categories.delete(category)
- mapper.save(user)
+ user_store.save(user)
expect(datastore).to have_persisted(
:categories,
hash_including(
id: category.id,
@@ -218,11 +228,11 @@
.to match_array(["categories/1", "categories/2"])
end
it "persists the change" do
post_with_one_category.categories.push(new_category)
- mapper.save(user)
+ user_store.save(user)
expect(datastore).to have_persisted(
:categories_to_posts,
{
post_id: post_with_one_category.id,
@@ -243,11 +253,11 @@
.to eq(modified_category_name)
end
it "persists the change" do
category.name = modified_category_name
- mapper.save(user)
+ user_store.save(user)
expect(datastore).to have_persisted(
:categories,
{
id: category.id,
@@ -256,17 +266,17 @@
)
end
end
context "node loaded as root has undefined one to many association" do
- let(:post_mapper) { mappers[:posts] }
- let(:post) { post_mapper.where(id: "posts/1").first }
+ let(:post_store) { object_store[:posts] }
+ let(:post) { post_store.where(id: "posts/1").first }
it "persists the changes to the root node" do
post.body = "modified body"
- post_mapper.save(post)
+ post_store.save(post)
expect(datastore).to have_persisted(
:posts,
hash_including(
id: "posts/1",
@@ -276,11 +286,11 @@
end
it "does not overwrite unused foreign key" do
post.body = "modified body"
- post_mapper.save(post)
+ post_store.save(post)
expect(datastore).to have_persisted(
:posts,
hash_including(
id: "posts/1",
@@ -289,21 +299,67 @@
)
end
end
end
+ context "when a many to one association is nil" do
+ context "when the object does not have a reference to its parent" do
+ it "populates that association with a nil" do
+ post = Post.new(
+ id: "posts/orphan",
+ subject: "Nils gonna getcha",
+ body: "",
+ created_at: Time.parse("2015-09-05T15:00:00+01:00"),
+ categories: [],
+ comments: [],
+ )
+
+ object_store[:posts].save(post)
+
+ expect(datastore).to have_persisted(
+ :posts,
+ hash_including(
+ id: "posts/orphan",
+ author_id: nil,
+ )
+ )
+ end
+ end
+
+ context "when an existing partent object reference is set to nil" do
+ it "populates that association with a nil" do
+ comment = user
+ .posts
+ .flat_map(&:comments)
+ .detect { |c| c.id == "comments/1" }
+
+ comment.commenter = nil
+
+ user_store.save(user)
+
+ expect(datastore).to have_persisted(
+ :comments,
+ hash_including(
+ id: "comments/1",
+ commenter_id: nil,
+ )
+ )
+ end
+ end
+ end
+
context "when a save operation fails (some object is not persistable)" do
let(:unpersistable_object) { ->() { } }
it "rolls back the transaction" do
pre_change = datastore[:users].to_a.map(&:to_a).sort
begin
user.first_name = "this will be rolled back"
user.posts.first.subject = unpersistable_object
- mapper.save(user)
- rescue Sequel::Error
+ user_store.save(user)
+ rescue Terrestrial::Error
end
post_change = datastore[:users].to_a.map(&:to_a).sort
expect(pre_change).to eq(post_change)