TECH EXPERT 28日目

TECH::EXPERT

最近はアジアビルで作業しているが、人数配分大丈夫なんだろうか。
今朝なんか私を含めて朝礼4人しかいないんだが。
しかも私は朝礼ガン無視するので居心地悪い。(自分のせいだが)

昨日一昨日とサボった分を取り戻すべく朝礼夕礼で遊んでる時間はないのだ。
すまん。
とりあえず2日ビハインドから1日ビハインドまで追い上げた。
明日も真面目にやって追いつくだろう。

ruby

Array.index(object)

オブジェクトに一致した配列の番号を返す。
1番目が0。

array = [1,2,3]
array.index(3)
=> 2

三項演算式

条件式 ? 真の時の値 : 偽の時の値

if文と変わらないが、内容が簡潔であれば短くかける。

.first / .last

array.firstという風に使う。
文字通り配列の1番目の値を返す。lastなら最後の値。

引数にnumを指定でき、その場合は先頭からnum個の配列を返す。
要素数を超える数字を指定しても元の配列を返すだけ。

arr = [1,2,3,4,5,6,7,8,9]
arr.first  => 1
arr.first(3) => [1,2,3]

rails

Railsでは、ルーティングとルーティングに対応するビューさえあれば、明示的にコントローラのアクションを定義しなくても、ビューを表示することができる。

before_action

class MessagesController < ApplicationController
  before_action :set_group

  private
  def set_group
    @group = Group.find(params[:group_id])
  end
end

form_for ネストされたpath

= form_for [@group, @message] do |f| 
  = f.label :image, class:"chat__form__btn--image" do
    = fa_icon "image"
    = f.file_field :image, class: "hidden"

ルーティングでresources groups do resources messagesとネストさせた場合、createアクションへのpathがgroup_message_pathとなっている。
formに@messageしか与えないと、message_pathへリクエストを送ってしまうため、回避するために引数を2つ与えてgroup_message_pathへ誘導する。
ネストされたモデルに対してform_forを使用する場合は、親モデルのインスタンス(もしくは親モデルのid)を第1引数、子モデルのインスタンスを第2引数に設定する。

.strftime

string format timeだと思う。
日付や時間形式のデータを扱う際に任意のフォーマットへ変換する。

%Y/%m/%d/ %H:%M:%S

基本は%+大文字のアルファベットにしておけば、常時2桁(年は4桁)となる。
Yearを除き、可変表記にするには%-mや%-dのようにマイナスで繋ぐ。
mはMonthとMinutesでダブるため、month・dayはセットで小文字表記になる。

テストコード

テストコードを書く際の原則

  • 各exampleで期待する値は1つ
  • 期待する結果をはっきりわかりやすく記述
  • 起きて欲しいことと起きてほしくないこと両方をテストする
  • 境界値をテストする
  • 可読性を考えつつ、適度にDRYにする

RSpec

Rubyを元に作成されたテストに特化した言語。
rspec-railsというGemをインストールして使う。

bundle exec rspec

上のコマンドで実行する。

RSpecをgemファイルに書き込む

開発環境とテスト環境にしか必要ないので以下のようにする。
web-consoleも合わせてインストールする。

group :development, :test do
  gem 'rspec-rails'
end

group :development do
  gem 'web-console'
end

gemファイルに書き込みが終わったらbundle install

設定ファイルを作成

rails g rspec:install

specフォルダに以下が作成される。

create  .rspec
create  spec
create  spec/spec_helper.rb
create  spec/rails_helper.rb

rails_helper.rb

共通の設定を書いておくファイル。
各テスト用ファイルに読み込ませ、共通の設定やメソッドを適用する。

spec_helper.rb

rails_helper.rbと同じくRSpec用の共通の設定を書いておくファイル。
こちらはRSpecをRails無しで利用する際に利用する。

フォーマット指定

.specファイルにフォーマットを指定できる。
デフォルトではProgressになっている。

  • progress (略:p)
  • documentation (d)
  • html (h)
  • json (j)
--format documentation

progressの場合、以下のような意味。

  • . 成功
  • F 失敗
  • * 未実装
User
  #create
    is invalid without a nickname
  #create
    is invalid without a email (FAILED - 1)

↑documentation
↓progress

.F

ファイル管理

project/spec/models
project/spec/controllers
のようにそれぞれモデル・コントローラーで対応するフォルダを分ける。
specファイルは対応するクラス名_spec.rbという名前にする。

テストコード

describe "hogehoge" do
  it "1 + 2は3になること" do
    expect(1 + 2).to eq 3
  end
end

describeでテストとしての塊を作る。””内にはテストの説明を書く。
クラスみたいな感じ。
以下のdo~endまでがテスト内容。

it “”で実際に動作させるコードの説明を書く。
メソッドみたいな感じ。エクスペクテーションと呼ぶ。

実行内容はexpect()内に書き、equalで期待する結果を書く。
ここはメソッド内の実行式みたいな感じ。
equalのほか、incledeやvalidなどがある。マッチャと呼ぶ。

eqマッチャ

includeマッチャ

be_valid

it "is valid with nickname & email & password" do
  user = build(:user)
  user.valid?
  expect(user).to be_valid
end

be_validマッチャ

expectの引数にしたインスタンスが全てのバリデーションをクリアする場合にパスする。

expect(user).to be_valid

エラーメッセージの種類

  • is too short
  • is too long
  • can’t be blank
  • doesn’t match Password
  • has already been taken

shortやlongはエラーメッセージの配列の1つ目を取ってくる必要あり。
user.errors[:name][0]とせず、user.errors[:name]とした場合、
“is too short (minimum is 6 characters)” といった文字で返ってくる。

password_confirmationのエラーを誘導する場合、Pが大文字なのに注意。

factory_bot

インスタンスの生成を楽にしてくれる。
rspecと併用するので以下のようにgemファイルへ記入してbundle install

group :development, :test do
  gem 'rspec-rails'
  gem 'factory_bot_rails'
end

specディレクトリ直下にfactoriesディレクトリを作成。
テストしたいインスタンスの複数形のファイル名でRubyのファイルを作成。

例
spec/factories/user.rb

FactoryBot.define do

  factory :user do
    nickname              {"hogehoge"}
    email                 {"aaa@aaa.com"}
    password              {"12345678"}
    password_confirmation {"12345678"}
  end

end

こうすることで以下のように書ける。

describe User do
  describe '#create' do
    it "is invalid without a nickname" do
      user = build(:user, nickname: nil)
      user.valid?
      expect(user.errors[:nickname]).to include("can't be blank")
    end
  end
end

buildメソッド

引数にクラス名をシンボルで指定するとfactoriesファイルを参照し、自動的にインスタンスが生成される。インスタンス以外を続けて指定すると上書きできる。

user = FactoryBot.build(:user)
user = build(:user, nickname: nil)

buildなのは昔の名残???newと同義と思って良さそう。

createメソッド

createの場合はテスト用のDBに値が保存する。
ただし、テスト実行ごとにDB内容はロールバックされるため、保存した値は消えるので確認できない。DBの中身を確認したい場合はbinding.pry等で処理を止めること。

user = FactoryBot.create(:user)

FactoryBotの省略記法

helperのconfigureに下記を記述することで冒頭のようにbuild(:user)でインスタンスを作成できるようになる。

spec/rails_helper.rb

RSpec.configure do |config|
  #下記の記述を追加
  config.include FactoryBot::Syntax::Methods
end

HAML

form_for

アイコンにラベルを貼って、input操作をさせる方法

= form_for [@group, @message] do |f| 
  = f.label :image, class:"chat__form__btn--image" do
    = fa_icon "image"
    = f.file_field :image, class: "hidden"

これは下と同義。
  %label.chat__form__btn--image(for="file")
    = fa_icon "image"
    %input.hidden#file{type: "file"}

Gem

CarrierWave

gemのインストール

gem 'carrierwave'
gem 'mini_magic'

bundle install

uploaderの作成

rails g uploader アップローダーの名前

例
rails g uploader image

これをすると以下が作成される
create  app/uploaders/image_uploader.rb

モデルへの関連付け

mount_uploader :image, ImageUploader
例
class Message < ApplicationRecord
  belongs_to :group
  belongs_to :user

  validates :content, presence: true, unless: :image?
  mount_uploader :image, ImageUploader
end

app/uploaders/image_uploader.rbのminiMagickのコメントアウトを外す

class ImageUploader < CarrierWave::Uploader::Base
  # Include RMagick or MiniMagick support:
  # include CarrierWave::RMagick
  include CarrierWave::MiniMagick

  process resize_to_fit: [800, 800]

ついでにresizeさせたい場合や処理がある場合にはコメントアウトを外した箇所の下の任意の場所に書く。

CSS

overflow:

記事の内容がboxに収まりきらない場合にどうするかを指定する。
scrollにするとスクロールされるがスクロールバーが表示される。

overflow: scroll;
&::-webkit-scrollbar {
  display: none;
}

webkit系(safariやchrome)に関しては比較的簡単にスクロールバーを消せる。
class名:: -webkit-scrollbar{ dysplay:none;}でOK
ただし、firefox等の他系統には効かない。

英語

characters 文字数。letterじゃなくて。

HyperSwitch

最小化されたウィンドウには効かない
困った

コメント