Skip to content

Commit e525dc9

Browse files
authored
Add safe record reload (#1122)
* Add `.reload?` and `.reload?(&)` methods Allow safe reloading records from the database and return `Nil` if the record no longer exists rather than raising a `Avram::RecordNotFoundError`. * Carify documentation in code and specs for `.reload?`
1 parent a067982 commit e525dc9

2 files changed

Lines changed: 66 additions & 0 deletions

File tree

spec/avram/model_spec.cr

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,33 @@ describe Avram::Model do
128128
end
129129
end
130130

131+
describe "reload?" do
132+
it "can safely reload a model" do
133+
user = UserFactory.create &.name("Original Name")
134+
newly_updated_user = User::SaveOperation.update!(user, name: "Updated Name")
135+
newly_updated_user.name.should eq("Updated Name")
136+
user.name.should eq("Original Name")
137+
138+
user.reload?.as(User).name.should eq("Updated Name")
139+
140+
User::DeleteOperation.delete!(user)
141+
142+
user.reload?.should be_nil
143+
end
144+
145+
it "can safely reload a model with a yielded query" do
146+
with_lazy_load(enabled: false) do
147+
post = PostFactory.create
148+
149+
post.reload?(&.preload_tags).as(Post).tags.should be_empty
150+
151+
Post::DeleteOperation.delete!(post)
152+
153+
post.reload?(&.preload_tags).should be_nil
154+
end
155+
end
156+
end
157+
131158
it "sets up simple methods for equality" do
132159
query = QueryMe::BaseQuery.new.email("foo@bar.com").age(30)
133160

src/avram/primary_key_methods.cr

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,45 @@ module Avram::PrimaryKeyMethods
6666
query.find(id)
6767
end
6868

69+
# Reload the model with the latest information from the database, if it still
70+
# exists.
71+
#
72+
# This method will return a new model instance with the latest data from the
73+
# database, or `Nil` if the record has been deleted in the meantime.
74+
#
75+
# Example:
76+
#
77+
# ```
78+
# user = SaveUser.create!(name: "Original")
79+
#
80+
# # ... record is deleted
81+
#
82+
# user.reload?
83+
# # => Nil
84+
# ```
85+
def reload? : self | Nil
86+
base_query_class.new.id(id).first?
87+
end
88+
89+
# Same as `reload?` but allows passing a block to customize the query.
90+
#
91+
# This is almost always used to preload additional relationships.
92+
#
93+
# Example:
94+
#
95+
# ```
96+
# user = SaveUser.create(params)
97+
#
98+
# # ... record is deleted
99+
#
100+
# user = user.reload?(&.preload_comments(CommentQuery.new.preload_article))
101+
# # => Nil
102+
# ```
103+
def reload?(&) : self | Nil
104+
query = yield base_query_class.new
105+
query.id(id).first?
106+
end
107+
69108
# For integration with Lucky
70109
# This allows an `Avram::Model` to be passed into a Lucky::Action to create a url/path
71110
def to_param : String

0 commit comments

Comments
 (0)