我有興趣獲取params散列的嵌套'name'參數。調用類似有沒有一種乾淨的方法來避免在嵌套參數散列中調用nil方法?
params[:subject][:name]
params [:subject]爲空時會引發錯誤。爲了避免這種錯誤我平時寫的是這樣的:
if params[:subject] && params[:subject][:name]
有沒有實現這一個更清潔的方式?
我有興趣獲取params散列的嵌套'name'參數。調用類似有沒有一種乾淨的方法來避免在嵌套參數散列中調用nil方法?
params[:subject][:name]
params [:subject]爲空時會引發錯誤。爲了避免這種錯誤我平時寫的是這樣的:
if params[:subject] && params[:subject][:name]
有沒有實現這一個更清潔的方式?
伊克很迷人。 – 2011-03-25 08:08:14
有趣的是,我之前沒有聽說過伊克。 – bowsersenior 2011-03-25 16:24:48
現在,紅寶石已經消失,上面的鏈接到Ick的可能插件被打破。新的寶石網站rubygems.org有一個叫做也許在這裏的寶石:https://rubygems.org/gems/maybe。這與紅寶石僞造者Ick的相同嗎? – 2014-06-20 17:30:08
不是。您可以嘗試fetch
或try
(來自ActiveSupport),但它不會比您已有的更清潔。
此處瞭解詳情:
更新:忘了andand
:
andand
讓你做:
params[:user].andand[:name] # nil guard is built-in
同樣,你可以使用maybe
從Ick libraryper the answer above。
您可以使用#try
,但我不認爲這是更好的:
params[:subject].try(:[], :name)
或者使用#fetch
使用默認參數:
params.fetch(:subject, {}).fetch(:name, nil)
或者你也可以設置#default=
到新的空散列,但不要嘗試修改從此返回的值:
params.default = {}
params[:subject][:name]
也打破了現有的所有簡單的測試,所以你不能寫:
if params[:subject]
,因爲它會返回空散,現在你必須#present?
調用添加到每個測試。
此外,當密鑰沒有值時,即使您期望字符串,也總是返回散列值。
但從我看到的,你嘗試提取嵌套參數,而不是分配給模型,並在那裏放置你的邏輯。如果你有Subject
模型,然後簡單地分配:
@subject = Subject.new(params[:subject])
shuld提取您的所有參數用戶填寫表單。然後嘗試保存它們,以查看用戶是否傳遞了有效值。
如果你擔心訪問該用戶不應該設置字段,然後(與@subject.attributes = params[:subject]
用於更新在我的例子中,)
params[:subject].try(:[], :name)
添加attr_accessible
白名單whoich應該被允許與質量分配字段集是乾淨方式
當我在編碼中遇到同樣的問題時,我有時會使用'rescue'。
name = params[:subject][:name] rescue ""
# => ""
這不是禮貌,但我認爲這是簡單的方法。
編輯:我不再經常使用這種方式。我推薦try
或fetch
。
或者,加上[]
即可。
class NilClass; def [](*); nil end end
params[:subject][:name]
這太好了。我刪除了我的,因爲這個比我的好多了。而且,感謝您使用沒有名稱的splat運算符'*'。我不知道這一點,並從你那裏瞭解到。 – sawa 2011-11-03 07:30:37
更多人對此有何評論?這對我來說似乎很棒! – 2015-03-13 06:17:32
我寫Dottie只是這種使用情況 - 達深成散列不知道第一次在整個預期樹是否存在。語法比使用try
(Rails)或maybe
(Ick)更簡潔。例如:
# in a Rails request, assuming `params` contains:
{ 'person' => { 'email' => '[email protected]' } } # there is no 'subject'
# standard hash access (symbols will work here
# because params is a HashWithIndifferentAccess)
params[:person][:email] # => '[email protected]'
params[:subject][:name] # undefined method `[]' for nil:NilClass
# with Dottie
Dottie(params)['person.email'] # => '[email protected]'
Dottie(params)['subject.name'] # => nil
# with Dottie's optional class extensions loaded, this is even easier
dp = params.dottie
dp['person.email'] # => '[email protected]'
dp['subject.name'] # => nil
dp['some.other.deeply.nested.key'] # => nil
退房的文檔,如果你想看到更多:https://github.com/nickpearson/dottie
我用:
params = {:subject => {:name => "Jack", :actions => {:peaceful => "use internet"}}}
def extract_params(params, param_chain)
param_chain.inject(params){|r,e| r=((r.class.ancestors.include?(Hash)) ? r[e] : nil)}
end
extract_params(params, [:subject,:name])
extract_params(params, [:subject,:actions,:peaceful])
extract_params(params, [:subject,:actions,:foo,:bar,:baz,:qux])
給出:
=> "Jack"
=> "use internet"
=> nil
class Hash
def fetch2(*keys)
keys.inject(self) do |hash, key|
hash.fetch(key, Hash.new)
end
end
end
例如
require 'minitest/autorun'
describe Hash do
it "#fetch2" do
{ yo: :lo }.fetch2(:yo).must_equal :lo
{ yo: { lo: :mo } }.fetch2(:yo, :lo).must_equal :mo
end
end
我從交叉我的答案在這裏發佈這樣的:
How to check if params[:some][:field] is nil?
我一直在尋找一個更好的解決方案了。
所以我想再拿try
不同的方法來測試一個嵌套的關鍵字設定:
params[:some].try(:has_key?, :field)
它不壞。如果未設置,則獲得nil
與false
。如果參數設置爲nil
,您還會得到true
。
可避免與內嵌分配的雙重散列訪問:
my_param = subj_params = params[:subject] && subj_params[:name]
的Ruby 2.3.0使這很容易與#dig
h = {foo: {bar: {baz: 1}}}
h.dig(:foo, :bar, :baz) #=> 1
h.dig(:foo, :zot, :baz) #=> nil
如果'h'爲'nil','h.dig'將會失敗。考慮使用安全導航運算符,或者將'.dig'與'h&.dig(:foo,:bar,:baz)'或'h&.foo&.bar&.baz'結合使用。 – thisismydesign 2017-09-11 15:32:39
我以前的評論中有關哈希的安全導航器操作符的語法不正確。正確的語法是:'h&。[](:foo)&。[](:bar)&。[](:baz)'。 – thisismydesign 2017-09-18 15:22:26
前幾天同樣的問題做:) http://stackoverflow.com/questions/5393974/ruby-nils-in-an-if-statement/5394240#5394240 – fl00r 2011-03-25 10:56:38