これは技術的にあなたの質問に答えるように見える1つのオプションですが、あなたが探しているものではないと思います:
params.select{|_,v| v.strip.length > 0 if v}
あなたが直面している根本的な問題は、Hash#map がハッシュではなく配列を返すことです。私を含め、多くの人がこれを煩わしいと感じています。例を参照してください: http://www.ruby-forum.com/topic/185611
これは、inject を使用した冗長オプションです。
params.inject({}) {|h,(k,v)| h.merge(k => v ? v.strip : v)}.select{|_,v| v.length > 0 if v}
あなたにとって重要な場合、これらのソリューションのどちらもパラメーターに破壊的な変更を加えることはありません。
1.9.3-p125 :030 > params = {:email => " ab", :xyz => " ", :opq => nil}
=> {:email=>" ab", :xyz=>" ", :opq=>nil}
1.9.3-p125 :031 > params.inject({}) {|h,(k,v)| h.merge(k => v ? v.strip : v)}.select{|_,v| v.length > 0 if v}
=> {:email=>"ab"}
1.9.3-p125 :032 > params
=> {:email=>" ab", :xyz=>" ", :opq=>nil}
Inject は、慣れが必要なトリッキーな機能です。この行を順を追って説明します。
params.inject({}}
結果を格納するための空のハッシュを作成するように指示します。
- |h, (k,v)| 新しい空のハッシュを変数 h に渡すと同時に、元の params ハッシュのキーと値のペアをそれぞれ k、v に渡すように指示します。
次に毛むくじゃらです。次のコマンドを内側から展開します。
v ? v.strip : v
三項演算子を使用して、v が true と評価される場合に v.strip を返し、v が false または nil の場合に v を返します。
k => v ? v.strip : v
結果で新しいハッシュを作成します
h.merge(k => v ? v.strip : v)
新しいハッシュを h にマージします。h は空で始まり、結果を注入ループの次の反復に渡します。
ループの次の繰り返しでは、 h は空ではなくなり、将来の結果は引き続き h にマージされます。
この時点で、ハッシュを削除しました。ここで停止すると、結果は次のようになります。
1.9.3-p125 :032 > params
=> {:email=>" ab", :xyz=>" ", :opq=>nil}
1.9.3-p125 :033 > params.inject({}) {|h,(k,v)| h.merge(k => v ? v.strip : v)}
=> {:email=>"ab", :xyz=>"", :opq=>nil}
ハッシュが削除されたので、select ステートメントは簡単です。ここでは、keep_if ではなく select を使用します。なぜなら、! がないにもかかわらず、keep_if は破壊的なメソッドだからです。この暴言を参照してください: http://news.ycombinator.com/item?id=2247352 . inject ステートメントはハッシュを返すので、それを直接呼び出すことができますが.select
、実際にはコード行をこれほど長くすることはお勧めしません。
1.9.3-p125 :034 > params
=> {:email=>" ab", :xyz=>" ", :opq=>nil}
1.9.3-p125 :035 > params.inject({}) {|h,(k,v)| h.merge(k => v ? v.strip : v)}.select{|_,v| v.length > 0 if v}
=> {:email=>"ab"}