ecto_shortcuts alternatives and similar packages
Based on the "ORM and Datamapping" category.
Alternatively, view ecto_shortcuts alternatives based on common mentions on social networks and blogs.
-
paper_trail
Track and record all the changes in your database with Ecto. Revert back to anytime in history. -
ecto_psql_extras
Ecto PostgreSQL database performance insights. Locks, index usage, buffer cache hit ratios, vacuum stats and more.
CodeRabbit: AI Code Reviews for Developers

* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest.
Do you think we are missing an alternative of ecto_shortcuts or a related project?
README
EctoShortcuts 🚅
Lightweight Elixir extension to simplify common use cases in Ecto.
Installation
Get Hex
Add
ecto_shortcuts
to your list of dependencies inmix.exs
:
def deps do
[{:ecto_shortcuts, "~> 0.1.6"}]
end
Configuration
Add it to your Ecto Models
like:
defmodule MyApp.User do
...
use EctoShortcuts, repo: MyApp.Repo
...
end
or (to closely mirror Phoenix model standards):
defmodule MyApp.RepoAUsers do
...
use EctoShortcuts, repo: MyApp.RepoA, model: MyApp.User
...
end
defmodule MyApp.RepoBUsers do
...
use EctoShortcuts, repo: MyApp.RepoB, model: MyApp.User
...
end
Usage
insert
# create a new user named Bob
MyApp.User.insert name: "Bob"
MyApp.User.insert %{name: "Bob"}
# create a new user named Alice without validation
MyApp.User.insert name: "Alice", validate: false
MyApp.User.insert %{name: "Alice"}, %{validate: false}
insert!
MyApp.User.insert! name: "Bob"
MyApp.User.insert! %{name: "Bob"}
MyApp.User.insert! name: "Alice", validate: false
MyApp.User.insert! %{name: "Alice"}, %{validate: false}
--
note: If your model defines a changeset, insert
, insert!
& any validations will by default use that changeset. To disable validation, use the validate: false option shown below. If your model lacks a changeset, then your model will be inserted without any validation.
--
update_all
# set status_id to 3 on all users
MyApp.User.update_all set: [status_id: 3]
MyApp.User.update_all %{set: [status_id: 3]}
update_by
# set status_id to 4 where mode is 3
MyApp.User.update_by [mode: 3], set: [status_id: 4]
MyApp.User.update_by %{mode: 3}, %{set: [status_id: 4]}
update_by_returning
# set status_id to 4 where mode is 3
updated_users = MyApp.User.update_by_returning [mode: 3], set: [status_id: 4]
# set status_id to 3 for user 1 and return updated user with posts association preloaded
[updated_user] = MyApp.User.update_by_returning [id: 1], [set: [status_id: 3]], preload: [:posts]
# same as above but using maps
[updated_user] = MyApp.User.update_by_returning %{id: 1}, %{set: [status_id: 3]}, preload: [:posts]
delete_all
# delete all users
MyApp.User.delete_all
delete_by
# delete all users where mode is 3
MyApp.User.delete_by mode: 3
MyApp.User.delete_by %{mode: 3}
get
# get user with id 3
MyApp.User.get 3
# get user with id 3 and preload posts association
MyApp.User.get 3, preload: [:posts]
# get user with id 3 and preload posts associations in addition to posts.post_type association
MyApp.User.get 3, preload: [{:posts, :post_type}]
get!
MyApp.User.get! 3
MyApp.User.get! 3, preload: [:posts]
MyApp.User.get! 3, preload: [{:posts, :post_type}]
get_by
# fetch a single user where name is Sally and age is 30
MyApp.User.get_by name: "Sally", age: 30
# fetch a single user where name is Sally and preload the posts association
MyApp.User.get_by [name: "Sally"], preload: [:posts]
# same as above but using maps
MyApp.User.get_by %{name: "Sally"}, preload: [:posts]
get_by!
MyApp.User.get_by! name: "Sally", age: 30
MyApp.User.get_by! [name: "Sally", age: 30], preload: [:posts]
where
# get all users where status is 3
MyApp.User.where status: 3
# get all users where status is 3 and limit to 10 ordering by created_at
MyApp.User.where [status: 3], limit: 10, order_by: [desc: :created_at]
# same as above but using maps
MyApp.User.where %{status: 3}, %{limit: 10, order_by: [desc: :created_at]}
# same as above but preload the posts association
MyApp.User.where [status: 3], limit: 10, order_by: [desc: :inserted_at], preload: [:posts]
get_or_insert
# get user with name John Smith or insert if user does not exist
MyApp.User.get_or_insert first_name: "John", last_name: "Smith"
MyApp.User.get_or_insert %{first_name: "John", last_name: "Smith"}
get_or_insert!
MyApp.User.get_or_insert! first_name: "John", last_name: "Smith"
first
# get first user
MyApp.User.first
# get first user preloading the posts association
MyApp.User.first preload: [:posts]
all
# get all users
MyApp.User.all
# get all users preloading the posts association
MyApp.User.all preload: [:posts]
count
# get count of all users
MyApp.User.count
count_where
# get count of all users where status is 4
MyApp.User.count_where status_id: 4
MyApp.User.count_where %{status_id: 4}
Wilcard Preloads
You can preload all associations via a wildcard, do
MyApp.User.get 3, preload: "*"
or
MyApp.User.get 3, preload: :*
Default Preloads
You can set a default set of preloads.
defmodule MyApp.Users do
...
use EctoShortcuts, repo: MyApp.Repo,
model: MyApp.User,
default_preload: [:friends, :user_status, :posts]
...
end
or using wildcards
defmodule MyApp.Users do
...
use EctoShortcuts, repo: MyApp.Repo,
model: MyApp.User,
default_preload: "*"
...
end
If you want to override defaults, pass in specific preloads.
Running Tests
To run tests:
mysql
must be running, then- create a database you want tests to run on &
configure
/config.exs
. This creates database calledecto_shortcuts_test
with the usernameroot
and passwordroot
. The default ismysql port 3306
.Run your test.
mix test
Coming Soon:
- support for greater & less than comparisons
- support for basic joins
NOTE: Ecto's DSL is rich & flexible. It should be deferred to for anything complex. 🙌