【RSpec】Factory_Botについて(パート2)

はじめに

 以前、【RSpec】Factory_botについてで基本的なFacotoryの使い方を説明しました。今回はさらに発展的なFactoryBotの使い方を紹介していきます。

基本的なファクトリー定義

  • 直接値を入れる
  • 値を動的に生成する
  • シーケンスを使用する
  • アソシエーションを定義する
FactoryBot.define do
  factory :user do
  first_name { "John" } #直接値を入れる
     last_name { "Doe" }  #直接値を入れる
  date_of_birth { 18.years.ago } # 値を動的に生成する
     sequence(:email) { |n| "test#{n}@example.com" } # シーケンスを使用
     assosiation :organization # Organizationへのアソシエーション
  end
end

buildcreate

*buildで十分な時はbuildを使用する

users = build_list(:user, 2)
users = create_list(:user, 2)

traitを使用し、条件の異なるファクトリーを定義

FactoryBot.define do
  factory :article do
    sequence(:title) { |n| "title-#{n}" }
    sequence(:slug) { |n| "slug-#{n}" }
  end

  trait :draft do
    state { :draft }
  end

  trait :future do
    published_at { Time.current.tomorrow }
    state { :publish_wait }
  end

  trait :past do
    published_at { Time.current.yesterday }
    state { :published }
  end

インスタンス生成時に、traitを指定、複数指定することもできます。

transientやcallbackを組み合わせてアソシエーション先のデータを生成

transientはモデルの属性以外のデータをファクトリに含めることができます。

after(:build)はコールバックでarticleインスタンスが生成された後に実行されます。

trait :with_author do
    #articleモデルの属性以外のデータをファクトリに含める
    transient do
      sequence(:author_name) { |n| "test_author_name_#{n}" }
      sequence(:tag_slug) { |n| "test_author_slug_#{n}" }
    end


    after(:build) do |article, evaluator|  #article作成して、その記事のauthorをbuildしている。
   # belongs_to :authorは定義済 
      article.author = build(:author, name: evaluator.author_name, slug: evaluator.tag_slug) #上記の変数を使用
    end
  end

参考文献

FactoryBotを使う時に覚えておきたい、たった5つのこと

【RSpec】describe,context,itの使い分けについて

はじめに

RSpecを書き始めてから、describeとcontextに何を書いたらよいか迷うことがありました。なので、describe、context、itの使い分けについて紹介します。

テストの流れ

テストの流れは、

  1. テストの対象に対して
  2. 特定の条件において
  3. 期待するアウトプットが返ってくるかを調べる

が主な流れである。

実は、この流れが使い分けのポイントである。

describeテストの対象を記述

context特定の条件を記述

itアウトプットを記述

となる。

例(モデルのバリデーションテスト)

RSpec.describe Task, type: :model do

  describe 'Taskモデル(テストの対象)' do
    context '値を入れなくてはならないカラムのバリデーションが有効であるか確認する(条件)' do
      it '全ての属性の値があれば有効' do
        task = build(:task)
        expect(task).to be_valid
        # バリデーション判定後のインスタンスの持つエラーメッセージの配列は空である
        expect(task.errors).to be_empty
      end

      # titleがなければ無効
      it 'タイトルがなければ無効' do
        task_without_title = build(:task, title: nil)
        # これは無効であるはずだ
        expect(task_without_title).to be_invalid
        # errors[:title]の中身が["can't be blank"]なので[]が必要
        expect(task_without_title.errors[:title]).to eq ["can't be blank"]
      end

      # statusがなければ無効
      it 'statusがなければ無効' do
        task_without_status = build(:task, status: nil)
        expect(task_without_status).to be_invalid
        expect(task_without_status.errors[:status]).to eq ["can't be blank"]
      end
    end

参考資料

RSpecの(describe/context/example/it)の使い分け

【Rails】gem wheneverについて

wheneverとは?

cronの設定を、rubyの簡単な文法で扱えるようにしたライブラリ

【Linux】cronについて

wheneverの実装

gemのインストール
gem 'whenever', require: false   
$ bundle install
初期設定
$ bundle exec wheneverize .

とコマンドを実行することでschedule.rbというファイルが生成されますので、ここに定期実行させたいタスクやその頻度などを記述していき、cronを編集していくこととなります。

schedule.rbに記述(今回は1時間ごとに作成したrakeタスクを実行する場合とする)
#wheneverはバックグラウンドで処理されるものであるため、Railsとは関係のないプロセスである。
#よって、このファイルの中でRailsのメソッドを使いたい場合は下記の記述が必要である。
#つまりconfig/environment.rbを読み込んでいる
require File.expand_path(File.dirname(__FILE__) + '/environment')


# cronを実行する環境変数
# ENV['RAILS_ENV']で環境を判断し、何も入っていなければ入っていなければ:developmentをrails_envに代入
rails_env = ENV['RAILS_ENV'] || :development

# cronを実行する環境変数をセット
set :environment, rails_env

# cronのログの吐き出し場所
set :output, "#{Rails.root}/log/cron.log"



job_type :rake, "export PATH=\"$HOME/.rbenv/bin:$PATH\"; eval \"$(rbenv init -)\"; cd :path && RAILS_ENV=:environment bundle exec rake :task :output"


every 1.hours do
  rake 'status_task:published'
end

schedule.rbの確認・反映など

$ bundle exec whenever 

→設定内容にエラーがないか確認

$ bundle exec whenever --update-crontab 

→cronにデータを反映

$ bundle exec whenever --clear-crontab

→cronからデータを削除する

【Linux】cronについて

cronとは?

 cronとは、「○時になったら〇〇の処理を実行して」といった具合に、定期的にコマンドを実行するためにメモリ上に常に命令を待機しているプロセス(=デーモンプロセス) のことです。

「何を」「いつ(頻度)」実行するかを決めて、そのルールを書き込むことです。

※複製」の意味の「クローン(clone)」とは異なるものです。

cronのメリット

  • 指定したプログラムの動作を予約できる。
  • そのプログラムを定期実行できる。
  • サーバー管理者の負担とミスは減り、効率よくサーバーの管理業務ができる。

cronとcrontabの違い

  • cronは機能を示す
  • crontabはコマンド名またはファイル名

cronでできること

  • 定期的なファイル転送 → Webサイトを楽に更新する
  • Webサイトの定期的なバックアップ
  • メールマガジンの日時指定配信

cronの操作方法

cronの開き方
crontab -e
cronの表示方法
crontab -l
cronの削除方法
crontab -r

cronファイルの書き方

cronファイルはスケジュールを指定する部分と、コマンドを指定する部分とで構成されています。基本ルールは以下の通りです。スケジュールとコマンドの間は半角空けます。

初期の状態

* * * * * (コマンド)
「*」の位置(左から) 頻度 指定できる数字 備考
1番目 0-59
2番目 0-23
3番目 1-31
4番目 1-12
5番目 曜日 0-7 0と7は日曜日

例1毎月10日の午前4時59日にコマンドを実行する場合

59 04 10 * * (コマンド)

例2 毎時0分で1時間おきにコマンドを実行する場合

* */1 * * * (コマンド)

参考資料

【入門】cron(クロン)設定・書き方の基本

【Rails】Rakeファイルについて

rakeとは?

Railsドキュメントでは下記のように記載されています。

buildツールとは?

アプリを構築する上では、同じことを正しい手順で何度も行う場面が出てきます。これを解決するために誕生したのがbuildツールです。

簡単に言うと 「一連のタスクを手順通りに実行してくれるもの」です。

rakeの特徴

rake taskを作成する

$ rake g task <タスク名>

すると、lib/tasksディレクトリ配下にファイルが生成されます。ここに、コードを記述していきます。

タスクの作成

namespace :aisatu_task do #namespaceでtaskをまとめられる。
  desc '朝のあいさつ' #タスクの説明をするところ
  task :hello do   # rake hello で実行できる
    puts 'Hello, Taro' 
  end
end

これで一つのタスクを作ることができました。

$ rake -T

設定されたタスクを上記のコマンドで確認すると、

rake aisatu_task:hello     # 朝のあいさつ

このように記載されています。

$ rake aisatu_task:hello

実行すると、

Hello, Taro

と表示されました。

【Rails】gem gretel(パンくずリスト)について

はじめに

 今回はパンくずリストを作成するgretelというgemについて紹介します。

パンくずリストとは?

こちらの記事がわかりやすかったので載せておきます。

【Webサイトの基本】パンくずリストについて知ろう

gemの導入

gem 'gretel'
$ bundle install

 

設定ファイルの生成

設定ファイルを生成するコマンドを入力します。

$ bundle exec rails generate gretel:install

このコマンドで、config/breadcrumbsが生成されました。

crumb :root do
  link "Home", root_path
end

# crumb :projects do
#   link "Projects", projects_path
# end

# crumb :project do |project|
#   link project.name, project_path(project)
#   parent :projects
# end

# crumb :project_issues do |project|
#   link "Issues", project_issues_path(project)
#   parent :project, project
# end

# crumb :issue do |issue|
#   link issue.title, issue_path(issue)
#   parent :project_issues, issue.project
# end

# If you want to split your breadcrumbs configuration over multiple files, you
# can create a folder named `config/breadcrumbs` and put your configuration
# files there. All *.rb files (e.g. `frontend.rb` or `products.rb`) in that
# folder are loaded and reloaded automatically when you change them, just like
# this file (`config/breadcrumbs.rb`).

こちらを編集していきます。

設定ファイルの編集

今回は一例として、HOME > ユーザー一覧 > ユーザー詳細ページの設定を示していきます。

crumb :root do
  link 'Home', root_path
end

crumb :users do
  link 'ユーザー一覧', users_path
end

crumb :user do |user|
  link "#{user.name}", user_path(user)
  parent :users
end

crumb :root do内に設定した項目は、パンクズリストのルートに表示されます。

parentでは、そのページの上の階層を指定することができます。

viewでの配置

<%= breadcrumbs pretext: "You are here: ",  separator: " &rsaquo; " %>

pretextには、パンくずリストの先頭に挿入する文章を記述。いらない場合は設定しなくてOKです。「separator」には、パンくずの区切り文字を指定。「›」は出力されると「›」になります。

ユーザー一覧
<% breadcrumb :users %>
ユーザー詳細
<% breadcrumb :users %>