Rails 4 - Thông số mạnh - Đối tượng lồng nhau


144

Tôi đã có một câu hỏi khá đơn giản. Nhưng cho đến nay vẫn chưa tìm được giải pháp.

Vì vậy, đây là chuỗi JSON tôi gửi đến máy chủ:

{
  "name" : "abc",
  "groundtruth" : {
    "type" : "Point",
    "coordinates" : [ 2.4, 6 ]
  }
}

Sử dụng phương thức cấp phép mới, tôi đã có:

params.require(:measurement).permit(:name, :groundtruth)

Điều này không có lỗi, nhưng mục cơ sở dữ liệu đã tạo chứa nullthay vì giá trị nền tảng.

Nếu tôi chỉ đặt:

params.require(:measurement).permit!

Mọi thứ đều được lưu như mong đợi, nhưng tất nhiên, điều này sẽ giết chết sự bảo mật được cung cấp bởi các tham số mạnh.

Tôi đã tìm thấy các giải pháp, làm thế nào để cho phép các mảng, nhưng không phải là một ví dụ duy nhất sử dụng các đối tượng lồng nhau. Điều này phải có thể bằng cách nào đó, vì nó phải là một trường hợp sử dụng khá phổ biến. Vì vậy, làm thế nào nó hoạt động?



1
@vinodadhikary Đó là chính xác Tôi nghĩ OP bị nhầm lẫn. Nghe có vẻ kỳ quặc khi bạn muốn cho phép các thuộc tính lồng nhau, bạn chỉ định các thuộc tính của đối tượng lồng trong mảng. Mặt khác, nếu bạn muốn lồng nhiều đối tượng thì bạn bọc nó bên trong hàm băm xem api.rubyonrails.org/groupes/ActionContoder/ và và github.com/rails/rails/blob/master/actionpack/lib/
j03w

@ j03w, Cảm ơn đã liên kết đến nguồn. Bây giờ thì rõ rồi. Bạn nên thêm một câu trả lời ở đây cho phát hiện này vì tôi nghĩ nó sẽ giúp được rất nhiều người khác.
vee

Câu trả lời:


181

Nghe có vẻ kỳ quặc khi bạn muốn cho phép các thuộc tính lồng nhau, bạn chỉ định các thuộc tính của đối tượng lồng trong một mảng. Trong trường hợp của bạn, nó sẽ là

Cập nhật theo đề xuất của @RafaelOliveira

params.require(:measurement)
      .permit(:name, :groundtruth => [:type, :coordinates => []])

Mặt khác, nếu bạn muốn lồng nhiều đối tượng thì bạn bọc nó bên trong một hàm băm như thế này

params.require(:foo).permit(:bar, {:baz => [:x, :y]})


Rails thực sự có tài liệu khá tốt về điều này: http://api.rubyonrails.org/groupes/ActionControll/Parameter.html#method-i-permit

Để làm rõ hơn, bạn có thể xem xét việc thực hiện permitstrong_parameterschính nó: https://github.com/rails/rails/blob/master/actionpack/lib/action_controll/metal/strong_parameter.rb#L246-L247


5
cả hai trường hợp đều giống nhau trong câu trả lời này, thực ra, chỉ là các dấu ngoặc nhọn là tùy chọn xung quanh {: groundtruth => [...]}; Đó là một hàm băm nhưng trình thông dịch có thể xác định nơi băm bắt đầu và kết thúc mà không có dấu ngoặc nhọn rõ ràng.
nói

Các mảng thuộc tính lồng nhau không cho phép các thuộc tính lồng nhau. Các thuộc tính lồng nhau và attr_accessor được liệt kê trong ứng dụng của tôi dưới dạng "Tham số chưa được gửi". Vẫn đang tìm giải pháp an toàn.
Katarzyna

Trong trường hợp có nhiều đối tượng lồng nhau, bạn cũng nên cho phép id để làm việc này. Thêm thông tin tại đây: stackoverflow.com/questions/18308714/NH
Fabrice Carrega

1
Điều này chỉ cho phép MỘT bộ thuộc tính lồng nhau. Điều này sẽ không hoạt động trong trường hợp một đến nhiều.
AKWF

23

Tôi thấy đề nghị này hữu ích trong trường hợp của tôi:

  def product_params
    params.require(:product).permit(:name).tap do |whitelisted|
      whitelisted[:data] = params[:product][:data]
    end
  end

Kiểm tra liên kết này của nhận xét của Xavier trên github.

Cách tiếp cận này liệt kê toàn bộ đối tượng params [: đo lường] [: groundtruth].

Sử dụng các thuộc tính câu hỏi ban đầu:

  def product_params
    params.require(:measurement).permit(:name, :groundtruth).tap do |whitelisted|
      whitelisted[:groundtruth] = params[:measurement][:groundtruth]
    end
  end

4
Chỉ cần một lưu ý phụ, Điều này vẫn sẽ hiển thị trong nhật ký dưới dạng các tham số chưa được cấp nhưng mô hình sẽ chấp nhận chúng bằng mọi cách.
Weston Ganger

5
Không chắc chắn về Rails 4 nhưng trong dự án Rails 5 của tôi, tôi phải gọi permit!để được đưa vào danh sách trắng nếu không nó vẫn không được chấp nhận sau khi nhấn vào nó. Trong trường hợp này, nó sẽ làparams[:measurement][:groundtruth].permit!
nayiaw

@nayiaw tôi cũng nhận được tin nhắn chưa được gửi nhưng việc permit!tăng NoMethodError (undefined method giấy phép lỗi này ! ' cho # <Mảng: 0x007f80cb71ea00>): `
wuliwong

@wuliwong permit!phương pháp không có sẵn trong Array. Bạn sẽ cần có quyền truy cập vào thể hiện của lớp tương ứng để có quyền truy cập permit!(đã được một thời gian vì vậy tôi đã quên tên lớp nhưng nó giống như ActionController::Parametersdựa trên trang này ).
nayiaw

8

Cho phép một đối tượng lồng nhau:

params.permit( {:school => [:id , :name]}, 
               {:student => [:id, 
                            :name, 
                            :address, 
                            :city]},
                {:records => [:marks, :subject]})

0

Nếu là Rails 5, vì ký hiệu băm mới: params.permit(:name, groundtruth: [:type, coordinates:[]])sẽ hoạt động tốt.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.