Parse và validate request param tong Phoenix với Ecto

9004 단어 elixirphoenixecto
Khi viết các API hoặc cả các endpoint thì thông thường chúng ta sẽ có một số nhu cầu:
  • Chỉ cho phép một số các tham số xác định được truyền vào.
  • Chuyển các tham số về kiểu dữ liệu mong muốn
  • các tham số theo yêu cầu 확인

  • Bài viết này sẽ hướng dẫn các bạn giải quyết các vấn đề trên sử dụng Ecto.Changeset
    Thư viện Ecto đã cung cấp sẵn cho chúng ta module Changeset . nó hỗ trợ việc 캐스트 các tham số v ề w thüng kiểu d ữ liệu mong muốn, nó cũng hỗ tr ợ các phương thức ³ comate các tham yêu cầu, và nó cũng chop phép bạn giới h th th th th th th th th th th th th than

    Và sau đây là một ví dụ sử dụng Chageset để 유효성 검증 các tham số khi 필터 các đơn hàng.

    1. Đầu tiên bạn phải định nghĩa một schema




    defmodule MyApp.OrderFilterParams do
        use Ecto.Schema
        import Ecto.Changeset
    
        schema "order_filter_params" do
            field :keyword, :string
            field :category_id,  :integer
            field :status, :string
            field :start_date, :utc_datetime
            field :end_date, :utc_datetime
        end
    end
    


    2. 캐스트 và 유효성 검사



    Sau đó phải định nghĩa một hàm để thực hiện việc cast tham số và validate changeset .

    defmodule MyApp.OrderFilterParams do
    
        ...
    
        @required ~w(category_id start_date)
        @optional ~w(keyword status end_date)
    
        def changeset(changeset_or_model, params) do
             cast(changeset_or_model, params, @required ++ @optional)
            |> validate_required(@required)
        end
    end
    


    3. giá trị 기본값 động 설정



    nếu b ốn muạn sử d ụng các giá tr ị default động, ví d ụ như mặc ³nh ngày kết thúc là ngày hi tại, các bạn phải ³nh nghĩa một fortment 탠 set giá tr tr t t t t t t t t t t t t tome mu t.

    defmodule MyApp.OrderFilterParams do
    
        ...
    
        def changeset(changeset_or_model, params) do
             cast(changeset_or_model, params, @required ++ @optional)
            |> validate_required(@required)
            |> set_default_end_date()
        end
    
        defp set_defaut_end_date(changeset) do
            end_date = get_change(changeset, :end_date)
            if is_nil(end_date) do
                put_change(changeset, :end_date, Timex.today())
            else
                changeset
            end
        end
    end
    


    4. Sử dụng Params 스키마




    defmodule MyApp.OrderController do
        use MyApp, :controller
        alias MyApp.OrderFilterParams
    
        def index(conn, params) do
            changeset = OrderFilterParams.changeset(%OrderFilterParams{}, params)
    
            if changeset.valid? do
                strong_params = Ecto.Changeset.apply_changes(changeset)
                    IO.put(strong_params.keyword)
                # Do something with your params
            else
                # handle error
            end
        end
    end
    
    


    Rất đơn giản đúng không, nếu bạn đã sử dụng Ecto thì việc này chỉ là ruồi muỗi. Tuy nhiên đơn giản thì phải có thứ đánh đổi chứ.

    Vài thứ mà bạn sẽ thấy bất tiện



    1. Lượng 코드 mà bạn phải viết quá nhiều.



    Thử tưởng tượng mỗi API bạn lại phải định nghĩa têm một Module params cho nó thì phức tạp vl.

    Bạn có thể sử dụng schemaless, nhưng mà function của bạn sẽ rối nùi lên vì code logic và code xử lý params nó không liên quan Và bạn thì kiểu như đổ sting vào cơm để ăn vậy.

    2. Thiếu linh hoạt.



    Điều này cũng đúng vì mục đích chính của Ecto là phục vụ cho việc định nghĩa các schema cho 데이터베이스.

    Đơn giản như việc định nghĩa giá trị default động như trên, bạn phải viết luôn 1 hàm mới

    Tuy nhiên nó cũng có một ưu điểm là bạn không phải sử dụng thêm thư viện của bên thứ ba.



    Nếu bạn không cần phải xử lý nhiều ràng buộc liên quan đến tham số của request thì đơn giản 4là7 dùn 5là c

    Nếu bạn muốn nhanh gọn hơn thì trên Hex có một số thư viện để hỗ trợ định nghĩa paramơẑơn

    Thư viện này cung cấp cách thức đơn giản và nhanh cóng hơn để định nghĩa param cho API. Mình sẽ viết bài hướng dẫn sau.

    좋은 웹페이지 즐겨찾기