{"id":13508809,"url":"https://github.com/MishaConway/ecto_shortcuts","last_synced_at":"2025-03-30T11:32:51.806Z","repository":{"id":57493654,"uuid":"67090763","full_name":"MishaConway/ecto_shortcuts","owner":"MishaConway","description":"Shortcuts for common operations in ecto","archived":false,"fork":false,"pushed_at":"2016-09-28T20:06:48.000Z","size":31,"stargazers_count":29,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-11-01T08:33:57.503Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MishaConway.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-09-01T02:27:18.000Z","updated_at":"2023-09-08T17:14:18.000Z","dependencies_parsed_at":"2022-08-28T16:42:04.024Z","dependency_job_id":null,"html_url":"https://github.com/MishaConway/ecto_shortcuts","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MishaConway%2Fecto_shortcuts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MishaConway%2Fecto_shortcuts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MishaConway%2Fecto_shortcuts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MishaConway%2Fecto_shortcuts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MishaConway","download_url":"https://codeload.github.com/MishaConway/ecto_shortcuts/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246314012,"owners_count":20757453,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T02:00:58.756Z","updated_at":"2025-03-30T11:32:51.439Z","avatar_url":"https://github.com/MishaConway.png","language":"Elixir","funding_links":[],"categories":["ORM and Datamapping"],"sub_categories":[],"readme":"# EctoShortcuts 🚅\n\n\u003e Lightweight Elixir extension to simplify common use cases in Ecto.\n\n## Installation\n\n1. Get [Hex](https://hex.pm/packages/ecto_shortcuts)\n\n2. Add `ecto_shortcuts` to your list of dependencies in `mix.exs`:\n\n```elixir\n  def deps do\n    [{:ecto_shortcuts, \"~\u003e 0.1.6\"}]\n  end\n```\n\n## Configuration   \n\nAdd it to your `Ecto Models` like:\n\n```elixir\ndefmodule MyApp.User do\n  ...\n  use EctoShortcuts, repo: MyApp.Repo\n  ...\nend  \n```\nor (to closely mirror Phoenix model standards): \n\n```elixir\ndefmodule MyApp.RepoAUsers do\n  ...\n  use EctoShortcuts, repo: MyApp.RepoA, model: MyApp.User\n  ...\nend\n\ndefmodule MyApp.RepoBUsers do\n  ...\n  use EctoShortcuts, repo: MyApp.RepoB, model: MyApp.User\n  ...\nend  \n```\n## Usage\n\n\n**insert**\n```elixir\n  # create a new user named Bob\n  MyApp.User.insert name: \"Bob\"\n  MyApp.User.insert %{name: \"Bob\"}\n\n  # create a new user named Alice without validation\n  MyApp.User.insert name: \"Alice\", validate: false\n  MyApp.User.insert %{name: \"Alice\"}, %{validate: false}\n```\n\n**insert!**\n```elixir\n  MyApp.User.insert! name: \"Bob\"\n  MyApp.User.insert! %{name: \"Bob\"}\n\n  MyApp.User.insert! name: \"Alice\", validate: false\n  MyApp.User.insert! %{name: \"Alice\"}, %{validate: false}\n```\n--\n**note:** If your model defines a changeset, `insert`, `insert!` \u0026 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.\n\n--\n\n**update_all**\n```elixir\n  # set status_id to 3 on all users\n  MyApp.User.update_all set: [status_id: 3]\n  MyApp.User.update_all %{set: [status_id: 3]}\n```\n\n**update_by**\n```elixir\n  # set status_id to 4 where mode is 3\n  MyApp.User.update_by [mode: 3], set: [status_id: 4]\n  MyApp.User.update_by %{mode: 3}, %{set: [status_id: 4]}\n```\n\n**update\\_by\\_returning**\n```elixir\n  # set status_id to 4 where mode is 3\n  updated_users = MyApp.User.update_by_returning [mode: 3], set: [status_id: 4]\n\n  # set status_id to 3 for user 1 and return updated user with posts association preloaded\n  [updated_user] = MyApp.User.update_by_returning [id: 1], [set: [status_id: 3]], preload: [:posts]\n\n  # same as above but using maps\n  [updated_user] = MyApp.User.update_by_returning %{id: 1}, %{set: [status_id: 3]}, preload: [:posts]\n```\n\n**delete_all**\n```elixir\n  # delete all users\n  MyApp.User.delete_all\n```\n\n**delete_by**\n```elixir\n  # delete all users where mode is 3\n  MyApp.User.delete_by mode: 3\n  MyApp.User.delete_by %{mode: 3}\n```\n\n**get**\n```elixir\n  # get user with id 3\n  MyApp.User.get 3\n\n  # get user with id 3 and preload posts association\n  MyApp.User.get 3, preload: [:posts]\n\n  # get user with id 3 and preload posts associations in addition to posts.post_type association\n  MyApp.User.get 3, preload: [{:posts, :post_type}]\n```\n\n**get!**\n```elixir\n  MyApp.User.get! 3\n  MyApp.User.get! 3, preload: [:posts]\n  MyApp.User.get! 3, preload: [{:posts, :post_type}]\n```\n\n**get_by**\n```elixir\n  # fetch a single user where name is Sally and age is 30\n  MyApp.User.get_by name: \"Sally\", age: 30\n\n  # fetch a single user where name is Sally and preload the posts association\n  MyApp.User.get_by [name: \"Sally\"],  preload: [:posts]\n\n  # same as above but using maps\n  MyApp.User.get_by %{name: \"Sally\"},  preload: [:posts]\n```\n\n**get_by!**\n```elixir\n  MyApp.User.get_by! name: \"Sally\", age: 30\n  MyApp.User.get_by! [name: \"Sally\", age: 30],  preload: [:posts]\n```\n\n**where**\n```elixir\n  # get all users where status is 3\n  MyApp.User.where status: 3\n\n  # get all users where status is 3 and limit to 10 ordering by created_at\n  MyApp.User.where [status: 3], limit: 10, order_by: [desc: :created_at]\n\n  # same as above but using maps\n  MyApp.User.where %{status: 3}, %{limit: 10, order_by: [desc: :created_at]}\n\n  # same as above but preload the posts association\n  MyApp.User.where [status: 3],  limit: 10, order_by: [desc: :inserted_at], preload: [:posts]\n```\n\n**get\\_or\\_insert**\n```elixir\n  # get user with name John Smith or insert if user does not exist\n  MyApp.User.get_or_insert first_name: \"John\", last_name: \"Smith\"\n\n  MyApp.User.get_or_insert %{first_name: \"John\", last_name: \"Smith\"}\n```\n\n**get\\_or\\_insert!**\n```elixir\n  MyApp.User.get_or_insert! first_name: \"John\", last_name: \"Smith\"\n```\n\n**first**\n```elixir\n  # get first user\n  MyApp.User.first\n\n  # get first user preloading the posts association\n  MyApp.User.first preload: [:posts]\n```\n\n**all**\n```elixir\n  # get all users\n  MyApp.User.all\n\n  # get all users preloading the posts association\n  MyApp.User.all preload: [:posts]\n```\n\n**count**\n```elixir\n  # get count of all users\n  MyApp.User.count\n```\n\n**count_where**\n```elixir\n  # get count of all users where status is 4\n  MyApp.User.count_where status_id: 4\n\n  MyApp.User.count_where %{status_id: 4}\n```\n\n## Wilcard Preloads\n\nYou can preload all associations via a wildcard, do\n\n```elixir\n  MyApp.User.get 3, preload: \"*\"\n```\n\nor\n\n```elixir\n  MyApp.User.get 3, preload: :*\n```\n\n## Default Preloads\n\nYou can set a default set of preloads.\n\n```elixir\ndefmodule MyApp.Users do\n  ...\n  use EctoShortcuts, repo: MyApp.Repo,\n                     model: MyApp.User,\n                     default_preload: [:friends, :user_status, :posts]\n  ...\nend\n```\nor using wildcards\n```elixir\ndefmodule MyApp.Users do\n  ...\n  use EctoShortcuts, repo: MyApp.Repo,\n                     model: MyApp.User,\n                     default_preload: \"*\"\n  ...\nend\n```\n\nIf you want to override defaults, pass in specific preloads.\n\n\n## Running Tests\n\nTo run tests:\n\n- `mysql` must be running, then\n- create a database you want tests to run on \u0026\n- configure `/config.exs`. This creates database called `ecto_shortcuts_test` with the username `root` and password `root`.  The default is `mysql port 3306`.\n\n- Run your test. `mix test`\n\n\n### Coming Soon:\n * support for greater \u0026 less than comparisons\n * support for basic joins\n \nNOTE: Ecto's DSL is rich \u0026 flexible. It should be deferred to for anything complex. 🙌\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMishaConway%2Fecto_shortcuts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FMishaConway%2Fecto_shortcuts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMishaConway%2Fecto_shortcuts/lists"}