ActiveDecoratorのRspecの書き方

こんにちは!kossyです!




さて、今回はDecoratorのRspecでのテストの書き方の例について、
ブログに残してみたいと思います。




環境
Rails 5.2.3
Ruby 2.6.3
draper 3.1.0
MacOS Mojave




書き方
とりあえずDecoratorのコードを載せます。

class MemberDecorator < Draper::Decorator

  delegate_all

  def show_sex
    sex == 'male' ? '' : ''
  end

  def administrate_display
    administrator == true  ? '' : ''
  end

  def show_birthday
    birthday&.strftime('%Y年%m月%d日')
  end

  def age
    date = Date.today
    ((date.strftime('%Y%m%d').to_i - birthday.strftime('%Y%m%d').to_i) / 10000).to_s + ''
  end

end

上記のコードのテストを書いてみます。

require 'rails_helper'

RSpec.describe MemberDecorator, type: :decorator do
  describe 'MemberDecoratorに定義したメソッドが正しく動作すること' do
    describe 'show_sex' do
      describe 'sexがmaleの場合' do
        let(:member) { create :member, sex: :male }
        subject { member.decorate }

        it '男と表示される' do
          expect(subject.show_sex).to eq ''
        end
      end

      describe 'sexがfemaleの場合' do
        let(:member) { create :member, sex: :female }
        subject { member.decorate }

        it '女と表示される' do
          expect(subject.show_sex).to eq ''
        end
      end
    end

    describe 'administrate_display' do
      describe 'administratorがtrueの場合' do
        let(:member) { create :member, administrator: true }
        subject { member.decorate }

        it '○と表示される' do
          expect(subject.administrate_display).to eq ''
        end
      end

      describe 'administratorがfalseの場合' do
        let(:member) { create :member, administrator: false }
        subject { member.decorate }

        it '-と表示される' do
          expect(subject.administrate_display).to eq ''
        end
      end
    end

    describe 'show_birthday' do
      let(:member) { create :member }
      subject { member.decorate }

      it '%Y年%m月%d日と表示される' do
        expect(subject.show_birthday).to have_content ''
      end
    end

    describe 'age' do
      let(:member) { create :member }
      subject { member.decorate }

      it '年齢が表示される' do
        expect(subject.age).to have_content ''
      end
    end
  end
end


subjectを使ってテスト対象をモック化して、
decorateメソッドでdecoratorに定義したメソッドを使えるようにしています。


おおむねこんな感じで書けばいいんじゃないでしょうか(適当)

Railsのvalidation オプション「inclusion」の使い方

こんにちは!kossyです!




さて、今回は、Railsのバリデーションオプションの一つである、
「inclusion」オプションの使い方について、ブログに残してみたいと思います。




環境
Rails 5.2.3
Ruby 2.6.3
MacOS Mojave






使い方

その属性が持つ値がinclusion内で定義した値に含まれているかを検証します。

って言ってもわかりづらいので、具体例を出してみます。


例として、状態ステータスを持つ属性があるとします。
そして、その属性が持ち得る値として、定数を定義します。

STATUS_VALUES = ['draft', 'published', 'secret']

この定数を、inclusionオプションに渡します。

app/models/hoge.rb

class Hoge < ApplicationRecord

  STATUS_VALUES = ['draft', 'published', 'secret']


  validates :status, inclusion: { in: STATUS_VALUES }

end

こうすることによって、statusカラムに入れられる値を制限することができます。



参考にさせていただいた記事
Active Recordバリデーション - Rails ガイド
inclusion - リファレンス - - Railsドキュメント

特定のレコードを増加させるRailsのメソッド「increment」

こんにちは!kossyです!




さて、今回は、Railsのメソッドであるincrementの使い方とユースケースについて、ブログに残してみたいと思います。




使い方

基本的な使い方はこうです。

Model.increment(:attribute, value)

モデル(本体でもレコードでもOK)の属性に対して呼ぶことで、値を増加させることができます。




ユースケース

ECサイト等で、在庫の変動調整なんかに使えるんじゃないでしょうか。

items.each do |item|
  item.increment!(:stock, -1 * purchase_count) # decrementでもよくね?とか言わないでね☆
end

increment!とすると、saveメソッドを使わなくても値の変更を永続化できます。

外野から何か聞こえてきたので注意書きを入れましたが、ユースケースのイメージとしては
こんな感じではないでしょうか。




参考にさせていただいたサイト
increment - リファレンス - - Railsドキュメント
Rails5 で `#increment!` と `#decrement!` が同時実行を意識した処理になった! - Qiita
意外と知らないかもしれないRuby, Railsのメソッドとか - Qiita