あなたが複数の場所でこのような機能を使用する場合は、MyApp.Repo
で、このための関数を定義することができます(場合そうでない場合は、このコードを使用したいコントローラーにコピーしてください)。 lib/my_app/repo.ex
でMyApp.Repo
モジュールに以下を追加します。その後
def get_or_insert(schema, params) do
case get_by(schema, params) do
nil -> insert(schema.changeset(schema.__struct__, params))
struct -> {:ok, struct}
end
end
を、あなたはMyApp.Repo.get_or_insert(MyItem, %{var1: "some value"})
を行い、バック{:ok, %MyItem{...}}
または{:error, %Ecto.Changeset{}}
得ることができます。
デモ:
iex(1)> Repo.all Post
[debug] QUERY OK db=1.2ms
SELECT p0."id", p0."title", p0."inserted_at", p0."updated_at" FROM "posts" AS p0 []
[]
iex(2)> Repo.get_or_insert Post, %{title: "foo"}
[debug] QUERY OK db=1.8ms queue=0.1ms
SELECT p0."id", p0."title", p0."inserted_at", p0."updated_at" FROM "posts" AS p0 WHERE (p0."title" = $1) ["foo"]
[debug] QUERY OK db=8.5ms
INSERT INTO "posts" ("title","inserted_at","updated_at") VALUES ($1,$2,$3) RETURNING "id" ["foo", {{2016, 9, 7}, {10, 6, 52, 0}}, {{2016, 9, 7}, {10, 6, 52, 0}}]
{:ok,
%MyApp.Post{__meta__: #Ecto.Schema.Metadata<:loaded, "posts">, id: 1,
inserted_at: #Ecto.DateTime<2016-09-07 10:06:52>, title: "foo",
updated_at: #Ecto.DateTime<2016-09-07 10:06:52>}}
iex(3)> Repo.get_or_insert Post, %{title: "foo"}
[debug] QUERY OK db=1.8ms decode=2.6ms
SELECT p0."id", p0."title", p0."inserted_at", p0."updated_at" FROM "posts" AS p0 WHERE (p0."title" = $1) ["foo"]
{:ok,
%MyApp.Post{__meta__: #Ecto.Schema.Metadata<:loaded, "posts">, id: 1,
inserted_at: #Ecto.DateTime<2016-09-07 10:06:52>, title: "foo",
updated_at: #Ecto.DateTime<2016-09-07 10:06:52>}}
iex(4)> Repo.get_or_insert Post, %{title: "bar"}
[debug] QUERY OK db=2.0ms
SELECT p0."id", p0."title", p0."inserted_at", p0."updated_at" FROM "posts" AS p0 WHERE (p0."title" = $1) ["bar"]
[debug] QUERY OK db=8.0ms
INSERT INTO "posts" ("title","inserted_at","updated_at") VALUES ($1,$2,$3) RETURNING "id" ["bar", {{2016, 9, 7}, {10, 6, 59, 0}}, {{2016, 9, 7}, {10, 6, 59, 0}}]
{:ok,
%MyApp.Post{__meta__: #Ecto.Schema.Metadata<:loaded, "posts">, id: 2,
inserted_at: #Ecto.DateTime<2016-09-07 10:06:59>, title: "bar",
updated_at: #Ecto.DateTime<2016-09-07 10:06:59>}}
iex(5)> Repo.get_or_insert Post, %{title: "bar"}
[debug] QUERY OK db=2.2ms
SELECT p0."id", p0."title", p0."inserted_at", p0."updated_at" FROM "posts" AS p0 WHERE (p0."title" = $1) ["bar"]
{:ok,
%MyApp.Post{__meta__: #Ecto.Schema.Metadata<:loaded, "posts">, id: 2,
inserted_at: #Ecto.DateTime<2016-09-07 10:06:59>, title: "bar",
updated_at: #Ecto.DateTime<2016-09-07 10:06:59>}}
あなたはおそらく1が常に一致しますitem'または他の '' item'上 'nil'句を移動したいです。 – Dogbert