All Projects → codeanpeace → ecto_conditionals

codeanpeace / ecto_conditionals

Licence: GPL-3.0 license
EctoConditionals implements a flexibly functional find_or_create and upsert behavior for Ecto models.

Programming Languages

elixir
2628 projects

Projects that are alternatives of or similar to ecto conditionals

strong migrations
Catch unsafe migrations in your Elixir application
Stars: ✭ 58 (+241.18%)
Mutual labels:  ecto
ecto trail
EctoTrail allows to store Ecto changeset changes in a separate audit_log table.
Stars: ✭ 51 (+200%)
Mutual labels:  ecto
hierarch
Tree structure & hierarchy for ecto models with ltree(Postgres)
Stars: ✭ 30 (+76.47%)
Mutual labels:  ecto
phoenix pagination
Simple pagination for Ecto and Phoenix that uses plain EEx templates.
Stars: ✭ 20 (+17.65%)
Mutual labels:  ecto
ectograph
Ectograph is a set of utility functions for using Ecto in combination with graphql-elixir/graphql
Stars: ✭ 29 (+70.59%)
Mutual labels:  ecto
monetized
A lightweight solution for handling and storing money.
Stars: ✭ 46 (+170.59%)
Mutual labels:  ecto
query builder
Compose Ecto queries without effort
Stars: ✭ 56 (+229.41%)
Mutual labels:  ecto
exposed-upsert
Upsert DSL extension for Exposed, Kotlin SQL framework
Stars: ✭ 21 (+23.53%)
Mutual labels:  upsert
mongodb ecto
MongoDB adapter for Ecto
Stars: ✭ 348 (+1947.06%)
Mutual labels:  ecto
slonik-utilities
Utilities for manipulating data in PostgreSQL database using Slonik.
Stars: ✭ 22 (+29.41%)
Mutual labels:  upsert
querie
Compose Ecto query from the client side
Stars: ✭ 20 (+17.65%)
Mutual labels:  ecto
music db
A playground for Ecto using a simple music database
Stars: ✭ 29 (+70.59%)
Mutual labels:  ecto
elixir-revisionair ecto
A Revisionair adapter based on Ecto. Allows you to persist and keep track of revisions of your data structures in any of Ecto's supported databases.
Stars: ✭ 18 (+5.88%)
Mutual labels:  ecto
algoliax
Algolia integration to elixir application
Stars: ✭ 38 (+123.53%)
Mutual labels:  ecto
exqlite
An SQLite3 driver for Elixir
Stars: ✭ 128 (+652.94%)
Mutual labels:  ecto
ex operation
A library for making domain operations in Elixir
Stars: ✭ 33 (+94.12%)
Mutual labels:  ecto
contextual
🌈 Generate your Ecto contexts using this macro and eliminate boilerplate
Stars: ✭ 18 (+5.88%)
Mutual labels:  ecto
ecto commons
Ecto common validators for Date, Time, URLs, Emails, PostalCodes, Phone Numbers, Luhn checks, etc.
Stars: ✭ 33 (+94.12%)
Mutual labels:  ecto
guardian trackable
A Guardian hook to track user sign ins.
Stars: ✭ 25 (+47.06%)
Mutual labels:  ecto
ecto nested changeset
Helpers for manipulating nested Ecto changesets
Stars: ✭ 23 (+35.29%)
Mutual labels:  ecto

EctoConditionals

EctoConditionals implements a flexibly functional find_or_create and upsert behavior for Ecto models.

Installation

The package can be installed by adding ecto_conditionals in mix.exs:

def deps do
  [{:ecto_conditionals, "~> 0.1.0"}]
end

This package is available in Hex here,

Basic Usage

First specify the repo you're going to use:

use EctoConditionals, repo: MyApp.Repo

Then, pipe or pass the record struct to find_or_create/1 or upsert/1. These functions assume finding by id to determine whether to create or upsert. If an id field is present in the record struct, the id field will be used as the unique selector to determine whether to find, insert, or update. If not present, these functions will insert a new record.

%User{id: 1, name: "Flamel"} |> find_or_create
#=> {:ok, %User{id: 1, name: "Flamel"}}

%User{name: "Dumbledore"} |> upsert
#=> {:ok, %User{id: 2, name: "Dumbledore"}}

You can also specify selectors by instead using find_or_create_by/2 or upsert_by/2 and passing a selector or list of selectors as the second argument.

%User{name: "Slughorn"} |> find_or_create_by(:name)
#=> {:ok, %User{id: 3, name: "Slughorn"}}

%User{first_name: "Harry", last_name: "Potter"} |> upsert_by(:last_name)
#=> {:ok, %User{id: 4, first_name: "Harry", last_name: "Potter"}}

Implementation Note

find_or_create_by/2 is a thin wrapper piping through find_by/2 and then or_create/1 upsert_by/2 is a thin wrapper piping through find_by/2 and then update_or_insert/1. find_or_create/1 is a thin wrapper piping through find/1 and then or_create/1 and upsert/1 is a thin wrapper piping through find/1 and Ecto.Repo's insert_or_update/1. find/1 is also just a thin wrapper around find_by/1 that assumes :id is the selector. It's functions all the way down!

%User{first_name: "Harry", last_name: "Potter"} |> find_by([:first_name, :last_name])
#=> {:found, %User{id: 4, first_name: "Harry", last_name: "Potter"}}

%User{name: "Buckbeak"} |> find_by(:name)
#=> {:not_found, %User{name: "Buckbeak"}}

# the following is equivalent
%User{id: 1} |> find_by(:id)
%User{id: 1} |> find

Pro Tips

Individual functions are very flexible when used independently. For example, try pairing Elixir's with construct with find_by/2, which returns pattern match friendly tagged tuples such as {:found, record_struct} or {:not_found, record_struct}. These conditional helper functions also play well with Ecto.Multi.

Common Gotchas

An Ecto.MultipleResultsError means your selector or list of selectors does not uniquely identify a record aka it is not sufficiently specific.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].