気ままに気ままのエンジニアブログ

定期的に得た知見を気ままに発信中

【spec】factory dateの一部を変更したテストの書き方

こんにちは。

最近1週間が秒で終わります。もう29歳なので年でしょうか。。

どうもハチマキです。

はじめに

先日deviseを実装し、factoriesのUserモデルスペックに「confirmed_at Time.now」を定義しました。
こう定義することで、すでに本登録済み状態となり、仮登録状態から本登録済みにするテストを書きたい時に、また新しくfactoriesにUser情報を定義する必要があるのか??と思い調べてみました。

結論、新たに定義する必要はなく解消できたので、この方法について書いていきたいと思います。

では早速行きましょう!

本日の概要 : factory dateの一部を変更したテストの書き方

事象

※deviseを実装した時を想定して進めていきます

ユーザー仮登録から本登録までのfeatureテストを追加したい。
すでに「confirmed_at Time.now」を定義したことによって、すでに本登録済みのなので、仮登録状態を作るためにfactoriesで定義したuserデータの一部変更したい。

実行方法

実行方法を調べていくと、解決方法は3つほどあることが見えてきました。
その中でも簡単にできる「specファイルに定義」する方法を紹介していきます。

・spec/factories/user.rb

factory :user, class: 'User' do
   sequence(:firstname) {|n| "hachimaki#{n}"}
   sequence(:lastname) {|n| "makitai#{n}"}

   email { Faker::Internet.email }
   gender 'man'
   birthday Date.new(1991, 1, 18)
   confirmed_at Time.zone.now
end

・spec/features/user_spec.rb

feature 'user.rb', js: true do
 let!(:admin) { create(:admin_user) }
 let!(:user) { create(:user, confirmed_at: nil) }

 before do
  sign_in(admin)
 end

 context '~~' do
  scenario '~~ do
   visit '~~'
   click '登録する'
      
   expect(page).to have_content '登録完了'
  end
 end
end

specファイルで引数に変更したい属性と値を渡すことで、すでに定義したデータの一部を変更できます。

【Rails】ポップアップ(確認ダイアログ)を表示する

こんにちは。

最近モンスターを飲み始めてから、目覚めが悪くなりました。

どうもハチマキです。

はじめに

ポップアップを表示する際にどうやって表示するんだろ?と思ったため、その方法について今回書いていきたいと思います。

▽イメージはこちら。
f:id:hachimaki37:20200910180148p:plain

実装前は、jquery(JS)を駆使して実装していくのか?なんて思っておりましたが、
確認ダイアログを使えば、簡易的なものがいとも簡単に出来ました。

では早速行きましょう!

本日の概要 : ポップアップ(確認ダイアログ)を表示する

事象

削除する際や変更する際に、確認用のポップアップみたいなものを表示したいけど、一から作るの?なんか定義するの?どうやってやるんや。。?

表示方法

・link_toの場合(上記イメージ図)
= link_to "投稿", ~~_path, data: { confirm: 'そこに愛はあるんか?'}, class: "btn btn-lg btn-primary"

・form_forの場合
= form_for(@user, method: :PUT) do |f|
 =  f.submit '更新', data: { confirm: 'そこに愛はあるんか?'}

どちらも同様に追記するだけで、確認ダイアログが表示されるようになります。
※「confirm: ~ 」オプションは非推薦となって、「data: ~ 」記述に変わったみたいです。

補足

確認ダイアログのデフォルトは非常に簡易的です。
Bootstrapを利用してモーダルウィンドウ風に表示にしてくれるgemがありますので、ぜひこちらも試してみてはいかがでしょうか。

▽こちらの記事を参考にされていただきました。
data: {confirm: }の確認ダイアログをいい感じにする【Ruby on Rails】 | FuchiAz.com

同様に簡単に出来ます!

【Rails】devise「メール認証機能」の仕組みについて

こんにちは。

やっと夏が来たと思いきやもう秋ですね。今日から栗開きです!

どうもハチマキです。

はじめに

今回新たにdevise機能を実装してみました。
deviseの実装方法の記事は色々あったため、今回はデータの流れからdeviseの仕組みを読み解いていきたいと思います。

もし実装方法が知りたいという方であれば、参考にさせて頂いた記事を載せておりますので、そちらを見ていただけたらと思います。

では早速行きましょう!

本日の概要 : メール認証機能「devise」の仕組み

事象

会員登録などでよく使われるメール認証機能(会員登録前にメール送信を行い、リンククリックによって本登録ができる)を実装したい!
そんな時に役立つのが、今回のdeviseです。

仕組み

deviseの実装を進めていくと、db:migrateを行い下記4つのカラムをDBに追加していきます。

  • confirmation_token
  • confirmed_at
  • confirmation_sent_at
  • unconfirmed_email

メール認証を実装する上では、追加したconfirmation_tokenカラムconfirmed_atカラムが肝になります。

consoleでデータの流れをみる(会員登録を想定し進めていきます)


deviseを実装し、登録フォームで登録を行うと、まず追加したカラムのconfirmation_tokenにパラメータが入ります。
これが言わば、仮会員登録の状態です。

$ rails c

[1] pry(main)> User.last
  User Load (0.8ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` DESC LIMIT 1
=> #<User id: 1, email: test@gmail.com", confirmation_token: "test-hoge123450", confirmed_at: nil, confirmation_sent_at: "2020-09-05 01:42:40", unconfirmed_email: nil>


登録を行うことで、SMTPから登録したメールアドレスにメールが送信されます。
送信されたメールのリンクをクリックすることで、confirmation_tokenに入ったパラメータがnilになり、confirmed_atにリンクをクリックした日時が入ります。
これが、本会員登録(メール認証が完了)した状態になります。

[2] pry(main)> User.last
  User Load (0.8ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` DESC LIMIT 1
=> #<User id: 1, email: test@gmail.com", confirmation_token: nil, confirmed_at: "2020-09-05 01:44:31", confirmation_sent_at: "2020-09-05 01:42:40", unconfirmed_email: nil>


よって、ブラウザではログインができる状態になります。

この一連のデータの流れがメール認証機能の仕組みです!結構シンプルでした。

カラムの補足
  • confirmation_sent_at: "2020-09-05 01:42:40"
    • 認証用メールが送られた日時のデータ
  • unconfirmed_email: nil
    • メールアドレスの変更時に使用。確認用メールを送信し、そのリンクを実行した場合に値が変更されます(※今回のメール認証では不要)

【spec / capybara】セレクトボックスなどの要素を評価したい場合のテスト方法

こんにちは。

腰の痛みを軽減させるためにマッサージ機を当て続けたら痛みが倍増しました。

どうもハチマキです。

はじめに

今回はrspecの振る舞いテストで、下記のようなselectの値が選択されているかというテストを書きたい!けど、エラーが出ました。
ググった結果解消できたので、解決方法について書いていこうと思います。

本日の概要 : セレクトボックスなどの要素を評価したい場合のテスト方法

事象

フォームで入力した値をselectできるようにした時に、expect(page).to have_text('test1')のように書いたら普通にエラーになりました。
原因は単純にtextではないから。でしょうか。

・こんな感じの画面をテストする
f:id:hachimaki37:20200821122527p:plain

エラー例

specファイル

require 'spec_helper'

feature 'フォームをテストする', do
  scenario 'selectの値が表示させる' do

  fill_in 'test', with: 'hogehoge,fugafuga'

  click_on '更新'

  expect(page).to have_text('hogehoge')
  expect(page).to have_text('fugafuga')
 end
end

ターミナル

Failures:

  1) フォームをテストする selectの値が表示させる
 Failure/Error: expect(page).to have_text('hogehoge')
       expected to find text "hogehoge" in ~~~~~~~~~~

...

Finished in 32.61 seconds (files took 35.01 seconds to load)
1 example, 1 failure

解決方法

have_xpathを使用し、要素の属性の値を評価するとテストは通ります。
XPath (XML Path Language) とは:SQLのSELECTのように、条件を指定してXMLデータを取得することができる

specファイル

require 'spec_helper'

feature 'フォームをテストする', do
  scenario 'selectの値が表示させる' do

  fill_in 'test', with: 'hogehoge,fugafuga'

  click_on '更新'

  expect(page).to have_xpath("//option[text()='hogehoge']")
  expect(page).to have_xpath("//option[text()='fugafuga']")
 end
end

ターミナル

WARNING: The next major version of capybara-webkit will require at least version 5.0 of Qt. You're using version 4.8.7.
 Top 1 slowest examples (46.21 seconds, 94.3% of total time):
 selectの値が表示させる

Finished in 27.63 seconds (files took 39.55 seconds to load)
1 example, 0 failures

【Rails】入力確認フィールドの実装方法

こんにちは。

今年はまだ台風が来ていなく幸せを感じております。
どうもハチマキです。

はじめに

入力確認の実装方法をまた一つ学んだため、忘れないうちに書いていきます。

本日の概要 : 入力確認フィールドの実装方法

事象

ユーザ登録などで、メールアドレスやパスワードの確認フォームを作成したけど、値の一致はどうやって実装したら良いのだろうか😨

実装方法

今回はメールアドレスの確認フォームを実装していきます。
2つの受け取る値を一致させるためには、結論confirmationヘルパーを使うことで簡単に実装できます。

model

...
attr_accessor :email, :email_confirmation

validates :email, confirmation: true
validates :email_confirmation, presence: true

View

= form_tag(~~~~~) do
 = label_tag :email
 = text_field :email
 %br
 = label_tag :email_confirmation
 = text_field :email_confirmation
end

以上です!

入力フォームでよく見るコピペ禁止の実装方法

こんにちは。

もう8月も終わりますね。なんか寂しくなります。

どうもハチマキです。

はじめに

入力フォームなどで、コピペを禁止する方法について書いていきます。
ある3つを定義するだけで、簡単にコピペ防止ができます。

本日の概要 : 入力フォームのコピペ禁止の実装方法

事象

入力フォーム作成時に、ユーザのメールアドレスの入力ミスを減らしたい。
そんな時のソリューションとしてよく見るのは、確認用メールアドレスを打ち込みメアドを2度入力するケースです。

1つ目に入力したアドレスを2つ目にコピペできてしまうと、確認用の意味が全くないので、このようなことを防ぐために確認用メールアドレスをコピペ禁止にしたい。

実装方法

下記3つをfalse(無効)に定義するだけで、コピペ禁止になります。

  • oncopy →コピーをしたときの動作
  • onpaste →ペーストをしたときの動作。
  • oncontextmenu →右クリックメニューを出そうとしたときの動作
= form_for @user do |f|
 = f.label :email_confirmation do
  メールアドレス(確認用)
 = f.text_field :email_confirmation, placeholder: '※test',
                    oncopy: 'return false',
                    onpaste: 'return false',
                    oncontextmenu: 'return false'

これだけで完了です!

【git】git pushがrejectedされた時の解決方法

こんにちは。

なんかすでに秋風の涼しさを感じた日がありました。

どうもハチマキです。

はじめに

git push時に発生したrejected(エラー)を初めて解決した時に結構苦戦したので、
同じ境地に立たされている方のソリューションになればと思います。
結論!めちゃ簡単でした。

本日の概要 : git pushがrejectedされた時の解決方法

事象

git push origin testでtest branchをpushした際にrejectedが発生

エラー例

$ git push origin test
To github.com:~~~~
 ! [rejected]              test -> test (non-fast-forward)
error: failed to push some refs to 'git@github.com:~~~~
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

問題点

端的に言うと、testブランチのリモートとローカルの最新情報が異なっているため、pushが行えずrejectされる。

こんなときに発生する

  • 別の人が同じブランチにすでにプッシュしてしまった
  • すでにコミット状態の中、ローカルのコードを新たに変更してpushした

など

解決方法

リポジトリを最新状態にすることで解決します。

$ git pull origin test
対象ブランチを最新にするため、pullする

$ git push origin test
再度pushする