簡単なサンプルを作ってみる (2)

ええと、以下なテーブルなのですが

class CreateCustomers < ActiveRecord::Migration
  def self.up
    create_table :customers do |t|
      t.string :name
      t.integer :age

      t.timestamps
    end
  end

  def self.down
    drop_table :customers
  end
end

で、name な属性は

validates_presence_of :name

ってことで入力必須らしい。ので試験としては以下なのかな。

require 'spec_helper'

describe Customer do
  before(:each) do
    @customer = Customer.new
  end

  it "@customer should not be valid because name property is null" do
    @customer.should_not be_valid
  end

end

model はまっさら状態で試験実行。

$ bundle exec rspec spec/
/home/hoge/Documents/rails_proj/api_sample/spec/models/customer_spec.rb:1:in `require': no such file to load -- spec_helper (LoadError)

げ。何ソレ。ココによると rails generate rspec:install しろとある。

$ rails generate rspec:install
      create  .rspec
       exist  spec
      create  spec/spec_helper.rb
$

なるほど。ちなみにググり中に自分ブログの数年前にエントリがでてきてびっくり。しかも全然役に立たんかった。
そりゃ良いのですが試験リトライ。

$ bundle exec rspec spec/
F

Failures:

  1) Customer @customer should not be valid because name property is null
     Failure/Error: @customer = Customer.new
     ActiveRecord::StatementInvalid:
       Could not find table 'customers'
     # ./spec/models/customer_spec.rb:5:in `new'
     # ./spec/models/customer_spec.rb:5:in `block (2 levels) in <top (required)>'

Finished in 1.03 seconds
1 example, 1 failure

Failed examples:

rspec ./spec/models/customer_spec.rb:8 # Customer @customer should not be valid because name property is null
$

あ、db 作ってないや。ええと以下かな。

$ bundle exec rake db:migrate
==  CreateCustomers: migrating ================================================
-- create_table(:customers)
   -> 0.0017s
==  CreateCustomers: migrated (0.0018s) =======================================

$ bundle exec rake db:test:prepare
$ ls db
development.sqlite3  migrate  schema.rb  seeds.rb  test.sqlite3
$

で、もっかい rspec をナニ。

$ bundle exec rspec spec/
F

Failures:

  1) Customer @customer should not be valid because name property is null
     Failure/Error: @customer.should_not be_valid
       expected valid? to return false, got true
     # ./spec/models/customer_spec.rb:9:in `block (2 levels) in <top (required)>'

Finished in 0.21798 seconds
1 example, 1 failure

Failed examples:

rspec ./spec/models/customer_spec.rb:8 # Customer @customer should not be valid because name property is null
$

では、app/models/customer.rb に以下を盛り込んで

class Customer < ActiveRecord::Base
  validates_presence_of :name
end

再度試験実行。

$ bundle exec rspec spec/
.

Finished in 0.61442 seconds
1 example, 0 failures
$

無事グリーンですね。あるいは試験はそのまんまで app/models/customer.rb に以下を盛り込んだらどうなるかな。

class Customer < ActiveRecord::Base
  validates_presence_of :name
  validates_numericality_of :age, :greater_than => 0
end

普通に 0 で初期化されるのだろうか。試験パスしてるのでそうらしい。あ、違うや。
以下かな?

require 'spec_helper'

describe Customer do
  before(:each) do
    @customer = Customer.new
    @customer2 = Customer.new(:name=>"hoge")
  end

  it "@customer should not be valid because name property is null" do
    @customer.should_not be_valid
    @customer2.should_not be_valid
  end

end

あ、書き方違うや。以下か。

require 'spec_helper'

describe Customer do
  before(:each) do
    @customer = Customer.new
    @customer2 = Customer.new(:name=>"hoge")
  end

  it "@customer should not be valid because name property is null" do
    @customer.should_not be_valid
  end

  it "@customer2 should not be valid because age property is less than 0" do
    @customer2.should_not be_valid
  end

end

試験にはパスしましたが、値は何なのだろう。

$ bundle exec rspec spec/
..

Finished in 0.34626 seconds
2 examples, 0 failures
$

ちなみに valid なナニも確認しておきたいのですが、ということで以下。

$ rails console --sandbox
Loading development environment in sandbox (Rails 3.0.9)
Any modifications you make will be rolled back on exit
ruby-1.9.2-p180 :001 > Customer.new.valid?
 => false 
ruby-1.9.2-p180 :002 > Customer.new(:name=>'fuga').valid?
 => false 
ruby-1.9.2-p180 :003 > customer = Customer.new
 => #<Customer id: nil, name: nil, age: nil, created_at: nil, updated_at: nil> 
ruby-1.9.2-p180 :004 > 

およよ。あるいは

ruby-1.9.2-p180 :004 > Customer.new(:name=>'fuga', :age=>0).valid?
 => false 
ruby-1.9.2-p180 :005 > Customer.new(:name=>'fuga', :age=>1).valid?
 => true 
ruby-1.9.2-p180 :006 > 

ありゃ。1 以上じゃないと駄目なのか。なので試験を以下にして

require 'spec_helper'

describe Customer do
  before(:each) do
    @customer = Customer.new
    @customer2 = Customer.new(:name=>"hoge")
    @customer_normal = Customer.new(:name=>"fuga", :age=>1)
  end

  it "@customer should not be valid because name property is null" do
    @customer.should_not be_valid
  end

  it "@customer2 should not be valid because age property is less than 0" do
    @customer2.should_not be_valid
  end

  it "@customer_normal should be valid" do
    @customer_normal.should be_valid
  end

end

で、試験グリーンを確認。

$ bundle exec rspec spec/
...

Finished in 0.33621 seconds
3 examples, 0 failures
$

なかなかに進捗が遅い。次は controller か。

Controller

rails generate controller CustomerController とかってやるのかな。

$ rails generate controller CustomerController
      create  app/controllers/customer_controller_controller.rb
      invoke  erb
      create    app/views/customer_controller
      invoke  rspec
      create    spec/controllers/customer_controller_controller_spec.rb
      invoke  helper
      create    app/helpers/customer_controller_helper.rb
      invoke    rspec
      create      spec/helpers/customer_controller_helper_spec.rb
$

う、しまった。CustomersController だ。destroy で削除できるかな。

$ rails destroy controller CustomerController
      remove  app/controllers/customer_controller_controller.rb
      invoke  erb
      remove    app/views/customer_controller
      invoke  rspec
      remove    spec/controllers/customer_controller_controller_spec.rb
      invoke  helper
      remove    app/helpers/customer_controller_helper.rb
      invoke    rspec
      remove      spec/helpers/customer_controller_helper_spec.rb
$

をー、素晴しい。で、リトライ。

$ rails generate controller CustomersController
      create  app/controllers/customers_controller_controller.rb
      invoke  erb
      create    app/views/customers_controller
      invoke  rspec
      create    spec/controllers/customers_controller_controller_spec.rb
      invoke  helper
      create    app/helpers/customers_controller_helper.rb
      invoke    rspec
      create      spec/helpers/customers_controller_helper_spec.rb
$

中身は以下。

$ cat app/controllers/customers_controller_controller.rb 
class CustomersControllerController < ApplicationController
end
$

ここにコピペすれば良いな。そろそろ出掛けるのでここで中断します。