学習の書き留め プログラミング勉強中

プログラミングで学んだことを日記として残して行こうと思います

今日の学習

今日学んだこと 2021/01/14

学習項目

オブジェクト指向
正規表現
railsの基本概念

学習内容

オブジェクト指向

アプリケーションを作成するときに、登場する役割ごとに分けて実装する方針のこと設計思想の一つ
メリット
実装がしやすくなる
後からコードを改変するときも他のオブジェクトに影響しない

単一責任の原則

アプリケーションの設計を考える上で、必要となる決まりの1つ。
「1つのクラスは1つの振る舞いしか持たない」という原則の下設計をする。

正規表現

文字列の一部分を抽出・置換したり、文字列が制約を満たしているかを調べるための表現方法
例えば、
090-1234-5678 09012345678 はコンピューターは別物と認識するから、合わせるよう組み替えたりする技術

上のパターンでは

irb
tel = '090-1234-5678'
tel.gsub(/-/'')

でできる。
.subは何かを何かに置換したい時に使えるもので、

変数.sub(/置き換えたいもの/'取り替えるもの')

と記述する。.gsubは置き換えたいもの全てを対象にする。
例のものはハイフンを空白に置き換えるという意味になる。

パスワード等が問題なく入力できているか調べる方法

パスワードやメールアドレスこれらの字数制限や@の有無はPC上でどのように認識しているのか。

まず、与えられた文字列に対して、内容をチェックするmatchメソッドがある。

word = 'hello, world'
word.match(/hello/)
=> #<MatchData "hello">

このように、match(/検索ワード/)でその文字列に検索ワードがあるかどうかを調べることができる。 その際にヒットしたワードはMatchDateという種類のオブジェクトで返される。
まあMatchDateに変換される感じかな、、、多分

これを使うことによって、文字列に何が入っているかを調べる。

表現方法のいくつか

[a-z] : aからzまでのどれかを指す
[\d] : 数字を指す
{n, m} : 少なくともn回多くてもm回を指す
i : 大文字、小文字を区別しない時に入れる

これらを使って、パスワードが満たしているかどうかを調べられる

password = '好きなパスワード'
password.match(/[a-z\d]{8,16}/i)
=> MatchDate or nil

上記の書き方を日本語にすると、
aからzの英語、数字を含む、8文字から16文字の大文字小文字は両方入っていてもいいパスワード
になる

. : ハイフンやピリオドなど含めた全ての英数字を指す
+ : 直前の文字が1回以上の繰り返しを指す

これを組み合わせて、

.match(/@.+/)

とすると、@以降に1文字以上の繰り返し、つまり@以降に何かの文字がある
と言うことになる。

\A : 直後に置いた文字を文字列の先頭に持つことを指す
\z : 直後に置いた文字を文字列の末尾に持つことを指す
[ぁ-んァ-ヶ一-龥々] : あらゆる日本語に対応することを指す
?= : 直後に設定した文字でチェックをかけて、設定した文字が続く文字列が存在する場合を指す
* : 直前の1文字が0回以上続く場合を指す

.match(/\A([a-z.\d])+(@.+)+([?=com jp])\z/i)

組み合わせると、おそらくこう言うのもありのはず。

railsの基本概念

レールズには言わずもがなDRYの概念があり、同じ情報を繰り返し定義しないと言うものがある
それ以外にフレームワークの概念として、
CoCと言う概念があり、設定よりも規約を優先すると言うものがある。これは簡単に言うと、多分自分で何か設定するより、そもそもあるものを先に使いなさいと言う意味だと思います。
これにより、開発スピードが上がり質も担保できることや、規約は開発者同士の共通認識であるため可読性が向上するなどのメリットがある。

まとめ

railsの基礎概念やそもそものrubyの概念、今後使っていくであろう正規表現の技術と深いところに近づいてきた。ゆっくり、ゆっくりと自分のものにしていく。

今日の学習

今日学んだこと 2021/01/13

学習項目

レスポンシブデザイン ruby応用

学習内容

レスポンシブデザイン

レスポンシブデザインとはざっくりいうとPC、タブレットスマホで表示するデザインを変えること。
画面の大きさが違うから、それに合わせないと見づらいから変えようって話ですね。特にPCは横長に対して、スマホって縦長だし。
方法は簡単で、CSS

@media(max-length: 表示を変えたい長さ) {
  その大きさを指定する
  .img {
    width: 50%;
  }
}

こんな感じに記述します。この@media.....のことをメディアクエリといい、表示を変えたい長さをブレークポイントという。

ruby応用

case文

まず、条件処理で一般的なものだと、if文がある。今日習ったのは、case文、書き方は

color = "red"

case color
when blue
 puts "進める"
when "yellow"
 puts "危ない"
when "red"
 puts "止まれ"
else
 puts "???"
end

というように、それぞれの状況に応じた処理で記述できる。実践だと、もしかしたら、ゲストユーザーor無料会員ユーザーor有料会員ユーザーの時とかの処理で使えそうとうという印象でした。

繰り返し処理

繰り返し処理だと、今まででは、eachやtimesを習っていたが、今日は新しく、whileを学んだ。

while 条件式
 # 条件が真である時に繰り返す処理
end

と書き、これの条件式を繰り返す処理と合わないものにすると無限ループが起こる。例えば

number = 0
while number == -1
  puts number
  number += 1
end

これだと、数は永遠に-1になることはないため、常に処理が行われるというループに陥る。実践でのイメージはつかないが使えるようにしておく。
抜け出す方法としては、breakを記述しておくことで、処理を止めることができる。

number = 0
while number == -1
  if number == 100
    break
  end
  puts number
  number += 1
end

クラスの継承

クラスは継承することができ、継承することで元の性質を引き継ぐことができる

class 子クラス < 親クラス

end

タスクの実装

Rakeタスクと呼ばれる、タスクを簡単に実行できるrubyツールがある。これは、railsにも組み込まれている。
タスクの生成

# Rakeタスク用のRakeファイルを作成
% rails g task タスクファイル名

これで、lib/tasks/ディレクトリにタスクファイル名.rakeというファイルが作成される。
また、environmentメソッドを記載することで、アプリケーション環境(今回はrails)に依存した処理を記載することができる。

namespace :ここにグループ名を記述する do
  desc "ここに処理の説明を記述する"
  task タスク名: :environment do

         ここに実際のタスクを記述する

    end
  end
end

呼び出し方

# Rakeタスクの実行
% rails namespaceの名前:taskの名前

例外処理

期待しない結果が起こった時に、どのような処理をするのかを決めることができるのが例外処理になる。期待しない結果は主にエラーが起こった時のことを言うが、基本はエラーが起こった時はその時点で処理が止まる。
しかし、処理が止まることで困ることがある場合、例外処理を実装する。 基本的には
①例外が起こった後、その処理だけ別の処理をして、元の処理に戻る場合と
②例外が起こった後、その処理だけ別の処理をして、元の処理自体を全て無効にして中止する場合 の二つのパターンがある。
つまり
通常
11111111111(エラー)00000000000となるが

1111111111(エラー→別の処理)1111111111

1111111111(エラー→別の処理→最初の処理もリセット)
と言うようなイメージ

元の処理に戻る場合
begin
  # 想定される例外
rescue
  # 例外が発生した時にrescue以下の処理が呼ばれる
end

のようにbeginで例外が起こると想定される処理を書き、rescueで例外が起こった後に行われる処理を書く。 また、raiseを使うことによって意図的にエラーを発生させることができる。

raise 発生させたい例外クラス, 'エラーメッセージ'
元の処理も全て無効にする場合
ActiveRecord::Base.transaction do
  # 処理1
  # 処理2
  # ...
end

のようにトランザクションを利用する。

まとめ

cssでユーザーに合った表示にできる。
rubyrailsは奥が深い。でもゆっくり頑張る!

今日の学習

今日学んだこと 2021/01/10

学習項目

画像のアップロード方法

学習内容

通常何もしない場合、画像はurlを入れて、任意の画像を表示できる。
自分のファイルにある画像を送る方法を学んだので、まとめていく。

まず、rails でファイルのアップロードができるgemはActive Storageで元々はインストールがが必要だっだらしいが、現在は必要ない。
画像に加工できるツール、gemのインストールを行う必要があり、 ImageMagick: コマンドラインから画像に処理を加えることができるツール
MiniMagick: ImageMagickの機能をRubyで扱えるようにしてくれるGem
ImageProcessing: MiniMagickでは提供できない、画像サイズを調整する機能を提供するGem
をそれぞれ、インストールする。

ImageMagick

brew install imagemagick

MiniMagick、ImageProcessing はそれぞれ、Gemfileに記述

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

その後、Active Storageのインストールし、マイグレーションファイルができるので、マイグレートする

rails active_storage:install
rails db:migrate

保存したい、モデルとファイルを紐付ける

class モデル < ApplicationRecord
  has_one_attached :ファイル名
end

画像の表示は image_tag を使う

# ファイルをモデルから指定する場合
<%= image_tag モデル.画像ファイル %>
<%= image_tag sample.image %>

# app/assets/ディレクトリ下の画像ファイルパスでも指定できる
<%= image_tag 画像ファイルのパス %>
<%= image_tag "image.png" %>

# 以下の記述で、画像が無い場合、表示しないようにできる
<%= image_tag sample.image, if message.image.attached? %>

画像の加工は variantメソッド を使う

モデル.ファイル名.variant(resize: '幅x高さ')

まとめ

画像を送る手順を覚えれば、インスタも夢じゃない!!

今日の学習

今日学んだこと 2021/01/06

学習項目

deviseの復習とフロントページの実装

学習内容

今日は新規で学んだことはないんだよね。書くのやめようかと思ったけど、日記だしこういうのってとりあえず書く習慣をつけないと大事なこと書けないと思うので。
フロントページの実装では内容はわかるけど、模範解答と比べるとクラス名がダサかったり、階層が足りなかったりした。発想が足りなかったり、穴が多いなと感じた瞬間でした。
ユーザー管理ページではdeviseがやはりわかりきってない。導入は問題ないが、値の取得の書き方とか細かいところが甘いと思った。数だと思うから。回数重ねるしかないかな。
あと、link_toの書き方が咄嗟だとわからないこととか知識がついているとは思うけど、中途半端なのが悔しい。知識の身につき方が、、、大丈夫なのかなって少し不安になります。3歩進んで二歩下がってる感じかな。
文字にしたことで、少しは整理できただろうか。一歩は進んでる。ゆっくり頑張ろう。うん。大丈夫。

まとめ

気持ちの整理も、言葉にすることも、日記に書くこともきっとどれも大切だと思いました(^ ^)

今日の学習

今日学んだこと 2021/01/04

学習項目

データベース設計

学習内容

今後カリキュラムで作るアプリのデータベースの設計を行った。
今後解説があるとは思うが、自分でも考えることで、今後につなげていく。
特に今回の設計では中間テーブルというのが鍵を握る。
基本的にはデータベースのアソシエーションは1対多又は多対1で作る。
しかし、多対多の条件が発生する場合がある。
例えば、インスタのタグの機能も、一つのツイートや記事に対して多くつけることができるし、タグ自体も記事に多く結びついている。
そういった時は中間に一つ振り分けるデータベースを作り、どの記事がどのダグと結びついているか判断する。
そうすることで、中間テーブルを挟んで、1対多の関係を作ることができる。

まとめ

1対多を作るための発想と工夫がすごい

今日の学習

今日学んだこと 2021/01/03

学習項目

統合テストコード(RSpec

学習内容

基本的な書き方は変わらないが、統合テストの場合は流れで行っていく。

it '正しい情報を入力すればユーザー新規登録ができる do
  # 1.トップページに移動する
  visit root_path
  # 2.トップページにサインアップページへ遷移するボタンがあることを確認する
  expect(page).to have_content 'sign_up'
  # 3.新規登録ページへ移動する
  visit new_path
  # 4.ユーザー情報を入力する
  fill_in 'Name', with: 'sample'
  # 5.サインアップボタンを押すとユーザーモデルのカウントが1上がることを確認する
  expect{
    find('sample[name="botton"]').click
  }.to change { Sample.count }.by(1)
  # 6.トップページへ遷移したことを確認する
  expect(current_path).to eq root_path
end

適当にテストコードを書いたが、こんな感じ。
1.はvisitを使うことによって、実際にトップページに移動する。
2.はそもそもトップページに新規登録のボタンがあるかを確認する。
3.は登録ページへ移動する。
4.はおそらく入力フォームがあるので、それを入れる。
5.は新規登録のボタンを押したことによって、ちゃんとデータベースに登録されたのか、レコード数によって判定する。
6.は登録完了後、トップページに移動したかを確認している。

こんな感じで、人がクリックしたしとかするのを文字コードで実際にパソコンにやってもらう感じです。トップページに行ったな。ボタンある。次いこう。的な感じのを自動でしてくれます。
テストを実行すると、超高速で動き出すので面白いです。こうなってくると、やはりexampleの整理、何をテストするのかがかなり大事になると思いました。
全く太刀打ちできなくなる訳ではなく、binding.pryを途中に入れることで途中で処理が止まるのでやりたい処理を打ちながら確認できます。

まとめ

パソコンが"うらああああああ"って感じでテストしてるかんじがかなり好き

今日の学習

今日学んだこと 2021/01/02

学習項目

単体テストコードの概要(RSpec

学習内容

RSpecを使ったテスト

RSpecの導入方法

①Gemfileに記述

# group :development, :test のグループ内に記述
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'rspec-rails', '~> 4.0.0' # RSpecの導入
  gem 'factory_bot_rails' # テストで使うインスタンスをまとめてくれるGem
  gem 'faker' # ランダムな値を生成するGem
end
# 省略

②bundle install 実行

RSpecのインストール

rails g rspec:install

④テストコードの結果をターミナル上に可視化するための設定をする

# .rspec
--require spec_helper
--format documentation

モデルの単体テスト方法

①テストファイルの作成

rails g rspec:model モデル名

②テストで使うインスタンスの生成

# spec/factories/モデル名.rb
FactoryBot.define do
  factory :モデル名 do
    name         {Faker::Name.initials(number: 文字数)}
    email         {Faker::Internet.free_email}
    password  {Faker::Internet.password(min_length: 文字数)}

③テストコードの記述

#spec/models/モデル名_spec.rb
require 'rails_helper'
RSpec.describe モデル名, type: :model do
  before do
    @インスタンス名 = FactoryBot.build(:モデル名)
  end

  describe 'ユーザー新規登録' do
    it "nameが空だと登録できない" do
      @インスタンス名.name = ""
      @インスタンス名.valid?
      expect(@インスタンス名.errors.full_messages).to include ("name can't be blank")
    end
  end
end

まず before do ... end の間の記述は②で書いたインスタンスを生成する。
describe はどの機能に対してテストを行うのグループ分けをし、
細分化、特定の条件を指定してグループ分けをする場合、入子構造にしてcontextのなかに、条件を記載する。
入子構造の it でどのような状況のテストをするのか明記する。itで分けたグループのことを example と呼ぶ。 今回はnameが空の状態だと登録できないのかを検証するために、
@インスタンス名.name = "" でnameを空に上書きする。
その後に @インスタンス名.valid? でバリテーションを実行してエラーがあるかどうかを検証する。
最後に @インスタンス名.errors.full_messages で実際のエラーメッセージを出し、その中に、nameが空の時に出るエラーメッセージ "name can't be blank" が含まれているか include を使って検証する。(同一かどうかを検証する場合は eq )

まとめるとこの処理はnameが空の状態でバリテーションを実行した際に出てくるエラーメッセージが、nameが空の時にでてくるエラーメセージと同一のものか? と言う内容を検証していることになる。

④テストコードの実行

bundle exec rspec spec/models/モデル名_spec.rb

コントローラーの単体テスト方法

①テストファイルの作成

rails g rspec:request コントローラー名

②テストコードの記述

#spec/models/モデル名_spec.rb
require 'rails_helper'
RSpec.describe コントローラー名Controller, type: :request do
  before do
    @インスタンス名 = FactoryBot.create(:コントローラー名)
  end

  describe "GET #index" do
    it "indexアクションにリクエストすると正常にレスポンスが返ってくる" do 
      get root_path
      expect(response.status).to eq 200
end
    it "indexアクションにリクエストするとレスポンスに投稿済みのツイートのテキストが存在する" do 
      get root_path
      expect(response.body).to include @インスタンス名.text
    end
  end
end

まず、今回はツイートなどが存在するかを調べるため create で情報をデータベースに保存する。(テストようのためテストのたびに消去される)
HTTPメソッドを使って、リクエストを送る。 responce でそのリクエストに対して、のレスポンスを受け取る。HTTPステータスコードだと、200が処理の成功のため responce.status が 200 と同一かと言う検証を行う。
もう一点のは response.body でHTMLの情報を取得し、テストに期待する情報が含まれているかと言う検証を行う。

④テストコードの実行

bundle exec rspec spec/models/コントローラー名_spec.rb

以上があらかたのテスト方法になる。

まとめ

地味だけど大切。