質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

2回答

1683閲覧

if foo.class == Hash && foo[:title] == "bar" を短く書く方法を教えてください

退会済みユーザー

退会済みユーザー

総合スコア0

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2017/01/15 10:54

Ruby

1if foo.class == Hash && foo[:title] == "bar" 2 やりたい処理 3end

上記のifの条件部分を短く書きたいです。
fooにはStringやHashやArrayなどどのclassが入ってくるかわからないため、 classのチェックと同時にkey: valueのチェックを行っています。

Ruby

1if foo[:title] == "bar" 2 やりたい処理 3end

このように書くと、もしfooにHash以外のclassが入っていた場合エラーになってしまいます。
ただ、keyを指定しているのであればHashを期待してることは明らかなので、Hash以外が入っていたらエラーになるのではなくただ一致しなかっただけとして処理をしてほしい、というのが理想です。

あまりうまく伝えられていないかもですが、とにかく、
Hashかどうか、:titleの値はbarか、という二段階のチェックをもっと短く書きたいです。

何か方法は無いでしょうか。

ちなみに、どんなclassが入ってくるかわからないという設計自体がまずいですかね、という疑念が。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

すでに回答として上がっておりますが、私ならこうします。

ruby

1def foo.has?(key, val) 2 # Hashクラス かつ valのkeyをもつか? 3 self.is_a?(Hash) && self[key] == val 4end 5 6if foo.has?(:title, "bar") 7 やりたい処理 8end

投稿2017/01/15 12:56

JUNJUNJUN

総合スコア25

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/01/15 13:16

実は取り出したい値がネストしている状況でして、それに対応するメソッドを書いていたのですが行き詰ってしまいました。。 def has_value?(item, key, value) if key.is_a?(Array) keys = "'"+key.join("','")+"'" p eval("#{item}.dig(#{keys}) == '#{value}'") end item.is_a?(Hash) && item[key] == value end res = { 'error': {'title': 'Unauthorized'} } has_value?(res,[:error,:title],'Unauthorized')
JUNJUNJUN

2017/01/15 13:26

行き詰まること、私もよくあります(笑) いい解法がでることをお祈りしています。
退会済みユーザー

退会済みユーザー

2017/01/15 13:30

怪しいですけど動きました! def has_value?(item, key, value) if key.is_a?(Array) keys = ":"+key.join(",:") eval("#{item}.dig(#{keys}) == '#{value}'") end item.is_a?(Hash) && item[key] == value end res = { "error": {"title": "Unauthorized"} } has_value?(res,['error','title'],'Unauthorized') https://paiza.io/projects/MgfsZ9rmXn5gowg6u1oS8Q
JUNJUNJUN

2017/01/15 13:51

おめでとうございます~
guest

0

Ruby

1if ( foo[:title] == "bar" rescue false )

のような荒技を使わない限り、2条件をandで繋がざるを得ないと思います。
短く書くなら、そういうメソッドを定義してifではそれを呼び出すようにするか。

また、foo.class == Hashよりは、Hashのサブクラスのインスタンスでも良いfoo.is_a?(Hash)の方が良いと思います。

#コメントに対して追記。「そういうメソッド」の例。

Ruby

1def has_value?(item, key, value) 2 item.is_a?(Hash) && item.dig(*key) == value 3end 4 5# キーはシンボルとする 6res = {error: 7{title: "Unauthorized"} 8} 9if has_value?(res,[:error,:title],'Unauthorized') 10 ~~ 11end

投稿2017/01/15 11:35

編集2017/01/15 16:19
otn

総合スコア84499

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/01/15 13:17

ありがとうございます。 別の方にコメントで返答させていただいた状況になっております。 お助けいただけないでしょうか。。
otn

2017/01/15 16:13

キーが文字列なのか、シンボルなのか混乱していますね。 「シンボルとは何か」について理解されていますか? コードは本分に追記します。
退会済みユーザー

退会済みユーザー

2017/01/16 00:55

ありがとうございます。 ご指摘の通り、実はシンボルや文字列の違いを理解しておらず、下記のようなコードにしていました。 def has_hash?(item, *key, value) item = item.deep_symbolize_keys if key.is_a?(Array) keys = ':'+key.join(',:') eval("#{item}.dig(#{keys}) == '#{value}'") elsif item.is_a?(Hash) item[key] == value end end アドバイスをいただいて今はこうしました。 def has_hash?(item, key, value) item = item.deep_symbolize_keys key = key.map &:to_sym item.is_a?(Hash) && item.dig(*key) == value end これならシンボルでも文字列でもOKかなと。 rails依存にはなりますが。 名前も、has_value?は既に存在していたのでhas_hash?に変更してみました。 いけてますかね!?
退会済みユーザー

退会済みユーザー

2017/01/16 00:58

訂正 itemがハッシュじゃない場合deep_symbolize_keysでエラーになるので下記のようにしました。 def has_hash?(item, key, value) key = key.map &:to_sym if item.is_a?(Hash) item = item.deep_symbolize_keys item.dig(*key) == value end end
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問