2016-08-30 2 views
2

특히 제약 조건 오류를 처리 내가 필드 중 하나에 고유 제한 조건이있는 변경 집합이 다음 컨트롤러 중 하나에서피닉스

defmodule Oauth.Shop do 
    use Ecto.Model 
    import Ecto.Changeset 
    alias Ecto.Changeset 

    schema "shops" do 
    field :shop, :string 
    field :access_token, :string 
    field :scope, :string 
    field :active, :boolean 
    timestamps 
    end 

    def changeset(shop, params \\ %{}) do 
    shop 
    |> cast(params, [:shop, :access_token, :scope, :active]) 
    |> Changeset.validate_required([:shop, :access_token, :scope, :active]) 
    |> unique_constraint(:shop) 
    end 
end 

을, 나는 새로운 가게를 삽입합니다. 중복 상점이 만들어지는 경우, 예외가 발생합니다 : 변수하면서, % 숍이 구조체는 것을

def save_shop({:ok, access_params}, shop) do 
    Repo.insert(%Shop{shop: shop, access_token: access_params.access_token, scope: access_params.scope}) 
    hook_uninstall(shop, access_params.access_token) 
    {:ok} 
    end 

참고 : 여기에

** (exit) an exception was raised: 
    ** (Ecto.ConstraintError) constraint error when attempting to insert model: 

    * unique: shops_shop_index 

내가 레코드를 저장하는 코드입니다 shop은 쿼리 문자열 매개 변수의 값입니다.

Ecto.ConstraintError에 대한 플러그를 만들 수는 있지만 자세한 사용자 피드백에 필요한 세분화 된 컨트롤이 제공되지 않는다고 생각합니다.

예외를 포착하고 상점이 이미 등록되었다는 것을 사용자에게 알리는 좋은 방법은 무엇입니까?

+1

어떻게 데이터베이스에 삽입하나요? 'Repo.insert!'또는'Repo.insert'를 사용하고 있습니까? [docs] (https://hexdocs.pm/ecto/Ecto.Changeset.html#unique_constraint/3)에 따르면 후자는 쉽게 패턴 매치가 가능한 두 개의 튜플'{: error, changeset}'을 반환해야하기 때문에 on –

+0

구조체가 아닌'Repo.insert'에'Changeset'을 전달하고 있습니까? – Dogbert

+0

@Dogbert 외. . . Repo.insert()를 포함하도록 질문이 업데이트되었습니다. – sheldonkreger

답변

2

당신은 통과하는 데 필요한 Ecto.ChangesetShop 당신은 어떤 효과가 그 함수에서 정의 된 검증 및 unique_constraint 원하는 구조체를 직접하는 경우 Shop.changeset/2Repo.insert에하지에 의해 반환. 또한 오류 케이스를 처리하기 위해 패턴 일치를 사용해야합니다.

def save_shop({:ok, access_params}, shop) do 
    case Repo.insert(Shop.changeset(%Shop{}, %{shop: shop, access_token: access_params.access_token, scope: access_params.scope})) do 
    {:ok, _} -> 
     hook_uninstall(shop, access_params.access_token) 
     {:ok} 
    {:error, changeset} -> 
     # Put whatever value you want to return in case of an error here. 
     # You can get more details about the error using `changeset.errors`. 
     {:error} 
    end 
end 

은 (내가 삽입이 성공하면 당신은 단지 hook_uninstall를 실행하려는 가정했습니다. 그런 경우는 다른 지점에 그 라인을 복사하거나 case 외부로 이동할 수 있습니다 아니라면.)

가능한 한 패턴 일치를 사용하는 것이 더 이상적입니다. .field을 사용하여지도 필드에 액세스하는 대신

def save_shop({:ok, %{access_token: access_token, scope: scope}}, shop) do 
    case Repo.insert(Shop.changeset(%Shop{}, %{shop: shop, access_token: access_token, scope: scope})) do 
    {:ok, _} -> 
     hook_uninstall(shop, access_token) 
     {:ok} 
    {:error, changeset} -> 
     # Put whatever value you want to return in case of an error here. 
     # You can get more details about the error using `changeset.errors`. 
     {:error} 
    end 
end 
+0

어떻게 작동하는지 알 수 있습니다. 두 번째 예제에서는 Typo, 두 번째 줄은 누락 된 닫는 괄호입니다. 솔루션 및 관용적 구현을 ​​도와 주셔서 감사합니다. 나는 아직도 오래된 습관을 깨고 있으며 패턴 매칭에 대해 상기시켜야한다. – sheldonkreger

+1

오타가 수정되었습니다. 기꺼이 도와 줬어! 패턴 매칭은 익숙해지기까지 약간의 시간이 걸릴 수 있지만, 패턴 매칭없이 언어를 사용해야 할 때마다 패턴 매칭을 놓칠 수 있습니다. – Dogbert

관련 문제