2016-06-10 4 views
6

필자는 Phoenix/Elixir에 대해 처음으로 접해 왔으며 변경 세트를 감추려 고 노력 중입니다.Ecto changeset를 repo에 삽입하기 전에이를 어떻게 수정합니까?

나는 모델을 만들거나 업데이트하는 데 사용되는 일련의 변경 사항을 보유하고 있음을 이해합니다.

내가 알고 싶은 것은 데이터베이스로 푸시하기 전에 변경 사항을 수정할 수 있는지 여부입니다.

  • 난 사람들이 데이터베이스에 새로운 아티스트를 만들 수 있도록 양식을 가지고 :

    내 사용 사례는 다음과 같다.

  • 이 양식에는 특수 필드가 있습니다.
  • 작가를 만들기 전에, 나는 인해 변하지 제약에 직접 변경 집합을 수정하여 그 해 드리겠습니다 모르겠어요 문자열

의 배열로 저장하기 ","로 전문 분야를 분할 할 하지만 repo에 삽입 할 다른 changeset을 만들 수도 있습니다.

모든 제안은 환영하며, 내가하는 일은 좋지 않거나 어리석은 행위를 가리 키기를 망설이지 않습니다! 코멘트 다음

편집 : 내가 좋아하는 뭔가를 찾고 있어요 :

defp put_specialty_array(changeset) do 
    case changeset do 
    %Ecto.Changeset{valid?: true, changes: %{specialty: spec}} -> 
     put_change(changeset, :specialty, String.split(spec, ",")) 
    _ -> 
     changeset 
    end 
end 
+0

이것은 사용자 암호를 해싱하고 저장하는 것과 유사한 접근 방식입니다. [ "Programming Phoenix"(https://pragprog.com/book/phoenix/programming-phoenix)가 어떻게했는지 확인하십시오. [https://media.pragprog.com/titles/phoenix/code/authentication/listings] /rumbl/web/models/user.change1.ex). defp의 put_specialty_array (변경 집합) %의 Ecto.Changeset {유효한? 사실, 변경을 변경 집합 케이스를 수행합니다 : %를 {전문 : 사양 – AbM

+0

그래서 내가 뭔가를 할 수 있습니다 (특히 방법'registration_changeset'이 put_pass_hash''호출) }} -> put_change (변경 집합, : specialty, String.split (spec, ",")) 변경 집합 끝 끝 ? – Cratein

+0

당신의 제안을 조금 수정했습니다 – AbM

답변

9

내가 당신을 위해 무엇을 찾고있는 것은 사용자 정의 Ecto.Type 믿습니다. 나는 항상 이것을하고, 그것은 위대한 일을한다! 그것은 다음과 같이 보일 것입니다 :

defmodule MyApp.Tags do 
    @behaviour Ecto.Type 
    def type, do: {:array, :string} 
    def cast(nil), do: {:ok, nil} # if nil is valid to you 
    def cast(arr) when is_list(arr) do 
    if Enum.all?(arr, &String.valid?/1), do: {:ok, arr}, else: :error 
    end 
    def cast(str) when is_binary(str), do: {:ok, String.split(",")} 
    def cast(_), do: :error 

    def dump(val) when is_list(val), do: {:ok, val} 
    def dump(_), do: :error 
    def load(val) when is_list(val), do: {:ok, val} 
    def load(_), do: :error 
end 

그런 다음 마이그레이션에 마지막으로 스키마에서 만든 필드 유형을 지정 권리 유형

add :tags, {:array, :string} 

에 열을 추가합니다.

field :tags, MyApp.Tags 

그러면 변경 세트의 필드로 추가 할 수 있습니다. 형식 변환이 :error을 반환하면 변경 집합에 {:tags, ["is invalid"]}과 같은 오류가 발생합니다. 모델 또는 컨트롤러의 필드 처리에 대해 걱정할 필요가 없습니다. 사용자가 값에 대한 문자열 배열이나 쉼표로 구분 된 문자열을 게시하면 제대로 작동합니다. 다른 형식으로 데이터베이스에 값을 저장해야하는 경우

, 당신은 단지 def type의 반환 값을 변경하고 def dump는 해당 유형의 값을 반환하는 것을 보장하고 def load는 해당 유형의 값을 읽을 수 있습니다 무엇 이건 원하는 내부 표현. 한 가지 공통적 인 패턴은 내부 표현에 대한 구조체를 정의하여 단순 문자열을 반환 할 수있는 Poison의 to_json을 직접 구현할 수 있도록하는 것입니다. 한 예는 json의 12.12345N,123.12345W으로 인코딩 된 LatLng 유형이고, postgres에 일부 GIS 유형으로 저장하지만 %LatLng{lat: 12.12345, lng: -123.12345}과 같은 구조로되어있어 연상 기호에서 간단한 수학을 수행 할 수 있습니다. DateTime 형식은 이와 비슷하게 작동합니다 (엘렉서 용 구조체, db 드라이버 용 튜플 형식 및 json 용 ISO 형식).

암호 필드, btw에 대해이 기능이 잘 작동한다고 생각합니다.JSON 표현을 스쿼시하거나, 구조체를 사용하여 알고리즘을 표현하거나, 알고리즘에 매개 변수를 해시와 다른 소금과 다른 것으로 쉽게 사용할 수 있습니다. 코드에서 비밀번호를 업데이트하려면 Ecto.Changeset.change(user, password: "changeme")이어야합니다.

나는 이것이 6mo의 오래된 질문이며 아마도 당신이 뭔가를 발견했음을 알고 있지만, 나는 구글 검색에서 끝나고, 다른 사람들도 역시 그렇게한다고 가정한다.

+0

현재 사용자의 컨텍스트 데이터를 사용자 정의 필드에 삽입하는 방법이 있는지 알고 있습니까? 사용자의 암호 구를 사용하여 필드를 암호화/암호 해독하고 사용자 정의 필드에서 키를 참조해야하는 경우를 가정 해보십시오. –