クジラの練習帳012(修正版)

練習帳012

f:id:whale_86:20201124020122j:plain

今回は、ネット上で拾った問題を実際に解きながら考えていきます。

問題

「ある駄菓子屋で飲み物を買うと、空き瓶3本で新しい飲み物を1本プレゼントしてくれる。最初に100本購入した場合、トータルで何本飲めるか」

 

購入した本数 飲める本数
0 0
1 1
3 4
11 16
100

(プログラムで算出する)

 解答

昨日あげた解答は間違いだったため、修正させていただきます。

f:id:whale_86:20201125230310p:plain

問題は、100本買ったときに33本のボーナスが貰え、この33本からまた11本ボーナスが貰え、更に..ってやっていくと飲み終わるときに飲んだ飲み物は何本かを求める必要があったようです💦

解説

まず、bonus_drinkメソッドで[買った本数(100)] と [count_bottle(貰える本数)]を足していきます。 全てのボーナスは下記で表す青字の値を合計し、49となり100 + 49で149となります。

今回のウエイトはcount_bottleメソッド(ボーナスで貰える本数)です。

 

count_bottleメソッドはボーナスで貰える本数を求めます。

今回は、ループするような形で作り、num(持っている本数)が3以下になるまで行い、全てを合計し

その時に持っている本数は[交換した本数(num / 3)と交換に余った本数(num % 3)]の合計を求める必要があります。

 

elseでcount_bottle(num / 3 + num % 3)の動き

100の場合、

f:id:whale_86:20201125234924p:plain

 

問題元↓

github.com

 

 

前回 クジラの練習帳011 - whale_86’s blog

 

オリジナルアプリに警告文が出た

validatesで警告文

f:id:whale_86:20201111193655j:plain

エラー内容

チームメンバーを選択するのにusersテーブルからuser_name(英数字混合のID)を取得する予定。このuser_nameへのバリデーションでエラーが出てしまっている。

 
テーブル設計
## usersテーブル

| Column    | Type   | Options     |
| --------- | ------ | ----------- |
| nickname  | string | null: false |
| user_name | string | null: false |
| email     | string | null: false |
| password  | string | null: false |

### Association
- has_many: team_users
- has_many: team, through: team_users

## teamsテーブル | Column | Type | Options | | --------- | ------ | ----------- | | team_name | string | null: false | ### Association - has_many: team_users - has_many: user, through: team_users
## team_usersテーブル | Column | Type | Options | | ------- | --------- | ------------------------------ | | user | reference | null: false, foreign_key: true | | team | reference | null: false, foreign_key: true | ### Association - belongs_to: user - belongs_to: team

 

警告文

ターミナル:

DEPRECATION WARNING: Uniqueness validator will no longer enforce case sensitive comparison in Rails 6.1. To continue case sensitive comparison on the :user_name attribute in User model, pass `case_sensitive: true` option explicitly to the uniqueness validator.

と出力されました。

翻訳してみると、

非推奨の警告:一意性バリデーターは、R​​ails6.1で大文字と小文字を区別する比較を強制しなくなりました。Userモデルの:user_name属性で大文字と小文字を区別する比較を続行するには、明示的に`case_sensitive:true`オプションを一意性バリデーターに指定してください

 

user_nameに一意性を付けたいと設けた部分

app/models/user.rb

validates :user_name, uniqueness: true

とした部分が警告が出ていました。

Rails 6で、MySQLを使っているときに、uniquenessのvalidationを使うと警告が出るようになっているようです。

 

どんな警告文?

昔々、Rails 5.2以前の仕様では、uniquenessバリデータはデフォルトで大文字小文字を区別する比較をしてくれていました。

つまり、'test'TEST'をデフォルトで区別しているということですが、デメリットがありました。

  • DB上のユニーク制約に一致しないため、バリデーションの結果に信用性が低い。
  • DB上のINDEXが効率よく使えないため、DBの負荷が大きくかかる。

 

現在のRails 6.1からの仕様では、uniquenessバリデータはデフォルトで大文字小文字を区別しなくなり、開発者が選択するように促しているようです。これが警告文の内容です。

 

警告文を消す

翻訳にあるように、`case_sensitive:true`オプションを一意性バリデーターに指定すると警告は消える。

validates :user_name, uniqueness: { case_sensitive: true }

しかし、

  • DB上のユニーク制約に一致しないため、バリデーションの結果に信用性が低い。
  • DB上のINDEXが効率よく使えないため、DBの負荷が大きくかかる。

のデメリットが有効になるそうです。このデメリットを解消する場合は、モデルのコードをいじるのではなくDB側のcollectionオプションにutf8_binを追加して「大文字小文字を区別するcollection」に変更する必要があるそうですが、手順が調べても分からなかったため上記のcase_sensetiveを追加しました。もし、今後分かったら書きたいと思います。

 

参考にさせていただいたページ

Rails 6.0で"Uniqueness validator will no longer enforce case sensitive comparison in Rails 6.1."という警告が出たときの対処法 - Qiita

 

Rails6 のちょい足しな新機能を試す81(case_sensitive編) - Qiita

クジラの練習帳011

練習帳011(二重ハッシュ)

f:id:whale_86:20201116192657j:plain

問題

配列の内部に、複数の有名人の情報をハッシュとして持つ変数star_dateがあります。

 

star_data = [
{star: {profile: {name: 'ヒカキン'}}},
{star: {profile: {name: 'ダウンタウン'}}},
{star: {profile: {name: '尾田栄一郎'}}},
]

 star_dateを利用して、全てのユーザーの名前だけが出力されるようにRubyでコーティングしてください。

 

出力結果は以下

ヒカキン 
ダウンタウン
尾田栄一郎

 

以下は解答

 

 

 

 

解答
star_data.each do |u|
puts u[:star][:profile][:name]
end

 ハッシュが複数重なっている場合は、取得したいキーまで連続して指定すると取得できます。

ハッシュ[取得したい値のキー][取得したい値のキー]

 またハッシュに格納されているため、each文で取り出す必要があります。

 

前回 クジラの練習帳010 - whale_86’s blog

次回 クジラの練習帳012 - whale_86’s blog

クジラの練習帳010

練習帳010(ハッシュの基礎を復習)

f:id:whale_86:20201116192657j:plain

puts hash.keys
puts hash.values

 上記のコマンドを実行した際に、

one
two
three
みかん
りんご ぶどう

とターミナルで表示されるような変数hashを作成するためのコードをシンボルを使って記述しましょう。

 

以下は解答になります

余談ですが、秋は果物の季節です。

私の住んでいる長野県はりんご🍎の産地で、長野県民はりんごを食べたら、品種がわかるという噂を聞いたので自分と家族で実験してみたところ8割強で的中しまして、自分でも驚きでしたが家族は当然のような顔でした(・・;)もしかしたら、りんご王者の青森県さんは余裕だったりして...。

 

家族それぞれ推しリンゴがありまして、私はシナノゴールドという品種が一番オススメでーす。

シナノゴールド | りんご大学

 

 

 

解答
hash = { one: "みかん", two: "りんご", three: "ぶどう" }

 シンボルを使用したキーの記述方法は、キーの後にをつけて定義します。

 例↓

hash = { キー: 値}

 

keysメソッドとvaluesメソッド

オブジェクト.keysで、ハッシュに含まれるキーの取得

オブジェクト.valuesで、ハッシュに含まれる値の取得

 

keyとvalueとは

valueとは格納したいデータのことで、keyはそれに対応するデータの名前のことです。

 

衣替えする時に、夏服Tシャツ(value)を[夏用A](key)、水着(value)[夏用B](key)と分けてボックスにしまうのと同じですよ☺️

 

 

前回 クジラの練習帳009 - whale_86’s blog

 

次回 クジラの練習帳011 - whale_86’s blog

 

クジラの練習帳009

練習帳009(処理に名前をつけて作る)

f:id:whale_86:20201111193655j:plain

以下のプログラムを実行するとエラーが発生します。

price = 300

def calculate_price_with_tax
  tax = 0.1
  puts price + price * tax
end

calculate_price_with_tax

エラーが発生した理由と正しいコードを答えましょう。

 

以下は解答になります

 

 

 

 

解答

エラー理由

メソッド外で定義した変数(price)がメソッド内で使えていない。

正しいコード

price = 300

def calculate_price_with_tax(price)
  tax = 0.1
  puts price + price * tax
end

calculate_price_with_tax(price)

 使えるようにするには、「引数」を使います。

引数は、メソッドの外から中に値を渡す役割を担います。

使い方は、2ステップ

メソッドの呼出、メソッド名(渡したい値)

メソッドの定義、def メソッド名(受け取った値を入れる変数名)

 

前回 クジラの練習帳008 - whale_86’s blog

次回 クジラの練習帳010 - whale_86’s blog

クジラの練習帳008

練習帳008(処理に名前を付けて作る)

f:id:whale_86:20201110192357j:plain

以下の条件にあったメソッドを作成してください。

メソッド名

bai_gaeshida

処理内容

1、ターミナルから数値を入力させる

2、入力した数値を2倍にして戻り値にする

 

*1

 ヒント

def メソッド名
  # メソッドの処理
end 

 

以下は解答になります

 

 

 

 

解答
def bai_gaeshida
  num = gets.to_i
num * 2 end

 処理1:ターミナルから数値を入力させる

getsメソッドにto_iメソッドを使いターミナルから数値の入力を受け付けます。

 

処理2:入力した数値を2倍にして戻り値にする

戻り値とは、メソッドから抜ける時に呼び出し元に返す値です。メソッドの最後の値が基本的に戻り値となります。

また、return文を使ってもいいです。return文を使うことでメソッドの最後でなくても戻り値にすることができます。

 

num * 2と最後に記載すれば、戻り値がnumを*2したものが返ります。

 

return文を使った場合

def bai_gaeshida
  num = gets.to_i
  return num * 2
end

 

前回 クジラの練習帳007 - whale_86’s blog

次回 クジラの練習帳009 - whale_86’s blog

*1:半沢直樹は見てなくて、小説だけ買って積み本になってます..

クジラの練習帳007

練習帳007(繰り返し処理)

f:id:whale_86:20201109193132j:plain

1〜10までの数値を順に足していった合計値を繰り返し処理を用いて出力するプログラムを書きましょう。

ヒント:times文を用います。

NGなプログラム

sum = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10

 

以下は解答

 

 

 

解答
sum = 0

10.times do |i|
  sum += i + 1
end

puts sum

 

解説
sum = 0

 一行目で合計値を入れる変数sumの初期値を0とします。

 

10.times do |i|
end

 times文を使用し、10回繰り返す処理を中に書きます。

 

  sum += i + 1

 自己代入演算子を使い、sumに を足していきます。i には、何回目の繰り返しか数値が入ります。

しかし、プログラムなので1回目の処理には0が i に入ってしまうため、+1をする必要があるのです。

 

最後にputsを用いて合計値sumを出力すればOKです!

今回は簡単でした!

 

前回 クジラの練習帳006 - whale_86’s blog

次回 クジラの練習帳008 - whale_86’s blog