Ruby、またはnot_nilのRuby-ismはありますか?nilの反対?方法?


87

私はRubyの経験がないので、コードは「醜い」と感じ、慣用的ではありません。

def logged_in?
  !user.nil?
end

どちらかというと

def logged_in?
  user.not_nil?
end

しかし、反対の方法を見つけることができません nil?

回答:


51

ActiveSupportを使用している場合は、user.present? http: //api.rubyonrails.org/classes/Object.html#method-i-present%3Fがあり、nilでないかどうかだけを確認できます。

def logged_in?
  user # or !!user if you really want boolean's
end

48
注意:present?空白以外の文字列が必要です。 ! "".nil?trueを返しますが、"".present?falseを返します。
lambshaanxy

9
注意2:私はまた、!! userはユーザーがnilであることとユーザーがfalseであることを区別しないことに注意します。ダブルバンの使用法はこれら2つを統合します。したがって、オブジェクトがnilではない(つまり、true、false、0、 ""、nil以外のものである)かどうかを本当に判断したい場合は、バークが好まない「醜い」アプローチを使用する必要があります。または@Tempus が以下に提案する monkeypatch 。もちろん、nilが必要ない(Railsのユーザー)この場合、Samo採用するアプローチは最も醜いimoです。
likethesky

12
false.present? == false !false.nil? == true
Dudo 14

3
この答えは、尋ねられた質問にまったく答えません。これは、この特定の実装の問題に対する答えです。
Ekkstein、2016年

3
この答えは正しくありません。false.nil?falseですが、false.present?また偽です!
マイク

49

ブール値に過度に関心があるようです。

def logged_in?
  user
end

ユーザーがnilの場合、logged_in?「false」値を返します。それ以外の場合は、オブジェクトを返します。RubyではJavaScriptのように「真実」と「偽」の値があるため、trueまたはfalseを返す必要はありません。

更新

Railsを使用している場合は、次のpresent?メソッドを使用して、これをより適切に読み取ることができます。

def logged_in?
  user.present?
end

1
aで終わるメソッドの期待?は、ブール値を返すことです。!!value何かをブール値に変換する古典的な方法です。まったく同じではありませんが、この場合Object#present?はRoRでも問題ありません。
tokland

これは実際、Pathを使用したRuby 2.4で機能しなくなります。[43](引き離し)#<ReactOnRails :: AssetsPrecompile>:0> assets_path.blank?true [44](pry)#<ReactOnRails :: AssetsPrecompile>:0> assets_path.to_s "/ var / folders / rp / _k99k0pn0rsb4d3lm9l3dnjh0000gn / T / d20170603-96466-zk7di7" [45](pry)#<ReactOnRails :: Assets >:0> assets_path.present?false [46](pry)#<ReactOnRails :: AssetsPrecompile>:0> assets_path.nil?false
justingordon

23

present?質問への回答として提示される他の回答に注意してください。

present?blank?レールの反対です。

present?意味のある値があるかどうかをチェックします。これらはpresent?チェックに失敗する可能性があります。

"".present? # false
"    ".present? # false
[].present? # false
false.present? # false
YourActiveRecordModel.where("false = true").present? # false

一方、!nil?チェックでは次のようになります。

!"".nil? # true
!"    ".nil? # true
![].nil? # true
!false.nil? # true
!YourActiveRecordModel.where("false = true").nil? # true

nil?オブジェクトが実際にあるかどうかを確認しますnil。何か他のもの:空の文字列、0false、何でも、ではありませんnil

present? 非常に便利ですが、その反対ではありません nil?。2つを混同すると、予期しないエラーが発生する可能性があります。

あなたのユースケースでpresent?はうまくいきますが、違いを認識することは常に賢明です。


受け入れられた回答に含める必要があります。false.blank?と同じではありませんfalse.nil?
Yason

17

多分これはアプローチかもしれません:

class Object
  def not_nil?
    !nil?
  end
end

良いアイデア。私はこれからnot_nilがないことを確認しますか?Rubyで。しかし、これはそう!self.nil?ではなく!nil?、またはself暗黙的ですか?
berkes

3
あなたは自己を必要としません。それは暗示されます。
Geo

インスタンスメソッド(または実際には単なるメソッドであるアクセサ)から読み取る場合は、自己を意味します。値を設定する場合、Rubyがクラスインスタンスで同じ名前のセッターメソッドをチェックする前に、メソッドにローカルな変数が作成されます。一般的なルール:xxxというattr_accessorがある場合は、「self.xxx = 3」(値を設定)または「temp = xxx」(値を読み取る)を使用します。「xxx = 3」を使用しても、アクセサは更新されず、メソッドスコープに新しい変数が作成されるだけです。
フェーダーDarkly 2017

4

以下を使用するだけです。

if object
  p "object exists"
else
  p "object does not exist"
end

これはnilだけでなくfalseなどでも機能するため、ユースケースで機能するかどうかをテストする必要があります。


4

!メソッドの結果についてRuby-esque メソッドを提供してもよいnil?ですか。

def logged_in?
  user.nil?.!
end

RubyMine IDEがエラーとしてフラグを立てるほど難解です。;-)


2

ブロックの代わりにSymbol#to_proc省略形を使用できるように、オブジェクトメソッドを探しているこの質問に到達しました。私はarr.find(&:not_nil?)より読みやすいと思いますarr.find { |e| !e.nil? }

私が見つけた方法はObject#itselfです。私の使用法では、キーのハッシュで値を見つけたかったのですが、nameそのキーが誤ってとして大文字になっている場合がありましたName。そのワンライナーは次のとおりです。

# Extract values for several possible keys 
#   and find the first non-nil one
["Name", "name"].map { |k| my_hash[k] }.find(&:itself)

他の回答で述べたように、ブール値をテストしている場合、これは見事に失敗します。


それはどう違うのmy_hash.values_at("Name", "name").findですか?
berkes

まったく同じです。私のオリジナルにmapは、この例で簡単にするために削除した他のロジックがいくつかありました。そのため、ここでは、と交換可能values_atです。重要な部分は、渡されるものfindです。
イアン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.