Strong Parameters trong Rails 4
Docs: http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html Từ trong Rails 4 StrongParamaters được thêm. Vậy ý nghĩa, cách sử dụng của nó là gì hôm nay mình sẽ giới thiệu với các bạn về nó. Strong Parameters và Mass Assignment StrongParameters là 1 phương pháp để ...
Docs: http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html
Từ trong Rails 4 StrongParamaters được thêm. Vậy ý nghĩa, cách sử dụng của nó là gì hôm nay mình sẽ giới thiệu với các bạn về nó.
Strong Parameters và Mass Assignment
-
StrongParameters là 1 phương pháp để đối phó với lỗi bảo mật khi sử dụng tính năng Mass Assignment.
-
Mass Assignment là 1 tính năng cực kì tiện lợi cho phép update 1 model – khi tạo mới hoặc thay đổi – bằng hash của Ruby.
# không sử dụng mass assignment user = User.find(1) user.name = "Rock Khuya" user.email = "sample@gmail.com" user.save # sử dụng mass assignment user = User.find(1) user.update(name: "Rock Khuya", email: "sample@gmail.com")
Điều này đặc biệt tiện lợi khi cần thay đổi nhiều dữ liệu cùng lúc. Ví dụ trong controller này:
class ProfileController < ApplicationController def update user = current_user # params = {name: "Rock Khuya", email: "sample@gmail.com"} user.update(params[:user]) end end
Tuy nhiên, điều này ẩn chứa 1 lỗi khá nghiêm trọng, đó là ta không kiểm soát được những giá trị trong params. Nếu hacker thêm vào những giá trị như {password: "12345678", admin: true} thì mặc nhiên user sẽ bị thay đổi password hoặc trở thành admin.
Cách sử dụng
StrongParameters được thêm vào để ngăn chặn lỗi này.
class ProfileController < ApplicationController def update user = current_user # params = {name: "Rock Khuya", email: "sample@gmail.com"} user.update(user_params) end private def user_params params.require(:user).permit(:name, :email) end end
StrongParameters giống như 1 bộ lọc các giá trị được phép thay đổi.
Cách sử dụng rất đơn giản :
- require(:user) bắt buộc trong params phải có key là user
- permit(:name, :email) trong key user chỉ cho phép name và email
Ví dụ khác, trong trường hợp params không có key user, Rails sẽ báo lỗi. Điều này khá bất tiện, do đó ta có thể sử dụng fetch khai báo mặc định.
2 params.fetch(:article, {}).permit(:headline, :content) # Nếu params[:article] có thì sử dụng giá trị đó, nếu không thì được coi là {}
Strong Parameters và nest
Giả sử 1 user có nhiều địa chỉ, khi đó ta có :
has_many :addresses, :dependent => :destroy accepts_nested_attributes_for :addresses
Cách viết Strong Parameters cho trường hợp này :
def user_params params.require(:user).permit( :name, :email, :addresses_attributes => [:location, :zip, :prefecture, :street]) end
debug Strong Parameters
Strong Parameters tiện lợi và mạnh mẽ thật, song đôi khi lại là ác mộng khi debug. Vì đôi khi mọi thứ đều hoàn hảo, chỉ trừ việc quên không khai báo trong Strong Parameters và 1 giá trị nào đó bị loại bỏ. Mình từng bị 1 lần viết code cho upload ảnh, khi đó sẽ có thêm 1 giá trị mới là :_destroy, mình quên không khai báo và debug hết … 1 ngày.
Để khắc phục điều này, ta có thể thay đổi setting trong config/application.rb ( cho từng môi trường cụ thể config/environments/xyz.rb) để khi có 1 giá trị không được cho phép ở trong params, Rails sẽ gọi lỗi lên :
config.action_controller.action_on_unpermitted_parameters = :raise
Thuộc tính ảo cũng phải khai báo
Với những thuộc tính ảo, không tồn tại trên DB, ta vẫn phải khai báo với Strong Parameters. Ví dụ như confirmed, _destroy, …
class Paper < ActiveRecord::Base # thuộc tính này không được lưu trên DB attr_accessor :confirmed def create @paper = Paper.new(paper_params) # Nếu không được confirmed sẽ báo lỗi if @paper.save redirect_to @paper, notice: "failed." else render action: "new" end end private def paper_params params.require(:paper).permit(:confirmed) end end
Hy vọng bài viết này sẽ giúp các bạn nhanh chóng làm quen hơn với Rails. Thân.