From 3d674109590ca2170f8e9d8880d30104ce99407f Mon Sep 17 00:00:00 2001 From: Wout Date: Fri, 14 Nov 2025 08:36:08 +0100 Subject: [PATCH 1/2] 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`. --- spec/avram/model_spec.cr | 27 ++++++++++++++++++++++ src/avram/primary_key_methods.cr | 39 ++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/spec/avram/model_spec.cr b/spec/avram/model_spec.cr index 8fa9a8cc2..358246cdb 100644 --- a/spec/avram/model_spec.cr +++ b/spec/avram/model_spec.cr @@ -128,6 +128,33 @@ describe Avram::Model do end end + describe "reload?" do + it "can safely reload a model" do + user = UserFactory.create &.name("Original Name") + newly_updated_user = User::SaveOperation.update!(user, name: "Updated Name") + newly_updated_user.name.should eq("Updated Name") + user.name.should eq("Original Name") + + user.reload?.as(User).name.should eq("Updated Name") + + User::DeleteOperation.delete!(user) + + user.reload?.should be_nil + end + + it "can reload a model with a yielded query" do + with_lazy_load(enabled: false) do + post = PostFactory.create + + post.reload?(&.preload_tags).as(Post).tags.should be_empty + + Post::DeleteOperation.delete!(post) + + post.reload?(&.preload_tags).should be_nil + end + end + end + it "sets up simple methods for equality" do query = QueryMe::BaseQuery.new.email("foo@bar.com").age(30) diff --git a/src/avram/primary_key_methods.cr b/src/avram/primary_key_methods.cr index d52e65408..52266b2b4 100644 --- a/src/avram/primary_key_methods.cr +++ b/src/avram/primary_key_methods.cr @@ -66,6 +66,45 @@ module Avram::PrimaryKeyMethods query.find(id) end + # Reload the model with the latest information from the database, if it still + # exists. + # + # This method will return a new model instance with the latest data from the + # database, or `Nil` if the record has been deleted in the meantime. + # + # Example: + # + # ``` + # user = SaveUser.create!(name: "Original") + # + # # ... record is deleted + # + # user.reload? + # # => Nil + # ``` + def reload? : self | Nil + base_query_class.new.id(id).first? + end + + # Same as `reload` but allows passing a block to customize the query. + # + # This is almost always used to preload additional relationships. + # + # Example: + # + # ``` + # user = SaveUser.create(params) + # + # # ... record is deleted + # + # user = user.reload?(&.preload_comments(CommentQuery.new.preload_article)) + # # => Nil + # ``` + def reload?(&) : self | Nil + query = yield base_query_class.new + query.id(id).first? + end + # For integration with Lucky # This allows an `Avram::Model` to be passed into a Lucky::Action to create a url/path def to_param : String From 7a707834b93a5eca091f86a43000d477481578ce Mon Sep 17 00:00:00 2001 From: Wout Date: Fri, 14 Nov 2025 08:42:42 +0100 Subject: [PATCH 2/2] Carify documentation in code and specs for `.reload?` --- spec/avram/model_spec.cr | 2 +- src/avram/primary_key_methods.cr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/avram/model_spec.cr b/spec/avram/model_spec.cr index 358246cdb..54b49fdeb 100644 --- a/spec/avram/model_spec.cr +++ b/spec/avram/model_spec.cr @@ -142,7 +142,7 @@ describe Avram::Model do user.reload?.should be_nil end - it "can reload a model with a yielded query" do + it "can safely reload a model with a yielded query" do with_lazy_load(enabled: false) do post = PostFactory.create diff --git a/src/avram/primary_key_methods.cr b/src/avram/primary_key_methods.cr index 52266b2b4..cfdb652ec 100644 --- a/src/avram/primary_key_methods.cr +++ b/src/avram/primary_key_methods.cr @@ -86,7 +86,7 @@ module Avram::PrimaryKeyMethods base_query_class.new.id(id).first? end - # Same as `reload` but allows passing a block to customize the query. + # Same as `reload?` but allows passing a block to customize the query. # # This is almost always used to preload additional relationships. #