コロナで無職になった私がエンジニアになるまで

コロナの影響で前職をクビになってから、エンジニアを目指してます。

Rubyの練習問題 ~while~

問題.1

以下の仕様を満たすアプリケーションを作成してください。

仕様

プログラムの実行を行うと、

①「[0]:カロリーを表示する、[1]:終了する」という選択肢が表示され、数字を入力することができる
② 0を入力すると「500kcal」と表示され、上記条件①が繰り返し実行される。
③ 1を入力するとアプリケーションが終了する

注意
・正しく動作している箇所までが採点対象となるため、必ず動作確認しながら進めること。
・エラーはインターネットで調べるなりして解決すること。
・エラーが出たままその先の実装をしないこと。

 

[自分の解答]

while true do
  puts "[0]:カロリーを表示する"
  puts "[1]:終了する"

  input = gets.to_i

  if input == 0
    puts "500kcal"
  elsif input == 1
    exit
  end 
end

while文でtrueの間は文の中の記述を繰り返す。
これを利用して、この中で条件分岐することでwhile文の無限ループの処理にはまらず
処理を適切に止めながら、ループさせることができる。

Rubyの練習問題 ~include?~

問題.1

任意の文字列にcatとdogの文字が含まれていたらtrue、
それ以外だとfalseを出力するメソッドを作りましょう。

 

[自分の解答]

def include_cat_and_dog?(str)
  if str.include?("cat") && str.include?("dog")
    puts "true"
  else
    puts "false"
  end
end

任意の文字列に要素が含まれているかどうかをチェックするためのメソッド。
オリジナルアプリを制作する際にも使用した便利なメソッド。
その時には配列に対して使用した。

Rubyの練習問題 ~クラスの継承~

問題.1

以下の仕様にしたがってコードを記述してください。

・Personクラスはプロパティ name, ageを持っている。
・StudentクラスはPersonクラスを継承している。
・Studentクラスにはintroduceメソッドが定義されている。実行すると
 「私の名前は◯◯です。◯歳です」と表示がされる。
・Studentクラスのインスタンスを作成し、introduceメソッドを実行する。

[自分の解答]

class Person
  def initialize(name, age)
    @name = name
    @age = age
  end
end

class Student < Person
  def introduce
    puts "私の名前は#{@name}です。#{@age}歳です"
  end
end

student = Student.new("テスト", 13)
student.introduce

親クラスであるPersonでinitializeで名前と年齢を渡して、インスタンス変数で定義。
これを子クラスのStudentに継承させ、introduceメソッドを定義し、その中で使用する。
親クラスを継承しているので、親クラスで定義されているインスタンス変数は、
子クラスでも使用することができることを利用した問題。

オリジナルアプリ作成記 10 ~ 画像の投稿 ~

チャット画面にて画像の投稿をできるように実装する。

Active Storage
Active Storageは画像を投稿するためのGem。
Railsに最初から統合されている。


Image Magick
Image Magickという画像加工ツールをダウンロードする。
画像の作成、サイズ変更、保存形式の変更などができるようになる。
Image MagickはソフトウェアなのでHomebrewでダウンロードする必要がある。
さらにこのImage Magickを使用するためには、Mini MagickというGemをインストールする。

おまけに画像のサイズ変更をするためには、ImageProcessingというGemをインストールする必要がある。

Image Magick = Mini Magick + Image Processing

とまぁこんな感じ。

image magickをターミナルでインストール。

% brew install imagemagick

Gemの追加。

gem 'mini_magick'
gem 'image_processing', '~> 1.2'

追加したなら、ターミナルでインストール。

% bundle install


これでようやくActive Storageを導入する準備ができた。

Active Storageの導入

% rails active_storage:install

するとマイグレーションファイルが生成されるのでマイグレートを実行する。

% rails db:migrate

 

画像の保存

画像を保存するためには対象となるモデルとアソシエーションを組む必要がある。
この場合、チャット画面(=Messageモデル)と組むことになる。

f:id:Kosei_Program:20210120212621p:plain

has_one_attachedを記述したモデルの各レコードは、それぞれ一つのファイルを添付することができる。
この場合はimageを添付することができるようになる。
=>Message.imageと記述することで、モデルに添付された画像へとアクセスすることができるようになる。

もちろんcontrollerでストロングパラメータの追記を行う必要もある。

f:id:Kosei_Program:20210117233844p:plain

前回も貼り付けた画像と同じだが
message_paramsの部分のpermitの項目にimageを追加している。

これで画像の保存ができるようになった。

保存した画像の表示

f:id:Kosei_Program:20210120213350p:plain

image_tagでimage要素を生成することができる。
複雑なディレクトリパスを指定しなくても、モデルから画像を呼び出して、引数に記述するだけで画像を表示することができる。
<%= image_tag message.image %>

これに加えて、画像が存在しない時に発生するエラーを防ぐために
条件分岐でattached?を記述する。
これにより画像が存在する場合のみ、image_tagが実行されるようになる。

画像の大きさは、variant(resize: ~~~)で変更することができる。
モデル.ファイル名.variant(resize: ~~~)


バリデーションの変更

画像かテキストどちらかの場合でもチャットできるように、バリデーションに条件分岐を追加する。
上の画像ですでに記述しているが、
validates :content, presence: true, unless: :was_attached?

def was_attached?
 self.image.attached?
end
の部分がこの条件分岐にあたる。
文章に対して、unlessを追加し、画像が添付されているか確かめるメソッドを定義し
添付されていなければ(unlessがfalse)文章に対してのバリデーションが行われる。
これにより、画像がなければ文章のみ投稿され、文章がなければ画像が存在しなければならないという処理になる。

次回は、実際にチャット機能を動かしてみる。

Rubyの練習問題 ~ハッシュ~

問題

ある映画のハッシュを定義し、格納されている「title」(タイトル)・「genre」(ジャンル)・「year」(公開年)の三つの要素の中から一つを取り出すプログラムを作成してください。

定義する変数

①movie = {"title" => "ハリーポッター", "genre" => "ファンタジー", "year" => "2001年"}

②ユーザーが入力するキーを、getsメソッドを利用し定義しましょう

 

[自分の解答]

movie = {"title" => "ハリーポッター", "genre" => "ファンタジー", "year" => "2001年"}

puts "以下の中から一つ選んで入力してください"
puts "・title"
puts "・genre"
puts "・year"

user = gets.chomp

puts "#{movie[user]}"

問題の定義があやふやだったので、メソッドも何も定義せずに記述した。
ハッシュから値を取り出すには、ハッシュ[キー]と記述する。

[正答]

def movie_info(movie, data)
  puts movie[data]
end

movie = {"title" => "ハリーポッター", "genre" => "ファンタジー", "year" => "2001年"}

puts "以下から一つを選んで入力してください。
  ・title
  ・genre
  ・year"

info = gets.chomp

movie_info(movie, info)

メソッドを定義すると、上のようなプログラムになる。
メソッドの第一引数にハッシュ、第二引数に入力した値を渡す。
処理内容自体は自分の書いたプログラムと同じ。

 

Rubyの練習問題 ~shuffle~

問題.1

誕生日を入力すると、今日の運勢を表示してくれるプログラムを作ってください。
占い結果については、以下のアルゴリズムにて判定することとします。
必ず、メソッドを作成しそれを呼び出すように記述してください。

・引数として誕生日の数字を受け取る(例:4月3日なら403、11月15日なら1115と入力)
・誕生日の数字に、乱数で生成された0 ~ 9の数字のいずれかを掛け算し、その後4で割った時の余りを算出
・シャッフルした占い結果を格納した配列から、上記の数値の順番の値を取り出す
 ["凶","中吉","吉", "大吉"]

 

[自分の解答]

def lacky(birthday)
  lacky_result = ["凶","中吉","吉", "大吉"]

  num = (birthday * rand(10)) % 4

  lacky_random = lacky_result.shuffle
  puts lacky_random[num]
end


puts "誕生日を入力してください"
birth = gets.to_i

lacky(birth)

配列に対して、shuffleメソッドを使用するとその配列の中身をシャッフルしてくれる。
というかこれくらい単純なプログラムならば、わざわざshuffleを使用しなくても
randで値はランダムに出力される。
これを利用して、配列の添字として渡せば一応値はランダムになる。

オリジナルアプリ作成記 9 ~チャット画面の実装~

前回でチャットルームへのアクセス制限を行った。
その際には、チャットルームへのアクセス制限というよりは、
チャット画面への移動を制限することでアクセス制限をした。
=> チャット機能のコントローラーへ記述。

チャット画面

f:id:Kosei_Program:20210118231446p:plain

f:id:Kosei_Program:20210118231526p:plain

実際の画面はこんな感じ。
ビューファイルのコードは

f:id:Kosei_Program:20210118231657p:plain

form_withで実際にチャットのメッセージを投稿する際にmodelにroomとmessageに対して送信していることに注意する。
これはroomにmessageをネスト、ルーティングを入れ子しているためにこのように記述する必要がある。
=> roomに属するmessageというように親子関係である。
この@roomにはどのチャットルームか、@messageにはMessageモデルからのインスタンスを予めセットしておく必要がある。
=> コントローラー(indexアクション)でセットする。

f:id:Kosei_Program:20210117233844p:plain

投稿された全てのメッセージを表示するために@messagesとして、
@messages = @room.messages.includes(:user)
取得した特定の部屋@roomに紐づいている、messages(全てのメッセージ)を取得。
=> アソシエーションを組んでいるためにこのような記述が可能。
さらにこの取得したメッセージにはユーザーの情報も取得したいので、
N+1問題(必要なデータを取得するために何度もアクセスすること)を防ぐために
includesメソッドを使用して、取得する。
=>メッセージに紐づいたユーザー情報も一度に取得することが可能。

メッセージの投稿

実際にメッセージを投稿(保存)する際には、
投稿する目的の部屋(@room)を取得して、
それを利用して、投稿するメッセージ(@message)を
@room.messages.new(message_params)として保存。
message_paramsのストロングパラメーターには、
messageモデルへ、本文と画像(後に実装)と投稿するユーザーのidを一緒に保存する。
保存に成功すれば(条件分岐)、投稿したページ(チャット画面へ)
失敗すれば、その時点で投稿されていたメッセージを全て取得して表示。
=>renderでindexアクションへ持っていく。

これはindexのビューファイルに
<%= render partial: 'message', collection: @messages %>
と記述して、このcreateアクションのrenderをここに持っていくといったイメージ。

次回は画像投稿についてまとめる。