How to encrypt your data with Ecto
If your data is encrypted, even if it’s leaked, no one know what is the data. That’s great. In this post, I’m going to show you how …
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:
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 cast các tham số về đúng kiểu dữ liệu mong muốn, nó cũng hỗ trợ các phương thức để validate các tham số yêu cầu, và nó cũng cho phép bạn giới hạn tham số nào được truyền vào.
Và sau đây là một ví dụ sử dụng Chageset
để validate các tham số khi filter các đơn hàng.
1defmodule MyApp.OrderFilterParams do
2 use Ecto.Schema
3 import Ecto.Changeset
4
5 schema "order_filter_params" do
6 field :keyword, :string
7 field :category_id, :integer
8 field :status, :string
9 field :start_date, :utc_datetime
10 field :end_date, :utc_datetime
11 end
12end
Sau đó phải định nghĩa một hàm để thực hiện việc cast tham số và validate changeset
.
1defmodule MyApp.OrderFilterParams do
2
3 ...
4
5 @required ~w(category_id start_date)
6 @optional ~w(keyword status end_date)
7
8 def changeset(changeset_or_model, params) do
9 cast(changeset_or_model, params, @required ++ @optional)
10 |> validate_required(@required)
11 end
12end
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ện tại, các bạn phải định nghĩa một function để set giá trị mong muốn.
1defmodule MyApp.OrderFilterParams do
2
3 ...
4
5 def changeset(changeset_or_model, params) do
6 cast(changeset_or_model, params, @required ++ @optional)
7 |> validate_required(@required)
8 |> set_default_end_date()
9 end
10
11 defp set_defaut_end_date(changeset) do
12 end_date = get_change(changeset, :end_date)
13 if is_nil(end_date) do
14 put_change(changeset, :end_date, Timex.today())
15 else
16 changeset
17 end
18 end
19end
1defmodule MyApp.OrderController do
2 use MyApp, :controller
3 alias MyApp.OrderFilterParams
4
5 def index(conn, params) do
6 changeset = OrderFilterParams.changeset(%OrderFilterParams{}, params)
7
8 if changeset.valid? do
9 strong_params = Ecto.Changeset.apply_changes(changeset)
10 IO.put(strong_params.keyword)
11 # Do something with your params
12 else
13 # handle error
14 end
15 end
16end
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ứ.
Thử tưởng tượng mỗi API bạn lại phải định nghĩa thê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 gì tới nhau cả. Và bạn thì kiểu như đổ sting vào cơm để ăn vậy.
Đ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 database.
Đơ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 là cứ dùng Changeset
thôi.
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 giản hơn, ví dụ như https://github.com/bluzky/tarams/
Thư viện này cung cấp cách thức đơn giản và nhanh chóng hơn để định nghĩa param cho API. Mình sẽ viết bài hướng dẫn sau.
If your data is encrypted, even if it’s leaked, no one know what is the data. That’s great. In this post, I’m going to show you how …
Credit: filter image taken from svgrepo.com In web developments, server receives lots of request data from client side. And when working with request …