Skip to content

Commit

Permalink
Add methods to model class
Browse files Browse the repository at this point in the history
  • Loading branch information
treagod committed Nov 26, 2024
1 parent 5661f4a commit 7a83223
Show file tree
Hide file tree
Showing 2 changed files with 230 additions and 0 deletions.
120 changes: 120 additions & 0 deletions spec/marten/db/model/querying_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,60 @@ describe Marten::DB::Model::Querying do
it "makes use of the default queryset when using a block defining an advanced predicates expression" do
Tag.get { q(name: "crystal") }.should be_nil
end

it "returns the object corresponding to the raw SQL predicate" do
user = TestUser.create!(username: "jd3", email: "[email protected]", first_name: "John", last_name: "Doe")
TestUser.get("username = 'jd3'").should eq user
end

it "returns the object corresponding to the raw SQL predicate with positional arguments" do
user = TestUser.create!(username: "jd3", email: "[email protected]", first_name: "John", last_name: "Doe")
TestUser.get("username = ?", "jd3").should eq user
end

it "returns nil if no record matches the raw SQL predicate with positional arguments" do
TestUser.get("username = ?", "unknown").should be_nil
end

it "returns the object when parameters are passed as an array" do
tag = Tag.create!(name: "elixir", is_active: true)
Tag.get("name = ? AND is_active = ?", ["elixir", true]).should eq tag
end

it "returns nil when no record matches and parameters are passed as an array" do
Tag.get("name = ? AND is_active = ?", ["nonexistent", true]).should be_nil
end

it "raises an error for an invalid SQL column in raw predicate" do
expect_raises(Exception) { TestUser.get("invalid_column = ?", "jd1") }
end

it "returns the object using a raw SQL predicate with named parameters" do
tag = Tag.create!(name: "custom", is_active: true)
Tag.get("name = :name AND is_active = :active", name: "custom", active: true).should eq tag
end

it "returns nil if no record matches the raw SQL predicate with named parameters" do
Tag.get("name = :name AND is_active = :active", name: "nonexistent", active: false).should be_nil
end

it "returns the object when parameters are passed as a named tuple" do
tag = Tag.create!(name: "rust", is_active: true)
Tag.get("name = :name AND is_active = :active", {name: "rust", active: true}).should eq tag
end

it "returns nil when no record matches and parameters are passed as a named tuple" do
Tag.get("name = :name AND is_active = :active", {name: "nonexistent", active: false}).should be_nil
end

it "returns the object when parameters are passed as a hash" do
tag = Tag.create!(name: "python", is_active: true)
Tag.get("name = :name AND is_active = :active", {"name" => "python", "active" => true}).should eq tag
end

it "returns nil when no record matches and parameters are passed as a hash" do
Tag.get("name = :name AND is_active = :active", {"name" => "nonexistent", "active" => false}).should be_nil
end
end

describe "::get!" do
Expand Down Expand Up @@ -477,6 +531,72 @@ describe Marten::DB::Model::Querying do
it "makes use of the default queryset when using a block defining an advanced predicates expression" do
expect_raises(Marten::DB::Errors::RecordNotFound) { Tag.get! { q(name: "crystal") } }
end

it "returns the object using a raw SQL predicate" do
tag = Tag.create!(name: "elixir", is_active: true)
Tag.get!("name = 'elixir' AND is_active = true").should eq tag
end

it "raises RecordNotFound when no record matches" do
expect_raises(Marten::DB::Errors::RecordNotFound) do
Tag.get!("name = 'nonexistent' AND is_active = true")
end
end

it "returns the object using a raw SQL predicate with positional arguments" do
tag = Tag.create!(name: "elixir", is_active: true)
Tag.get!("name = ? AND is_active = ?", "elixir", true).should eq tag
end

it "raises RecordNotFound when no record matches with positional arguments" do
expect_raises(Marten::DB::Errors::RecordNotFound) do
Tag.get!("name = ? AND is_active = ?", "nonexistent", true)
end
end

it "returns the object using a raw SQL predicate with named arguments" do
tag = Tag.create!(name: "python", is_active: true)
Tag.get!("name = :name AND is_active = :active", name: "python", active: true).should eq tag
end

it "raises RecordNotFound when no record matches with named arguments" do
expect_raises(Marten::DB::Errors::RecordNotFound) do
Tag.get!("name = :name AND is_active = :active", name: "nonexistent", active: false)
end
end

it "returns the object when parameters are passed as an array" do
tag = Tag.create!(name: "elixir", is_active: true)
Tag.get!("name = ? AND is_active = ?", ["elixir", true]).should eq tag
end

it "raises RecordNotFound when no record matches and parameters are passed as an array" do
expect_raises(Marten::DB::Errors::RecordNotFound) do
Tag.get!("name = ? AND is_active = ?", ["nonexistent", true])
end
end

it "returns the object when parameters are passed as a named tuple" do
tag = Tag.create!(name: "rust", is_active: true)
Tag.get!("name = :name AND is_active = :active", {name: "rust", active: true}).should eq tag
end

it "raises RecordNotFound when no record matches and parameters are passed as a named tuple" do
expect_raises(Marten::DB::Errors::RecordNotFound) do
Tag.get!("name = :name AND is_active = :active", {name: "nonexistent", active: false})
end
end

it "returns the object when parameters are passed as a hash" do
tag = Tag.create!(name: "rust", is_active: true)
Tag.get!("name = :name AND is_active = :active", {"name" => "rust", "active" => true}).should eq tag
end

it "raises RecordNotFound when no record matches and parameters are passed as a hash" do
expect_raises(Marten::DB::Errors::RecordNotFound) do
Tag.get!("name = :name AND is_active = :active", {"name" => "nonexistent", "active" => false})
end
end
end

describe "::get_or_create" do
Expand Down
110 changes: 110 additions & 0 deletions src/marten/db/model/querying.cr
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,61 @@ module Marten
default_queryset.get(**kwargs)
end

# Returns a single model instance matching the given raw SQL condition.
# Returns `nil` if no record matches.
#
# Example:
# ```
# post = Post.get("is_published = true")
# ```
def get(raw_predicate : String)
default_queryset.get(raw_predicate)
end

# Returns a single model instance matching the given raw SQL condition with positional arguments.
# Returns `nil` if no record matches.
#
# Example:
# ```
# post = Post.get("name = ?", "crystal")
# ```
def get(raw_predicate : String, *args)
default_queryset.get(raw_predicate, *args)
end

# Returns a single model instance matching the given raw SQL condition with positional parameters.
# Returns `nil` if no record matches.
#
# Example:
# ```
# post = Post.get("name = ? AND is_published = ?", ["crystal", true])
# ```
def get(raw_predicate : String, params : Array)
default_queryset.get(raw_predicate, params)
end

# Returns a single model instance matching the given raw SQL condition with named parameters.
# Returns `nil` if no record matches.
#
# Example:
# ```
# post = Post.get("name = :name AND is_published = :published", name: "crystal", published: true)
# ```
def get(raw_predicate : String, **kwargs)
default_queryset.get(raw_predicate, **kwargs)
end

# Returns a single model instance matching the given raw SQL condition with a named parameters hash.
# Returns `nil` if no record matches.
#
# Example:
# ```
# post = Post.get("name = :name", {name: "crystal"})
# ```
def get(raw_predicate : String, params : Hash | NamedTuple)
default_queryset.get(raw_predicate, params)
end

# Returns the model instance matching a specific set of advanced filters.
#
# Model fields such as primary keys or fields with a unique constraint should be used here in order to
Expand Down Expand Up @@ -365,6 +420,61 @@ module Marten
default_queryset.get!(**kwargs)
end

# Returns a single model instance matching the given raw SQL condition.
# Raises a `RecordNotFound` exception if no record matches.
#
# Example:
# ```
# post = Post.get!("is_published = true")
# ```
def get!(raw_predicate : String)
default_queryset.get!(raw_predicate)
end

# Returns a single model instance matching the given raw SQL condition with positional arguments.
# Raises a `RecordNotFound` exception if no record matches.
#
# Example:
# ```
# post = Post.get!("name = ?", "crystal")
# ```
def get!(raw_predicate : String, *args)
default_queryset.get!(raw_predicate, *args)
end

# Returns a single model instance matching the given raw SQL condition with positional parameters.
# Raises a `RecordNotFound` exception if no record matches.
#
# Example:
# ```
# post = Post.get!("name = ? AND is_published = ?", ["crystal", true])
# ```
def get!(raw_predicate : String, params : Array)
default_queryset.get!(raw_predicate, params)
end

# Returns a single model instance matching the given raw SQL condition with named parameters.
# Raises a `RecordNotFound` exception if no record matches.
#
# Example:
# ```
# post = Post.get!("name = :name AND is_published = :published", name: "crystal", published: true)
# ```
def get!(raw_predicate : String, **kwargs)
default_queryset.get!(raw_predicate, **kwargs)
end

# Returns a single model instance matching the given raw SQL condition with a named parameters hash.
# Raises a `RecordNotFound` exception if no record matches.
#
# Example:
# ```
# post = Post.get!("name = :name", {name: "crystal"})
# ```
def get!(raw_predicate : String, params : Hash | NamedTuple)
default_queryset.get!(raw_predicate, params)
end

# Returns the model instance matching a specific set of advanced filters.
#
# Model fields such as primary keys or fields with a unique constraint should be used here in order to
Expand Down

0 comments on commit 7a83223

Please sign in to comment.