Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding transaction raise methods #232

Merged
merged 17 commits into from
Jun 21, 2018
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions spec/granite/exceptions/record_invalid_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require "../../spec_helper"

{% for adapter in GraniteExample::ADAPTERS %}
module {{adapter.capitalize.id}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

describe Granite::RecordNotSaved do
it "should have a message" do
parent = Parent.new
parent.save

Granite::RecordNotSaved
.new(Parent.name, parent)
.message
.should eq("Could not process {{adapter.capitalize.id}}::Parent")
end

it "should have a model" do
parent = Parent.new
parent.save

Granite::RecordNotSaved
.new(Parent.name, parent)
.model
.should eq(parent)
end
end
end
{% end %}
27 changes: 27 additions & 0 deletions spec/granite/exceptions/record_not_destroyed_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require "../../spec_helper"

{% for adapter in GraniteExample::ADAPTERS %}
module {{adapter.capitalize.id}}
describe Granite::RecordNotDestroyed do
it "should have a message" do
parent = Parent.new
parent.save

Granite::RecordNotDestroyed
.new(Parent.name, parent)
.message
.should eq("Could not destroy {{adapter.capitalize.id}}::Parent")
end

it "should have a model" do
parent = Parent.new
parent.save

Granite::RecordNotDestroyed
.new(Parent.name, parent)
.model
.should eq(parent)
end
end
end
{% end %}
22 changes: 18 additions & 4 deletions spec/granite/transactions/create_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ module {{adapter.capitalize.id}}
describe "{{ adapter.id }} .create" do
it "creates a new object" do
parent = Parent.create(name: "Test Parent")
parent.id.should_not be_nil
parent.persisted?.should be_true
parent.name.should eq("Test Parent")
end

it "does not create an invalid object" do
parent = Parent.create(name: "")
parent.id.should be_nil
parent.persisted?.should be_false
end

it "takes JSON::Any" do
Expand Down Expand Up @@ -51,15 +51,15 @@ module {{adapter.capitalize.id}}
describe "with a custom primary key" do
it "creates a new object" do
school = School.create(name: "Test School")
school.custom_id.should_not be_nil
school.persisted?.should be_true
school.name.should eq("Test School")
end
end

describe "with a modulized model" do
it "creates a new object" do
county = Nation::County.create(name: "Test School")
county.id.should_not be_nil
county.persisted?.should be_true
county.name.should eq("Test School")
end
end
Expand All @@ -72,5 +72,19 @@ module {{adapter.capitalize.id}}
end
end
end

describe "{{ adapter.id }} .create!" do
it "creates a new object" do
parent = Parent.create!(name: "Test Parent")
parent.persisted?.should be_true
parent.name.should eq("Test Parent")
end

it "does not save but raise an exception" do
expect_raises(Granite::RecordNotSaved, "{{adapter.capitalize.id}}::Parent") do
parent = Parent.create!(name: "")
end
end
end
end
{% end %}
30 changes: 30 additions & 0 deletions spec/granite/transactions/destroy_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,35 @@ module {{adapter.capitalize.id}}
end
end
end

describe "{{ adapter.id }} #destroy!" do
it "destroys an object" do
parent = Parent.new
parent.name = "Test Parent"
parent.save!

id = parent.id
parent.destroy
found = Parent.find id
found.should be_nil
end

it "does not destroy but raise an exception" do
callback_with_abort = CallbackWithAbort.new
callback_with_abort.name = "DestroyRaisesException"
callback_with_abort.abort_at = "temp"
callback_with_abort.do_abort = false
callback_with_abort.save!
callback_with_abort.abort_at = "before_destroy"
callback_with_abort.do_abort = true


expect_raises(Granite::RecordNotDestroyed, "{{adapter.capitalize.id}}::CallbackWithAbort") do
callback_with_abort.destroy!
end

CallbackWithAbort.find_by(name: callback_with_abort.name).should_not be_nil
end
end
end
{% end %}
23 changes: 20 additions & 3 deletions spec/granite/transactions/save_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ module {{adapter.capitalize.id}}
parent = Parent.new
parent.name = "Test Parent"
parent.save
parent.id.should_not be_nil
parent.persisted?.should be_true
end

it "does not create an invalid object" do
parent = Parent.new
parent.name = ""
parent.save
parent.id.should be_nil
parent.persisted?.should be_false
end

it "updates an existing object" do
Expand Down Expand Up @@ -96,7 +96,7 @@ module {{adapter.capitalize.id}}
county = Nation::County.new
county.name = "Test School"
county.save
county.id.should_not be_nil
county.persisted?.should be_true
end

it "updates an existing object" do
Expand Down Expand Up @@ -132,5 +132,22 @@ module {{adapter.capitalize.id}}
end
end
end

describe "{{ adapter.id }} #save!" do
it "creates a new object" do
parent = Parent.new
parent.name = "Test Parent"
parent.save!
parent.persisted?.should be_true
end

it "does not create but raise an exception" do
parent = Parent.new

expect_raises(Granite::RecordNotSaved, "{{adapter.capitalize.id}}::Parent") do
parent.save!
end
end
end
end
{% end %}
50 changes: 50 additions & 0 deletions spec/granite/transactions/update_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
require "../../spec_helper"

{% for adapter in GraniteExample::ADAPTERS %}
module {{adapter.capitalize.id}}
describe "{{ adapter.id }} #update" do
it "updates an object" do
parent = Parent.new(name: "New Parent")
parent.save!

parent.update(name: "Other parent").should be_true
parent.name.should eq "Other parent"

Parent.find!(parent.id).name.should eq "Other parent"
end

it "does not update an invalid object" do
parent = Parent.new(name: "New Parent")
parent.save!

parent.update(name: "").should be_false
parent.name.should eq ""

Parent.find!(parent.id).name.should eq "New Parent"
end
end

describe "{{ adapter.id }} #update!" do
it "updates an object" do
parent = Parent.new(name: "New Parent")
parent.save!

parent.update!(name: "Other parent")
parent.name.should eq "Other parent"

Parent.find!(parent.id).name.should eq "Other parent"
end

it "does not update but raises an exception" do
parent = Parent.new(name: "New Parent")
parent.save!

expect_raises(Granite::RecordNotSaved, "{{adapter.capitalize.id}}::Parent") do
parent.update!(name: "")
end

Parent.find!(parent.id).name.should eq "New Parent"
end
end
end
{% end %}
1 change: 1 addition & 0 deletions spec/spec_models.cr
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ require "uuid"
table_name callbacks_with_abort
primary abort_at : String, auto: false
field do_abort : Bool
field name : String

property history : IO::Memory = IO::Memory.new

Expand Down
21 changes: 21 additions & 0 deletions src/granite/exceptions.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module Granite
class RecordNotSaved < ::Exception
getter model : Granite::Base

def initialize(class_name : String, model : Granite::Base)
super("Could not process #{class_name}")

@model = model
end
end

class RecordNotDestroyed < ::Exception
getter model : Granite::Base

def initialize(class_name : String, model : Granite::Base)
super("Could not destroy #{class_name}")

@model = model
end
end
end
45 changes: 45 additions & 0 deletions src/granite/transactions.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require "./exceptions"

module Granite::Transactions
module ClassMethods
def create(**args)
Expand All @@ -11,6 +13,20 @@ module Granite::Transactions
instance
end

def create!(**args)
create!(args.to_h)
end

def create!(args : Hash(Symbol | String, DB::Any) | JSON::Any)
instance = create(args)

if instance.errors.any?
raise Granite::RecordNotSaved.new(self.name, instance)
end

instance
end

def from_json(args : JSON::Any)
if args.as_a?
args.as_a.map { |a| model = new; model.set_attributes(a); model }
Expand Down Expand Up @@ -151,6 +167,31 @@ module Granite::Transactions
true
end


def save!
save || raise Granite::RecordNotSaved.new(self.class.name, self)
end

def update(**args)
update(args.to_h)
end

def update(args : Hash(Symbol | String, DB::Any) | JSON::Any)
set_attributes(args)

save
end

def update!(**args)
update!(args.to_h)
end

def update!(args : Hash(Symbol | String, DB::Any) | JSON::Any)
set_attributes(args)

save!
end

# Destroy will remove this from the database.
def destroy
begin
Expand All @@ -166,6 +207,10 @@ module Granite::Transactions
end
true
end

def destroy!
destroy || raise Granite::RecordNotDestroyed.new(self.class.name, self)
end
end

# Returns true if this object hasn't been saved yet.
Expand Down