2016-09-07 15 views
1

エンティティを見つけたり、見つからない場合は挿入します。現在、私はこのようにしています:チェンジセットが無効な場合は、検索または挿入し、チェンジセットが無効な場合はエラーを返します。

my_item = Repo.get_by(MyItem, var1: "some value") || Repo.insert!(MyItem.changeset(%MyItem{}, %{"var1" => var1})) 

もっと良い方法がありますか?チェンジセットが無効な場合はエラーを返すようにしたいが、現在このコードはそれを行っていない。

答えて

1

このお試しください:いくつかの値を挿入し

item = case Repo.get_by(MyItem, var1: "some value") do 
     nil -> insert_item("some_value") 
     item -> item 
end 

を:

defp insert_item(params) do 
    case Repo.insert(MyItem.changeset(%MyItem{}, %{"var1" => params})) do 
     {:ok, item} -> item 
     {:error, changeset} -> IO.inspect changeset.errors 
    end 
    end 
+1

あなたはおそらく1が常に一致しますitem'または他の '' item'上 'nil'句を移動したいです。 – Dogbert

2

あなたが複数の場所でこのような機能を使用する場合は、MyApp.Repoで、このための関数を定義することができます(場合そうでない場合は、このコードを使用したいコントローラーにコピーしてください)。 lib/my_app/repo.exMyApp.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>}} 
+0

私の解決策は '||'で間違っていますか? – Johshi

関連する問題