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

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

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

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

Q&A

1回答

2270閲覧

[ruby] 「has_key?」を使って、配列の情報を確認するとともに、違うクラスの情報を追加したい

.FFFUN

総合スコア4

Ruby

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

0グッド

0クリップ

投稿2020/04/19 05:19

編集2020/04/20 02:40

前提・実現したいこと

初めまして。ruby 初学者です。

ただいま、補足情報にあります、TDD Boot Camp 大阪様の
「自動販売機のプログラム」を実装中です。
※詳細を補足情報に記載しております

補足情報の「ステップ3」までは一度実装したのですが、
現在、「新規の飲み物を追加する(コードの[在庫管理]部分です)」というところでつまづいております。

自動販売機で飲み物を購入する際、
「drink_stock」メソッドにて、「has_key?」を使って、
ドリンク名の確認を行い、ドリンク名が見つからない場合に
ドリンクのストックを実行できしたいと考えているのですが、
そもそも「drink_stock」の値が取れないという状況です。

ぜひアドバイスをいただければ幸いです。
何卒宜しくお願い申し上げます。

発生している問題・エラーメッセージ

irb(main):101:0> v = VendingMachine.new => #<VendingMachine:0x00007fb21d13d7c0 @total=0, @sale_amount=0, @drink_table=[{:name=>:cola, :price=>120, :stock=>5}]> irb(main):102:0> v.drink_stock(cola) Traceback (most recent call last): 4: from /Users/tsukinokikatsuhiro/.rbenv/versions/2.6.5/bin/irb:23:in `<main>' 3: from /Users/tsukinokikatsuhiro/.rbenv/versions/2.6.5/bin/irb:23:in `load' 2: from /Users/tsukinokikatsuhiro/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>' 1: from (irb):102 NameError (undefined local variable or method `cola' for main:Object) irb(main):103:0> v.drink_stock(:cola) Traceback (most recent call last): 6: from /Users/tsukinokikatsuhiro/.rbenv/versions/2.6.5/bin/irb:23:in `<main>' 5: from /Users/tsukinokikatsuhiro/.rbenv/versions/2.6.5/bin/irb:23:in `load' 4: from /Users/tsukinokikatsuhiro/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>' 3: from (irb):103 2: from (irb):103:in `rescue in irb_binding' 1: from (irb):64:in `drink_stock' NoMethodError (undefined method `has_key?' for [{:name=>:cola, :price=>120, :stock=>5}]:Array)

該当のソースコード

class Drink attr_reader :name,:price def initialize(name, price) @name = name @price = price end def self.cola self.new(:cola,120) end def self.redbull self.new(:redbull,200) end def self.water self.new(:water,100) end end class VendingMachine AVAILABLE_MONEY = [10, 50, 100, 500, 1000].freeze # これで投入合計額、売上金額をメソッドで呼び出せる。 attr_accessor :total, :sale_amount # :drink_table #初期値 def initialize @total = 0 @sale_amount = 0 @drink_table = [] @drink_table << {name: :cola, price:120, stock:5} # v1.drink_table[0][:stock]で確認できる end def drink_table @drink_table end #お金を受け取る 繰り返し def insert(money) if VendingMachine::AVAILABLE_MONEY.include?(money) @total += money else puts "#{money}円は使えません" end end #払い戻し def refund if @total == 0 puts "払い戻すお金はありません" else puts "#{@total}円を払い戻し" @total = 0 end end # 在庫管理 def drink_stock(drink) unless @drink_table.has_key?(Drink.name) @drink_table << { name: drink.name, price: drink.price, stock: 5 } end @drink_table end #購入可能ドリンクの表示 def purchasable @purchasable end #選んだドリンク以上のお金が入ってるか? def money_check @total >= drink_table[:price] end def purchase #購入したいドリンクをドリンク名で選んでもらう。 #購入可能ドリンクの表示 if money_check && stock # total金額から購入する(選択した)ドリンクの料金を引く @total -= drink_table[:price] # 選んだドリンクのストックを1本減らす @drink_table[:stock] -= 1 # 選んだドリンクの料金分売り上げが増える @sale_amount += drink_table[:price] # puts "残りは、#{@drink_table[:stock]}本です" else puts "購入できません" end end end

試したこと

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

引用:http://devtesting.jp/tddbc/?TDDBC%E5%A4%A7%E9%98%AA3.0%2F%E8%AA%B2%E9%A1%8C

<プログラムの実装手順>
●【ステップ0 お金の投入と払い戻し】
10円玉、50円玉、100円玉、500円玉、1000円札を1つずつ投入できる。
投入は複数回できる。
投入金額の総計を取得できる。
払い戻し操作を行うと、投入金額の総計を釣り銭として出力する。
ステップ1 扱えないお金
想定外のもの(硬貨:1円玉、5円玉。お札:千円札以外のお札)が投入された場合は、投入金額に加算せず、それをそのまま釣り銭としてユーザに出力する。

●【ステップ2 ジュースの管理】
値段と名前の属性からなるジュースを1種類格納できる。初期状態で、コーラ(値段:120円、名前”コーラ”)を5本格納している。
格納されているジュースの情報(値段と名前と在庫)を取得できる。
注意:責務を持ちすぎていませんか?責任を持ちすぎていたら分割しましょう

●【ステップ3 購入】
投入金額、在庫の点で、コーラが購入できるかどうかを取得できる。
ジュース値段以上の投入金額が投入されている条件下で購入操作を行うと、ジュースの在庫を減らし、売り上げ金額を増やす。
投入金額が足りない場合もしくは在庫がない場合、購入操作を行っても何もしない。
現在の売上金額を取得できる。
払い戻し操作では現在の投入金額からジュース購入金額を引いた釣り銭を出力する。
注意:責務が集中していませんか?責務が多すぎると思ったら分けてみましょう

●【ステップ4 機能拡張】
ジュースを3種類管理できるようにする。
在庫にレッドブル(値段:200円、名前”レッドブル”)5本を追加する。
在庫に水(値段:100円、名前”水”)5本を追加する。
投入金額、在庫の点で購入可能なドリンクのリストを取得できる。

●【ステップ5 釣り銭と売り上げ管理】
ジュース値段以上の投入金額が投入されている条件下で購入操作を行うと、釣り銭(投入金額とジュース値段の差分)を出力する。
ジュースと投入金額が同じ場合、つまり、釣り銭0円の場合も、釣り銭0円と出力する。
釣り銭の硬貨の種類は考慮しなくてよい。

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

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

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

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

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

guest

回答1

0

単純な使い方の間違いです。
そのコードの大半はエラーに無関係です。

Ruby

1drink_table = [] 2drink_table << {name: :cola, price:120, stock:5} 3drink_table.has_key?(:cola)

エラーが出るまでにdrink_tableについて実行されるコードはこれだけ。同じようにエラーが出ることが確認できるはずです。

エラーメッセージも参考になるはずです。

NameError (undefined local variable or method `cola' for main:Object) NoMethodError (undefined method `has_key?' for [{:name=>:cola, :price=>120, :stock=>5}]:Array)

どちらも'cola'や'has_key?'が定義されていないというエラーです。

おそらくdrink_tableの定義を変えたんでしょう。そのほかにもpurchaseやmoney_checkの中でもdrink_tableを使ってるコードがありますが、どれも使い方が間違ってます。
長いコードだとどこに問題があるのかわかりづらいので、一旦別のファイルでも作って短いコードで思い通りの動作ができるのか確認しながら変更していったほうがいいでしょう。

投稿2020/04/19 08:55

yudedako67

総合スコア2047

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

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

.FFFUN

2020/04/19 10:43 編集

ご回答ありがとうございます。コードを短く切って、一つずつきちんと検証してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問