Tìm hiểu về grape API và active model serializers
I. Các khái niệm? 1. Grape API Grape là một REST-like API micro-framework cho Ruby. Nó được thiết kế để chạy trên Rack hoặc bổ sung cho mô hình ứng dụng web hiện có như Rails và Sinatra bằng việc cung cấp một DSL đơn giản để dễ dàng phát triển các RESTful API Cài đặt: Thêm dòng này vào ...
I. Các khái niệm?
1. Grape API
- Grape là một REST-like API micro-framework cho Ruby. Nó được thiết kế để chạy trên Rack hoặc bổ sung cho mô hình ứng dụng web hiện có như Rails và Sinatra bằng việc cung cấp một DSL đơn giản để dễ dàng phát triển các RESTful API
- Cài đặt:
Thêm dòng này vào Gemfile:
gem 'grape'
Sau đó chạy:
$ bundle install
2. ActiveModel Serializers
- ActiveModelSerializers (AMS) là một gem trong rails hỗ trợ người dùng tạo ra JSON dễ dàng và đơn giản hơn. AMS thực hiện thông qua 2 thành phần: Serializers và Adapter. Serializers mô tả những thuôc tính và các mối quan hệ mà cần được chuyển đổi. Adapter mô tả cách các thuộc tính và các mối quan hệ mà cần chuyển đổi.
- Cài đặt:
Thêm dòng này vào Gemfile
gem 'active_model_serializers'
Sau đó chạy:
$ bundle install
II. Cách sử dụng
1. Grape API
- Tham khảo ở đây: https://viblo.asia/quynhbv_hp/posts/2p1PvQpBGldr. Bài viết trình bày rất rõ về cách sử dụng Grape API
2. ActiveModel Serializers
- Ví dụ khi ta gọi 1 API, cụ thể ở đây là gọi api user detail (current_user):
# lib/api/v1.rb class API::V1 < Grape::API version "v1", using: :path rescue_from Grape::Exceptions::ValidationErrors do error!({status_code: Settings.http_code.code_400, content: Settings.validations_error}, Settings.http_code.code_400) end desc "Return the current API version - V1." get do {version: "v1"} end helpers do def authenticate! error!({content: "401, Unauthorized"}, 401) unless current_user end def current_user @current_user ||= User.authorize!(env) end end mount UsersAPI end #lib/api/v1/users_api.rb class API::V1::UsersAPI < Grape::API resources :users do before do authenticate! end namespace :me do get do render curent_user, meta {message: "current_user's information"} end end end end
-
Khi client thông qua url: http://localhost:3000/api/v1/users/me, nếu không dùng ActiveModel::Serializer cho model User thì ta sẽ nhận được rất nhiều các attributes từ current_user và tất nhiên nhiều attributes sẽ bị coi là dư thừa nếu phía client không sử dụng đến chúng. VD:
Hình ảnh: kết quả trả về khi dùng postman gọi đến API users thông qua url: http://localhost:3000/api/v1/users/me
Và khi chúng ta dùng đến ActiveModel::Serializer
- Bật terminal lên và cd đến thư mực chứa project, chạy:
$ rails g serializer user
ta sẽ được 1 file như thế này:
#app/serializers/user_serializer.rb class UserSerializer < ActiveModel::Serializer attributes :id end
- Khi tạo user_serializer.rb thì mặc định attributes trả về dạng JSON của model User chỉ có :id, giờ ta sẽ edit nó thành như thế này:
#app/serializers/user_serializer.rb class UserSerializer < ActiveModel::Serializer attributes :name, :facebook_id, :birthday, :age, :sex end
- Thì khi gọi api user qua url http://localhost:3000/api/v1/users/me, ta sẽ thu được như thế này: Hình ảnh: kết quả trả về khi dùng postman gọi đến API users thông qua url: http://localhost:3000/api/v1/users/me
=> Ta có thể thấy, các attributes không cần dùng đến hoặc bị thừa đã bị loại bỏ khỏi kết quả trả về.
Using a serializer without renderNhiều thời điểm chúng ta cần sử dụng dữ liệu dạng JSON của 1 resource nào đó thì ta có thể dùng các cách sau:
- 1 resource:
UserSerializer.new(@user).serializable_hash
=> ta thu được:
=> {:name=>"Phuong", :facebook_id=>"0000000000000", :birthday=>Sun, 30 Nov 1997, :age=>1, :sex=>1}
- arrays resources:
ActiveModel::ArraySerializer.new(@users).as_json
=> ta thu được:
=> [{:name=>"Phuong", :facebook_id=>"0000000000000", :birthday=>Sun, 30 Nov 1997, :age=>1, :sex=>1}, {:name=>"Maximus Rau DVM", :facebook_id=>"0000000000000", :birthday=>Sun, 30 Nov 1997, :age=>1, :sex=>1}]Overriding association methods
- Nếu muốn override quan hệ nào đó, có thể viết như sau:
class UserSerializer < ActiveModel::Serializer attributes :name, :facebook_id, :birthday, :age, :sex has_many :battles def battles object.battles end end
- Nếu muốn override 1 thuộc tính nào đó thì ta có thể viết như sau:
class UserSerializer < ActiveModel::Serializer attributes :name, :facebook_id, :birthday, :age, :sex has_many :battles def battles object.battles end def age object.age = 18 end end
III. Lời kết
- Grape API là 1 công cụ để viết api rất đơn giản nhưng mang lại hiệu quả rất cao.
- Active Model Serializer khi kết hợp với API thì giúp cho kết quả của trả về API được ngắn gọn dễ hiểu
IV. Tham khảo
- https://intridea.github.io/grape/docs/
- https://viblo.asia/quynhbv_hp/posts/2p1PvQpBGldr
- https://github.com/rails-api/active_model_serializers