Awesome
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. 🙌