29

Có cách nào trong số strong parameters để cho phép tất cả các thuộc tính của một mô hình nested_attributes không? Đây là một mã mẫu.thông số mạnh mẽ cho phép tất cả thuộc tính cho thuộc tính lồng nhau

class Lever < ActiveRecord::Base 
has_one :lever_benefit 
accepts_nested_attributes_for :lever_benefit 
end 

class LeverBenefit < ActiveRecord::Base 
    # == Schema Information 
    # id   :integer   not null, primary key 
    # lever_id :integer 
    # explanation :text 
end 

Đối với đòn bẩy mạnh mẽ thông số i hiện đang viết những dòng này

def lever 
params.require(:lever).permit(:name,:lever_benefit_attributes => [:lever_id, :explanation]) 
end 

Có cách nào cho thuộc tính lồng nhau tôi có thể viết để cho phép tất cả các thuộc tính mà không đưa một cách rõ ràng các thuộc tính tên như lever_idexplanation?

Note: Xin đừng lẫn lộn với câu hỏi này với permit! hoặc permit(:all) này là dành cho cho phép tất cả cho các thuộc tính lồng nhau

+0

thử đọc câu trả lời này có thể đây là hữu ích. > http://stackoverflow.com/questions/14483963/rails-4-0-strong-parameters-nested-attributes-with-a-key-that-points-to-a-hash –

+0

cảm ơn, nhưng tôi đã thấy điều này . Nếu bạn nhận thấy nó đang làm cùng một điều của lọc thuộc tính chọn lọc ('asset_attributes:: filename') mà là đi qua tên tập tin. Tôi muốn cho phép tất cả các tham số cho thuộc tính lồng nhau – AnkitG

Trả lời

10

Toàn bộ các điểm thông số mạnh là trong tên của nó: làm cho các thông số đầu vào của bạn mạnh.
Cho phép tất cả các tham số sẽ là một ý tưởng rất tồi, vì nó sẽ cho phép bất cứ ai chèn các giá trị bạn không nhất thiết muốn được người dùng cập nhật.

Trong ví dụ bạn đưa ra, bạn đề cập đến hai tham số bạn hiện cần cung cấp:
[:lever_id, :explanation].

Nếu bạn cho phép tất cả các thông số, người khác có thể thay đổi bất kỳ giá trị nào khác. Ví dụ:
created_at hoặc lever_id.

Điều này chắc chắn sẽ là vấn đề bảo mật và đây là lý do tại sao bạn không nên làm điều đó.
Xác định rõ ràng tất cả các thuộc tính của bạn có vẻ nhàm chán khi bạn làm điều đó.
Nhưng điều này là cần thiết để giữ cho ứng dụng của bạn an toàn.

Chỉnh sửa: Để mọi người downvoting điều này. Đây có thể không phải là câu trả lời bạn đang tìm kiếm, nhưng đó là câu trả lời bạn cần.
Liệt kê tất cả các thuộc tính lồng nhau là một lỗ hổng bảo mật rất lớn mà các thông số mạnh đang cố gắng bảo vệ bạn và bạn sẽ xóa nó.
Hãy nhìn vào những gì dẫn đến việc xây dựng strong_params, và làm thế nào không sử dụng nó có thể là xấu cho bạn: https://gist.github.com/peternixey/1978249

+1

cảm ơn, câu trả lời của bạn là một điểm hợp lệ mà nó có thể là một mối quan tâm an ninh. Tôi sẽ đi với một cách rõ ràng đề cập đến các thuộc tính. – AnkitG

+17

Nếu băm bạn nhận được được lưu trữ trong một cột JSON được tuần tự hóa thì không có mối lo ngại về bảo mật cho các khóa. (Khác với các mối quan tâm hiện có của một đầu vào quá lớn). Tôi có trường hợp sử dụng này và tôi muốn cho phép bất kỳ khóa tùy ý nào trong một băm. –

+2

Có nhiều cách khác để bảo vệ các thuộc tính. Ví dụ, các đối tượng lệnh để tung ra các tham số chưa được gửi, là một cách tiếp cận tốt hơn nhiều, IMHO. – karmajunkie

46

Tình hình duy nhất mà tôi đã gặp ở đâu cho phép các phím tùy ý trong băm một params lồng nhau có vẻ hợp lý với tôi là khi viết vào một cột được tuần tự hóa. Tôi đã quản lý để xử lý nó như thế này:

class Post 
    serialize :options, JSON 
end 

class PostsController < ApplicationController 
    ... 

    def post_params 
    all_options = params.require(:post)[:options].try(:permit!) 
    params.require(:post).permit(:title).merge(:options => all_options) 
    end 
end 

try đảm bảo chúng tôi không yêu cầu những món quà của một chính :options.

+0

Cảm ơn bạn rất nhiều, Bạn tiết kiệm rất nhiều thời gian của tôi :) –

+1

Đây là câu trả lời đúng! bạn xứng đáng có một hộp kiểm màu xanh lá cây! –

+2

Tại sao 'params.require (: post) .fetch (: options, nil)' thay vì 'params.require (: post) [: options]'? –

5

thử

params.require(:lever).permit(:name, leave_benefit_attributes: LeaveBenefit.attribute_names.collect { |att| att.to_sym }) 
10

Trước tiên, hãy chắc chắn rằng bạn thực sự muốn cho phép tất cả các giá trị trong một hash lồng nhau. Đọc qua số Damien MATHIEU's answer để hiểu lỗ hổng bảo mật tiềm năng ...

Nếu bạn vẫn cần/muốn cho phép tất cả các giá trị trong băm (có trường hợp sử dụng hoàn toàn hợp lệ cho điều này, ví dụ: lưu trữ siêu dữ liệu không được cấu trúc, do người dùng cung cấp cho bản ghi), bạn có thể đạt được nó bằng cách sử dụng các mã sau đây :

def lever_params 
    nested_keys = params.require(:lever).fetch(:lever_benefit_attributes, {}).keys 
    params.require(:lever).permit(:name,:lever_benefit_attributes => nested_keys) 
end 

Lưu ý: Đây là rất giống với tf.'s answer nhưng một chút tao nhã hơn vì bạn sẽ không nhận được bất kỳ cảnh báo Unpermitted parameters: lever_benefit_attributes/lỗi.

15

Thực ra, có một cách để chỉ danh sách trắng tất cả các tham số lồng nhau.

params.require(:lever).permit(:name).tap do |whitelisted| 
    whitelisted[:lever_benefit_attributes ] = params[:lever][:lever_benefit_attributes ] 
end 

Phương pháp này có lợi thế hơn các giải pháp khác. Nó cho phép cho phép tham số lồng sâu.

Trong khi các giải pháp khác như:

nested_keys = params.require(:lever).fetch(:lever_benefit_attributes, {}).keys 
params.require(:lever).permit(:name,:lever_benefit_attributes => nested_keys) 

Đừng.


Nguồn:

https://github.com/rails/rails/issues/9454#issuecomment-14167664

+2

Điều này sẽ không hoạt động đối với các tham số lồng nhau sâu trong Rails 5. Xem tại sao tại đây: http://eileencodes.com/posts/actioncontroller-parameters-now-returns-an-object-instead-of-a-hash/ – rmcsharry

Các vấn đề liên quan