Create a new project

$ cd ~/Documents
$ rails new bookstore
$ cd bookstore/

Add rspec-rails and add rspec on Gemspec

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

Bundle install

$ bundle install

Install the rspec

rails generate rspec:install

Create a new model for book and author

$ rails g model author name:string birth_data:date nationality:string
$ rails g model book title:string author:references isbn:string

Run database migration

$ rails db:migrate

Let's execute rspec model tests

$ rspec spec/models/
**

..

2 examples, 0 failures, 2 pending

Let's write the test

require "rails_helper"

RSpec.describe Book, type: :model do

  author_1 = Author.first_or_create name: "George Raymond Richard Martin", birth_data: Date.parse("20/09/1948"), nationality: "American"

  it "Happy Way" do
    b1 = Book.new title: "A Game of Thrones", author: author_1, isbn: "0553593714"
    expect(b1.save).to be true
  end

  it "Happy Way" do
    b2 = Book.new title: "A Game of Thrones", author: author_1, isbn: "9780553593716"
    expect(b2.save).to be true
  end

  it "Happy Way" do
    b3 = Book.new title: "A Clash of Kings", author: author_1, isbn: "0553579908"
    expect(b3.save).to be true
  end

  it "Happy Way" do
    b4 = Book.new title: "A Clash of Kings", author: author_1, isbn: "9780553579901"
    expect(b4.save).to be true
  end 

  it "Wrong isbn size" do
    b5 = Book.new title: "A Storm of Swords", author: author_1, isbn: "055357342"
    expect(b5.save).to be false
  end

  it "Wrong isbn size" do
    b5 = Book.new title: "A Storm of Swords", author: author_1, isbn: "978055357342"
    expect(b5.save).to be false
  end

  it "Wrong isbn size" do
    b6 = Book.new title: "A Storm of Swords", author: author_1, isbn: "055357342XX"
    expect(b6.save).to be false
  end

  it "Wrong isbn size" do
    b7 = Book.new title: "A Storm of Swords", author: author_1, isbn: "97805535734288"
    expect(b7.save).to be false
  end 
end

Executing the test

$ rspec spec/models/book_spec.rb
....FFFF

...

rspec ./spec/models/book_spec.rb:27 # Book Wrong isbn size
rspec ./spec/models/book_spec.rb:32 # Book Wrong isbn size
rspec ./spec/models/book_spec.rb:37 # Book Wrong isbn size
rspec ./spec/models/book_spec.rb:42 # Book Wrong isbn size

Let's create a validation for this

As is known, the ISBN must be size 10 or 13

File app/models/book.rb must be like this

class Book < ApplicationRecord
  belongs_to :author
  validates :isbn, length: {included: [10, 13]}
end

Executing the book tests again

$ rspec spec/models/book_spec.rb
An error occurred while loading ./spec/models/book_spec.rb.
Failure/Error: validates :isbn, length: {included: [10, 13]}

ArgumentError:
  Range unspecified. Specify the :in, :within, :maximum, :minimum, or :is option.
# ./app/models/book.rb:3:in `<class:Book>'
# ./app/models/book.rb:1:in `<top (required)>'
# ./spec/models/book_spec.rb:3:in `<top (required)>'
No examples found.


Finished in 0.00046 seconds (files took 9.71 seconds to load)
0 examples, 0 failures, 1 error occurred outside of examples

Active model is not ready to run our tests

In a new file on config/initializers/bength.rb let's write a mod

class Fixnum
  def included? array
    array.include? self
  end
end

module ActiveModel
  module Validations
    class LengthValidator < EachValidator
      MESSAGES  = { is: :wrong_length, minimum: :too_short, maximum: :too_long }.freeze
      CHECKS    = { is: :==, minimum: :>=, maximum: :<= }.freeze

      RESERVED_OPTIONS = [:minimum, :maximum, :within, :is, :too_short, :too_long]

      def check_validity!
        keys = CHECKS.keys & options.keys

        if keys.empty?
          raise ArgumentError, "Range unspecified. Specify the :in, :within, :maximum, :minimum, or :is option."
        end

        keys.each do |key|
          value = options[key]
          if key != :included
            unless (value.is_a?(Integer) && value >= 0) || value == Float::INFINITY || value.is_a?(Symbol) || value.is_a?(Proc)
              raise ArgumentError, ":#{key} must be a non-negative Integer, Infinity, Symbol, or Proc"
            end
          else
            unless value.is_a?(Array)
              raise ArgumentError, ":#{key} must be a array"
            end
          end
        end
      end
    end
  end
end

Executing the book tests again

$ rspec spec/models/book_spec.rb
........

Finished in 0.23966 seconds (files took 9.44 seconds to load)
8 examples, 0 failures

🗓 2017-12-19
1006 👀