二足のわらじ

〜プログラミングとSEOの勉強をはじめたミーハー26歳のメモ帳〜

よく使うマッチャ・メソッド・Faker集/deviseをテストでも/CarrierWaveを使った場合のRSpec

 

  

よく使うマッチャ

単体テストでのマッチャ

・eq

expect(assigns(:group)).to eq group

・include

expect(message.errors[:group]).to include('を入力してください')

・be_valid

expect(build(:message, image: nil)).to be_valid

・render_template

expect(response).to render_template :index

・be_a_new

expect(assigns(:message)).to be_a_new(Message)

・redirect_to     引数にとったプレフィックスにリダイレクトした際の情報を返す

expect(response).to redirect_to(new_user_session_path)

・change   引数が変化したかどうかを確かめる

expect{ subject }.to change(Message, :count).by(1)

 

 

フィーチャスペック(統合テスト)でのマッチャ

 

・have_no_content  

引数に指定したバリューを持つHTML要素が、

そのページに存在しないことを確かめる

expect(page).to have_no_content('投稿する')

 

 

 

よく使われるFactoryBotのメソッド

 

・build インスタンスを作る

・create インスタンスを作る(一時的にDBにも保存する)

・create_list  factory_botで設定されたリソースを元に配列を作る

・attributes_for オブジェクトを生成せずにハッシュを生成する

 

 よく使うFaker

 

password = Faker::Internet.password(min_length: 8)
name {Faker::Name.last_name}
email {Faker::Internet.free_email}
name {Faker::Team.name}
 

 

 

 

 

deviseをテストでも

手順①

specディレクトリの直下にsupportディレクトリを作成

その中に、controller_macros.rbを作成

controller_macros.rbで、loginメソッドを定義する

module ControllerMacros
  def login(user)
    @request.env["devise.mapping"] = Devise.mappings[:user]
    sign_in user
  end
end

 

 

手順②

rails_helper.rbに、以下2つを読み込む記述を追加

・deviseのコントローラのテスト用のモジュール を読み込む記述

・先ほど定義したControllerMacros を読み込む記述

 

RSpec.configure do |config|
  Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
  config.include Devise::Test::ControllerHelpers, type: :controller
  config.include ControllerMacros, type: :controller
  #〜省略〜
end

 

 

 

画像アップロード CarrierWaveを使った場合の、modelのRSpec

 

 参考記事: https://qiita.com/motty93/items/5cbc46ce79a502fcaa65

 

 

 

 

 

 

 

 

 

【学習75日】テーブル作成に役立つレファレンス型・form_forとは・formの種類(チェックボックス型)・エラー発見メソッド【応用37日】

 

■進捗

chat-spaceを作成する上での

チャットグループの新規作成・編集機能の実装

 

以下は制作を進める上で気になったことのメモ

 

■reference型とは?

マイグレーションでテーブルを作る時の reference型について

reference(参照する)

参考記事:https://qiita.com/ryouzi/items/2682e7e8a86fd2b1ae47

 

マイグレーションでカラムを作成する際に

stringやintegerは型として理解できるけれども

このreference型とはなんぞや??

 

f:id:vamnasocana:20191111094515p:plain

 

 

【概要】

・外部キーをとなるカラムを作成する時に用いる型

・カラム作成時にnull:false などの制約を設定することもある。

 外部キーを作成する際にはforeign_key: trueが必要になるが

 reference型を使わなければ外部キーにならない。

(t.integer  :user_id ,null:false ,foreign_key: true では外部キーにならない)

 

【特徴】

・userではなくuser_idというカラム名を作成してくれる

 (外部キーは●●_idというカラム名にする必要があるが

  reference型で設定すれば、●●だけで、勝手に_idをつけてくれる)

 

・インデックスを自動で張ってくれる

 (検索を高速化するためのインデックスも通常であれば

  index:trueで設定する必要があるが

  reference型で設定すれば、勝手にインデックスをつけてくれる)

 

 

 

 

■form_for

参考記事:https://www.pikawaka.com/rails/form_for

 

■form_forとは

・情報を送信するためのヘルパーメソッド

・入力フォームに必要なHTMLを簡単に作成可能

・テーブルにレコードを新規作成・更新する際に利用

 

form_forを何故使う?

・アプリの投稿フォーム作成

→直接inputタグでは書かない(セキュリティ的な観点から)

→ヘルパーメソッドを使う

 (form_tag、form_for、form_with等)

 

■ヘルパーメソッドをどう使い分ける?

form_for 

投稿フォームに入力されたものをテーブルに保存する場合

 

form_tag 

テーブルに保存する必要がないもの(検索フォームのようなもの)を作成する場合

 

form_with

form_forと同じ。rails5.1からはform_withを推奨

 

form_forの使い方

・erbの場合

<%= form_for('モデルクラスのインスタンス') do |f| %>
  フォーム内容
<% end %>

「モデルクラスのインスタンス

保存したいテーブルのクラスのインスタンス

 これからフォームに入力される内容が

 このテーブルの具体例(インスタンス)ですという意味

 

(例)

<%= form_for(@user) do |f| %>
  <%= f.text_field :name %>
  <%= f.submit %>
<% end %>

 

Hamlの場合

= form_for('モデルクラスのインスタンス') do |f| 
  フォーム内容

(例)

= form_for(@user) do |f| 
  = f.text_field :name 
  = f.submit

 

 

■引数の定義は忘れない

※引数(@user)を利用する場合は、

 コントローラーでインスタンス変数を宣言しておく 

def new
  @user = User.new
end

 

 

■form_forで投稿フォームを作成する際に必要となるHTMLタグ
メソッド 用途
f.text_field 一行のテキスト投稿フォーム
f.text_area 複数行のテキスト投稿フォーム
f.number_field 数値入力ボックスを生成
f.email_field メールアドレス入力ボックスを生成
f.check_box データベースの情報を使わないでチェックボックスを生成
f.collection_check_boxes データベースの情報を元にチェックボックスを生成
f.select 選択肢を作成
f.collection_select データベースの情報を元に選択肢を生成
f.file_field ファイル選択ボックスを生成
f.datetime_field 日時の入力欄を生成
f.date_select 日付選択ボックスを生成
f.hidden_field 非表示のフォーム
f.submit 送信ボタンの生成

 

■選択肢にチェックを入れる フォームを入れる

f.collection_check_boxes:

投稿フォームを作成するための、HTMLタグの1種

データベースの情報を元にチェックボックスを生成

 = f.collection_check_boxes :user_idsUser.all:id:name

 

 

■引数の説明

https://apidock.com/rails/v4.0.2/ActionView/Helpers/FormOptionsHelper/collection_check_boxes

collection_check_boxes(①object、②method、③collection、④value_method、⑤text_method、⑥options = {}、⑦html_options = {}、⑧&block)public

 

正直、上記サイトを見てもわからん!

・③は、選択肢として並べるもの

・④⑤が、「結局どのカラムに値を入れるの?」

・⑥以降はオプションなので省略可能

 

 

 

■エラーが見つけるメソッド errors.full_messages

errors.full_messagesメソッド

バリデーションエラーが発生した場合、

(入力された内容に妥当性がない!というエラー)

発生した全てのエラーメッセージを配列で取得。

 

        %h2"#{@group.errors.full_messages.count}件のエラーが発生しました。"
        %ul
          - @group.errors.full_messages.each do |message|
            %li= message

 

■バリデーションエラーとは?

参考記事:https://blog.ohgaki.net/there-are-3-types-of-validations#3

f:id:vamnasocana:20191110144851p:plain

 

 

 

 

■resources の7つのアクション

 

7アクション 役割
index リソースの一覧を表示する。
show リソースの内容を表示する。
new リソースを追加する。
create リソースを追加し、作成する。
edit リソースを更新するためのフォームを表示する。
update リソースを更新する。
destroy リソースを削除する。

 

 

問題1の解答と解説

問題1:userモデルを作成しましょう

模範解答

ターミナル
1
2
$ rails g devise:install
$ rails g devise user
1
2
3
4
5
6
7
8
9
class DeviseCreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :name,               null: false, unique: true, index: true
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

# 〜省略〜

解説

deviseで使用するモデルは、rails g devise <モデル名>コマンドで作成できます。

ターミナル上でrails g devise Userを実行し、Userモデルを作成しましょう。

作成されたマイグレーションファイルを開き、 t.string :name, null: false, unique: trueと記述しましょう。これで、マイグレーション実行時にnameカラムがNOT NULL制約・一意性制約付きで作成されます。

最後にマイグレーションを実行しましょう。

ターミナル
1
$ rails db:migrate

【学習72日】プルリクエストのフィードバック・deviseの導入の続き・rake routes【応用34日】

 

 

■プルリクエストでのフィードバック①mailerは使わないので削除

※今回はメールを送受信することはないので削除

 

Action Mailerとは

アプリケーションのメイラークラスやビューで

メールを送信することができるもの。

メイラーの動作はコントローラと似ている。

メイラーはActionMailer::Baseを継承し、

app/mailersに配置され、

app/viewsにあるビューと結び付けられます。

 

 

 

rails g mailer メイラー名 

をターミナルに入力することで

メイラーに必要な以下のものが出来る

create app/mailers/user_mailer.rb
create app/mailers/application_mailer.rb
invoke erb
create app/views/user_mailer
create app/views/layouts/mailer.text.erb
create app/views/layouts/mailer.html.erb
invoke test_unit
create test/mailers/user_mailer_test.rb
create test/mailers/previews/user_mailer_preview.rb

・コントローラ(のようなもの)

・ビュー

・テスト

 

実際に使うことになったら参考記事を見ながら設定する

参考記事:https://railsguides.jp/action_mailer_basics.html

 

 

■プルリクエストでのフィードバック②ハッシュロケットを修正

 

ハッシュロケット( => )の書き方はもう古いらしい。

ハッシュロケットをシンボル型(●●:▼▼)に書き換える

 

'class' => hoge

class: hoge

 

 

 

【元】

!!!
%html
  %head
    %meta{:content => "text/html; charset=UTF-8""http-equiv" => "Content-Type"}/
    %titleChatSpace
    

 

【エラー】

!!!
%html
  %head
    %meta{content: "text/html;charset=UTF-8"http-equiv: "Content-Type"}/
    %titleChatSpace

 

【動いた!】

!!!
%html
  %head
    %meta{content: "text/html; charset=UTF-8""http-equiv""Content-Type"}/
    %titleChatSpace

 

"http-equiv" を””で囲うことがポイントだった様子

シンボル型のキー(:の左側)に

-(ハイフン)が入っているとエラーになるので、

その際にはキーを””で囲う 

 

 

devise導入⑤ビュー画面を作成

ターミナルにて、rails g devise:views  コマンドを入力

deviseのビュー画面が一気にできる!

 

※コントローラーと同じ名前のビューを作成したい場合

→デフォルトのビューのディレクトリ(フォルダ群)を生成できる!

 rails g devise:views テーブル名

 

 

コマンドを実行すると割とたくさんディレクトリやファイルができる

新規作成画面、パスワードを忘れた場合の画面、パスワード変更画面など

ログイン認証に関わる画面がセットになって出来る!便利!!

f:id:vamnasocana:20191105215735p:plain

 



■rake routes実行後の画面

rails g deviseコマンドを実行した際に

devise_for メソッドが発動!

各種ルーティングが設定された。

deviseの各アクションに紐付くパス・prefixも

自動的に設定してくれる!

至れり尽くせり!!

f:id:vamnasocana:20191105224300p:plain

 

図1

f:id:vamnasocana:20191105224548p:plain

 

図2

GET

リソースの取得

POST

子リソースの作成、リソースへのデータ追加、その他処理

PUT

リソースの更新、リソースの作成

DELETE

リソースの削除

HEAD

リソースのヘッダ (メタデータの取得)

OPTIONS

リソースがサポートしているメソッドの取得

TRACE

プロキシ動作の確認

CONNECT

プロキシ動作のトンネル接続への変更

 

 

 

 

 

 

 

 

 

 

 

 

【学習71日】mixin活用方法・deviseの導入【応用33日】

 

■mixin を活用してdisplay:flexを効率的に設定

 

$prefixes-webkit--moz--ms--o-'';

@mixin flexbox {
  @each $prefix in $prefixes {
    display#{$prefix}flex;
  }
}

 

●1行目 

prefixesという変数を設定し、中に複数の値を代入(配列)

 

●2行目

flexbox という mixin(スタイルの定義)を設定

 

●3−5行目

おなじみのeach

 

@each  $●●(単数形の変数) in  %▼▼(複数形の変数(配列)) {

 配列の要素1つ1つに繰り返したい処理

 この中で変数を使いたい時には #{ 単数形の変数 }

}

 

つまり

 
-webkit--moz--ms--o- において
display:flex を設定する
 

という意味になる

 

 

■そもそもベンダープレフィックスとは何ぞ?

 

参考記事:http://www.htmq.com/csskihon/603.shtml

 

ベンダープレフィックス(接頭辞)とは

ブラウザベンダーが

GooglechromeInternet Explorer等のブラウザ提供元)

独自の拡張機能を実装したり

草案段階の仕様を先行実装する場合に

それが拡張機能であることを明示するために付ける

識別子のこと

 

将来的に仕様が変更されるリスクに備えて

独自拡張や先行実装のプロパティ名や

値の先頭に付けることが推奨されている

 

ベンダープレフィックスでは、

前後に「-」を付けたベンダー識別子(vendor identifier)で

ブラウザの種類を特定

-moz-  …… Firefox
-webkit- …… Google ChromeSafari
-o-     …… Opera
-ms-     …… Internet Explorer 

 

 

■display:flex をはじめとする並列表記

参考記事: https://mamewaza.com/support/blog/howto-use-flex.html 

ある要素に定義するだけで、その直下の要素が並列になる便利なスタイル。シンプルな導入であれば、CSSで「display:flex」というスタイルを指定するだけでOK。

 

 

使い方 解説
float:left法 並列させたい要素のスタイルにfloat:left 要素を回り込みさせることで並列レイアウトを実現
display:inline-block法 並列させたい要素のスタイルにdisplay:inline-block 要素をインライン化(左寄せの場合に左詰め)することで並列レイアウトを実現
table法 tableタグを利用するか
CSSのdisplay:tableを使って要素をテーブル化
要素をテーブル化することで、並列・縦列を操る

 

 

上記3つでも並列表記が可能。

flex : display では以下のような柔軟な対応も可能

 

・順番入替え

・均等配置

・自在な配置

・並列幅の指定

・並列・縦列・隙間埋めの合わせ技

 

 

■box-sizingプロパティ

参考記事:http://www.htmq.com/css3/box-sizing.shtml

 

ボックスサイズの算出方法を指定するプロパティ。

 

■box-sizing : content-box
パディングとボーダーを幅と高さに含めない(初期値)

 

■box-sizing : border-box
パディングとボーダーを幅と高さに含める

 

■box-sizing : inherit
親要素の値を継承する

 

 

値にborder-boxを指定すると、

widthとheightで指定する幅と高さがボーダーボックスになる。

内容領域にパディングとボーダーを含んだ範囲に対して

幅と高さが適用されるため、

パディングとボーダーの分だけボックスサイズが小さくなる

 

 

 

■devise とは??

参考記事:https://www.sejuku.net/blog/13378

 deviseとは、簡単に認証機能を実装できるgemのこと

 

 ■手順

devise導入①deviseのインストール

①-1 Gemfileに以下の内容を追記

#いずれの環境でも必要
gem 'devise'


#開発環境にのみ必要
group :development do 
     gem 'rspec'
end


#テスト環境にのみ必要
group :test do 
     gem 'rspec'
end


#本番環境にのみ必要
group :production do 
     gem 'unicorn'
end

 

①-2

ターミナルにて、bundle install

 

 

devise導入②deviseに必要な設定ファイルを作成

②-1

ターミナルにて、rails g devise:installコマンドを実行!

アプリケーションの中にdeviseの設定ファイルを作成する

 

【作成されるファイル】

config/initializers/devise.rb(deviseセットアップ等のために動くruby
config/locales/devise.en.yml(devise諸設定・履歴の為のファイル)

 

 

devise導入③deviseに対応したモデルを作成

③-1 

普通のモデルなら rails g model モデル名

deviseに対応したモデルなら rails g devise モデル名(user)

(モデル:DBとデータのやりとりをする役割を持つもの)

 

 

モデルが作成され

ついでにルーティングも自動で設定される!便利!

config/routes.rb
 
Rails.application.routes.draw do
  devise_for :users
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

 

・devise_for はdeviseのヘルパーメソッド

rails g devise モデル名コマンドを入力すると勝手に発動

・必要なルーティングを一気に作ってくれる

 

 

devise導入④テーブルを作成

rails g devise モデル名コマンドを発動しただけでは

モデル・データベース・ルーティングを設定しただけ。

まだテーブルは作れていないので、migrateファイルを編集し実行。

テーブルのカラムに制限をつける(NOT NULL制限・一意性制限など) 

 

db/migrate

def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :name,               null: falseunique: trueindex: true
      t.string :email,              null: falsedefault: ""
      t.string :encrypted_passwordnull: falsedefault: ""

 

 

migrateファイルを編集した後に

ターミナルにて、rails db:migrateコマンドを実行

 

 

 

devise導入⑤ビュー画面を作成

ターミナルにて、rails g devise:views users コマンドを入力

コントローラーと同じ名前のビューを作成したい

→デフォルトのビューのディレクトリ(フォルダ群)を生成できる!

 それがrails g devise:views テーブル名

 

以下のようなディレクトリができるはず

| app
| | views/
| | | users/
| | | | confirmations/
| | | | mailer/
| | | | passwords/
| | | | registrations/
| | | | sessions/
| | | | shared/
| | | | unlocks/

意気消沈…

 

 

f:id:vamnasocana:20191101224856p:plain

 

検証ツールを見つつ、sampleサイトの構造を理解して

なるほど!こういうことだったのか!と写経してやってみると

意図していない謎のエラーが????

 

Turbolinks ??

帰りの電車の中で原因を調べます

参考記事:https://www.ryotaku.com/entry/2019/01/15/213420

【学習68日】chat-spaceのサイト画面の制作⑦【応用30日】

 

■進捗

・左上の歯車アイコン・挿入完了 

   アイコンが親要素に重ならない…!

   というトラブルもあったものの

    position: absolute;でなんとか解決

 

・右下のアイコンの挿入と

 ラベルタグでリンクを作れるようにはなったけれど

 場所がずれる 

f:id:vamnasocana:20191031225930p:plain

 

■反省

・プルリクエストまで送る予定だったのにできず。

 アイコンを挿入する・アイコンにリンクを貼るなどの

 新しいことを勉強して時間がかかるのはもちろん、

 アイコンをおく場所の親要素の設置で時間がかかる。

 →一番はじめ、HTMLの大枠を作成する段階でうまくできなかった

 

■次回HTMLの大枠を作るときに活かす反省点

  →完成サイトの挙動に合わせて塊を作る

  (今回におけるサイドバーとメインチャット画面)

 

  →極力要素の高さ横幅を設定しなくてもいいように、

   position: absolute;を乱発しなくていいように 

   親-子-孫の関係性を考える

 

  →最初の大枠でいかに緻密に作るかが勝負

   「この部分の子になるはずだから後で追加すればいいか」

   という考え方だと後で絶対に後悔する

   「あっちを立ててばこっちが立たず」になる   

 

 

◾︎エラー①  並列では宣言できません?

Illegal nesting: content can't be both given on the same line as %div and nested within it.

 

f:id:vamnasocana:20191031213047p:plain

 

ドユコト?調べてみると、

「タグの中身は「タグのすぐ後ろ」か「より深いインデント」のどちらかに書く必要があり、併用はできません。」ということらしい。

 

「タグの中身(今回の場合seoという文字列)」 を

「タグのすぐ後ろ(同じ行)」に書くか

「より深いインデント(次の行で深いインデントで書くか)」が原因だった様子。

 

 

タグの中身①seoという文字列

タグの中身②ulタグの子要素

 この2つを揃えて書く必要がある、ということだったらしい!!

 

これを

f:id:vamnasocana:20191031214418p:plain

こう!

f:id:vamnasocana:20191031214438p:plain

 

 

 

 

 

◾︎エラー②  エンドポイントありませんよ?

/Users/natsumi/projects/chat-space/app/views/messages/index.html.haml:25: syntax error, unexpected keyword_ensure, expecting end-of-input ...:Util.html_safe(_erbout);ensure;@haml_buffer = @haml_buffer.... ... ^~~~~~

 

f:id:vamnasocana:20191031220814p:plain

 

25行目にエンドポイントがありません??

でもhamlではendタグとか必要ないよね??

何故?と思い調べると、

link_toメソッドの doが抜けていた…!

構文で抜け漏れがある場合は

「最終行に足りませんよ」というエラーが出るんですね…

 

 ◾︎エラー③ アイコンが親要素に重ならない!

 

アイコンは中央揃えにしたいのに!!

親要素は中央揃えになってるのに!!

何故?!

f:id:vamnasocana:20191031223327p:plain

 

調べてみると

アイコンにposition: absolute;を設定

すれば良いらしい。

 

アイコンのiタグにfaというscssが適用されている…? 

f:id:vamnasocana:20191031223608p:plain

 faというscssを作ってしまえ!!

f:id:vamnasocana:20191031223512p:plain

で・き・た!!

f:id:vamnasocana:20191031223446p:plain