29

strong parameters中有沒有辦法允許nested_attributes模型的所有屬性?這是一個示例代碼。強參數允許嵌套屬性的所有屬性

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 

對於槓桿強大的參數我寫目前這

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

是否有嵌套屬性一種方法,我可以寫允許所有屬性沒有明確地給出屬性名稱,如lever_idexplanation

注意:請不要混淆與permit!permit(:all)這個問題,這是允許所有嵌套屬性

+0

嘗試讀取這個答案可能是,這是有幫助的。 > http://stackoverflow.com/questions/14483963/rails-4-0-strong-parameters-nested-attributes-with-a-key-that-points-to-a-hash –

+0

謝謝,但我看到這個。如果您注意到它正在進行與傳遞文件名相關的選擇性屬性過濾('assets_attributes :: filename')的相同操作。我想允許嵌套屬性的所有參數 – AnkitG

回答

10

的強烈參數的整點是它的名字:讓你的輸入參數強大。
允許所有參數將是一個非常糟糕的主意,因爲它允許任何人插入不需要用戶更新的值。

在你給出的例子中,你提到了你目前需要提供的兩個參數:
[:lever_id, :explanation]

如果您允許所有參數,那麼有人可以更改任何其他值。例如
created_atlever_id

這絕對是一個安全問題,這就是爲什麼你不應該這樣做。
明確指定所有屬性時,您可能會覺得無聊。
但這是保持應用程序安全所必需的。

編輯:對於人們downvoting這一點。這可能不是你正在尋找的答案,但它是你需要的答案。
將所有嵌套屬性列入白名單是一個巨大的安全缺陷,強大的參數試圖保護您,並且您將其刪除。書寫時https://gist.github.com/peternixey/1978249

+1

謝謝,你的回答是一個有效的觀點,它可能是一個安全問題。我會明確提及這些屬性。 – AnkitG

+17

如果您收到的散列存儲在序列化的JSON列中,那麼對於這些​​密鑰不存在安全問題。 (除了現有的關於太大輸入的擔憂)。我有這個用例,我想允許散列中的任意鍵。 –

+2

還有其他一些保護屬性的方法。例如,拋棄不允許的參數的命令對象是一種更好的方法,恕我直言。 – karmajunkie

46

我所遇到的其中一個嵌套PARAMS散列允許的任意鍵的唯一情況似乎合理的,我的是:
看看什麼導致建築strong_params,以及如何不使用它可以對你不好到一個序列化的列。我已經成功地處理這樣的:

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確保我們不需要:options關鍵的禮物。

+0

非常感謝,您節省了我很多時間:) –

+1

這是正確的答案!你應該得到一個綠色的複選框! –

+2

爲什麼'params.require(:post).fetch(:options,nil)'而不是'params.require(:post)[:options]'? –

5

嘗試

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

首先,確保你真的要允許在嵌套的散列所有值。閱讀Damien MATHIEU's answer以瞭解安全漏洞的潛在開放情況...

如果您仍然需要/想要允許散列中的所有值(對此存在完全有效的用例,例如存儲非結構化的用戶提供的記錄元數據),則可以使用以下代碼位實現它:

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

注:這是非常相似的tf.'s answer但有點更優雅,因爲你不會得到任何Unpermitted parameters: lever_benefit_attributes警告/錯誤。

15

實際上有一種方法可以只列出所有嵌套參數。

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

這種方法比其他解決方案有優勢。 它允許允許深嵌套參數。

而像其他的解決方案:

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

不要。


來源:

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

+2

這不適用於Rails 5中的深層嵌套參數。請參閱這裏的原因:http://eileencodes.com/posts/actioncontroller-parameters-now-returns-an-object-instead-of-a-hash/ – rmcsharry