capybaraで取得した要素の中身を確認する

テストが通らない原因を探るため、binding.pryを仕込んでデバッグをしておりました。

 

止まってくれたところで、

find(‘#client_check_by_id’)

とすれば、その要素を取得は出来るものの、その中身を見たい!と思い、そのやり方を調べてみました。

[1] pry(#<RSpec::ExampleGroups::Nested::Nested_2>)> find('#client_check_by_id')
=> #<Capybara::Node::Element tag="select" path="/html/body/main/form/div[1]/div[10]/select">

 

以下のように、

find(‘#client_check_by_id’).native.to_s

としてあげると、中身の要素を見ることが出来ました!!

[2] pry(#<RSpec::ExampleGroups::Nested::Nested_2>)> find('#client_check_by_id').native.to_s
=> "<select class="select required" name="client[check_by_id]" id="client_check_by_id"><option value=""></option> <option value="1">user 1</option> <option value="3">user 3</option> <option value="5">user 5</option> <option value="7">user 7</option></select>"

 

 

 

ポスグレとGP Commanderを接続する

起こった問題

PG Commanderというポスグレを可視化してくれるアプリを使いたかったのですが、ある日突然、自動で接続してくれなくなってしまっておりました。

 

自分で各項目を入力し接続を試みたのですが、上手くいかず困っておりました。。。

 

 

解決法

Portをずっと3000で接続しようと試みていたのですが、ポスグレは5432のようでしたw

以下のように入力したところ、無事接続できました!

 

gyazo.com

 

 

 

 

Heroku本番DBの内容をローカルに持ってくる

Herokuの本番DBの内容をローカルに持ってくる方法を教えていただきました!!

これは便利!!と感動したくので書き留めておきます。

 

 

以下のように、

heroku pg:pull herokuのDB名 ローカルDB名 --app アプリ名

とすると取得できます。

$ heroku pg:pull herokuのDB名 ローカルDB名 --app アプリ名

heroku-cli:
Pulling herokuのDB名 ---> ローカルのDB名
pg_dump: last built-in OID is xxxx
pg_dump: reading extensions
pg_dump: identifying extension members
pg_dump: reading schemas
pg_dump: reading user-defined tables
pg_dump: reading user-defined functions
pg_dump: reading user-defined types
pg_dump: reading procedural languages
pg_dump: reading user-defined aggregate functions
pg_dump: reading user-defined operators
pg_dump: reading user-defined access methods
pg_dump: reading user-defined operator classes
pg_dump: reading user-defined operator families
pg_dump: reading user-defined text search parsers
pg_dump: reading user-defined text search templates
pg_dump: reading user-defined text search dictionaries
pg_dump: reading user-defined text search configurations
pg_dump: reading user-defined foreign-data wrappers
pg_dump: reading user-defined foreign servers
.
.
.
.

heroku-cli: Pulling complete.

 

 

 

これだけでデータをローカルに引っ張ってこれました!!

Heroku便利&教えてもらえてよかったです!!

 

 

テストDBだけリセットしたい(postgresql)

テストデータベースだけリセットしたい!と思うことがありました。

調べてみたところ、以下の手順でテストデータベースをリセットできるようでした!

 

①データベースをtestに切り替える

$ bin/rails db:environment:set RAILS_ENV=test 

 

 

②データベースを消す

$ bundle exec rake db:drop RAILS_ENV=test

Dropped database 'm4ware_test'

 

 

③データベースを作り直す

$ bundle exec rake db:create RAILS_ENV=test

Created database 'm4ware_test'

 

 

スキーマを読み込んでテーブルを作り直す

$ bundle exec rake db:schema:load RAILS_ENV=test

-- enable_extension("plpgsql")

   -> 0.0900s

-- create_table(".................略

 

 

これでスッキリtest環境のDBのみリセットすることができました!

database_cleaner等のgemを入れたほうがいいという記事も何個か見かけましたが、プロジェクトをあまりいじらずに自分の環境だけリセットしたかったので今回はこの方法が良い感じでした!

 

 

おまけ

test環境でコンソールを動かすときは以下のコマンドで立ち上がります!

env RAILS_ENV=test rails c

 

 

bin/setup

先週末で自分が関わっていたプロジェクトが無事終了し、本日から新しいプロジェクトに関わることになりました!

その環境構築をしている中で、bin/setupコマンドを実行することがありました。

bin/setupが何なのかよくわかっていなかったので調べてみることにしました。

 

bin/setupとは

bin/setupとは、Railsアプリ配下にあるbin/setupファイルの内容を実行するコマンドです。

アプリケーションを初期化するスクリプトが置かれます。

ここにセットアップ内容を書いておくと、新しく環境構築するのがとても楽になります。

(実際とても楽でした)

 

 

そもそもbinディレクトリとは

スクリプトファイルが入っているディレクトリです。

bundle, rails, rake, setup, spring, update, yarnファイルが入っております。

それぞれ、サーバーを起動したり、セットアップ内容を書いておいたり等、アプリケーションを管理するためのスクリプトファイルです。

 

 

その他感想

前回のプロジェクトをDockerで環境構築した時も思ったのですが、こういったコマンド1つで設定が実行できるものがあると本当に楽ちんです!

利用するだけではなく、自分もこういった設定ファイルを作れるようになりたいと思います!

また、bin/setupについて調べていた際、以前もリンクを貼らせていただいた以下のスライドが出てきたので再び読み返してみました。

「一般的でなくても、使うときによりeasyになるなら取り入れていく姿勢」

「楽をするための努力を惜しまない」

というのを自分の中でも”当たり前”にしていきたいと思います。

ふつうのRailsアプリケーション開発

 

新しいプロジェクトも頑張る!!!

 

 

 

意味のあるテストデータの作成

 FactoryBotを使ったデータ作成について基礎を理解したいと思うことが多々ありました。

Everyday Rails Rspec 第4章、「意味のあるテストデータの作成」についてまとめる機会を頂いたので、こちらに下書きを書いていきたいと思います!

 

 

github.com

 

内容 

・ファクトリ対フィクスチャ

・FactoryBotをインストールする

・アプリケーションにファクトリを追加する

・シーケンスを使ってユニークなデータを生成する

・ファクトリで関連を扱う

・ファクトリ内の重複をなくす

・コールバック

・ファクトリを安全に使うには

・まとめ 

 

 

ファクトリ対フィクスチャ

フィクスチャのメリット

フィクスチャは比較的速い

Railsに最初から付いてくる

 

フィクスチャのデメリット

テストとは別のフィクスチャファイルに保存された値を覚えておく必要がある

フィクスチャはもろくて壊れやすい(らしい)

Railsはフィクスチャのデータを作るときActive Recordを読み込まない

 

・・・このような理由からテストデータのセットアップが複雑になってきたときはファクトリがおすすめ

ファクトリはシンプルで柔軟性に富んだテストデータ構築用のブロック

ファクトリは適切に(つまり賢明に)使えば、あなたのテストをきれいで読みやすく、リアルなものに保ってくれる

多用しすぎると遅いテストの原因になる(らしい)

 

 

FactoryBotをインストールする

group :development, :test do ~ end の中にgem 'factory_bot_rails'を追加し、bundle installします

group :development, :test do

gem 'factory_bot_rails'

end

 

 

アプリケーションにファクトリを追加する

spec/factorys/users.rbに属性や値を書いていきます

spec/factorys/users.rb

FactoryBot.define do
factory :user do
name 'hayashi'
email "test@gmail.com"
password '11111111'
end
end

 

このような設定をしておくだけで、テスト内で FactoryBot.create(:user) と書くと、定義したuserのデータが生成されます。

 

spec/models/user_spec.rb

require 'rails_helper'

describe 'User' do
it '有効なファクトリを持つ事' do
expect(FactoryBot.create(:user)).to be_valid
end
end
end

 

一方、FactoryBotを使用せず書くと、以下のようになります。

spec/models/user_spec.rb

require 'rails_helper'

describe 'User' do
it '有効なファクトリを持つ事' do
user = User.create(
name 'hayashi',
email "test@gmail.com",
password '11111111'
)

actexpect(:user).to be_valid
end
end
end

 

FactoryBotを使うと簡潔に書くことができる一方、どんな値を持ったデータが生成されているのかテストファイルを直接みるだけではわからないという注意点もあります。

時と場合によって、FactoryBotを使わずデータをベタ書きするのか、FactoryBotを使うのか使い分けるのが良いようです。

 

 

シーケンスを使ってユニークなデータを生成する

先ほど作ったファクトリを何回実行しても同じ値を持ったデータが作成されます。

メールアドレスのように、ユニークなデータでないとバリデーションエラーを起こしてしまう物に関しては、シーケンスを使ってユニークなデータを生成してあげることができます。

spec/factorys/users.rb

FactoryBot.define do
factory :user do
name 'hayashi'
sequence(:email) { |n| "test#{n}@gmail.com" }
password '11111111'
end
end

 

 

 

ファクトリで関連を扱う

FactoryBotはアソシエーションを扱うときにとても便利です。

以下のファクトリーはアソシエーション関連にあるデータも作成する設定です。

userモデル、projectモデル、noteモデルがあり、

・userモデルがhas_many :notes、has_many :projectsで、

・projectモデルがbelongs_to :user、has_many :notes

・noteモデルがbelongs_to :user、belongs_to :project

であるデータを作成する際は以下のように作成できます。

spec/factorys/notes.rb

FactoryBot.define do
factory :note do
message 'I am hayashi'
association :project
user {project.owner} // assosiation :user としてしまうと
end               userが重複して作られてしまう
end

 

spec/factorys/projects.rb 

FactoryBot.define do
factory :project do
sequence(:name) { |n| "project#{n}" }
association :owner
end
end

 

spec/factorys/users.rb

FactoryBot.define do
factory :user, aliases: [:owner] do
name 'hayashi'
sequence(:email) { |n| "test#{n}@gmail.com" }
password '11111111'
end
end

 

あとは、以下のように、FactoryBot.create(:note) とnoteを作成すればOKです。

spec/models/user_spec.rb

require 'rails_helper'

describe 'User' do
it '有効なファクトリを持つ事' do
expect(FactoryBot.create(:note)).to be_valid
end
end
end

 

 

ファクトリ内の重複をなくす

ファクトリで、ある属性の値だけ別なファクトリを作りたい時は以下のように設定します。

spec/factorys/projects.rb 

FactoryBot.define do
factory :project do
sequence(:name) { |n| "project#{n}" }
due_on 1.week.from_now
association :owner
end

factory :project_due_yesterday, class: Project do
sequence(:name) { |n| "project#{n}" }
due_on 1.day.from_now
association :owner
end
end

 こうすれば、

FactoryBot.create(:project)

FactoryBot.create(:project_due_yesterday)

とスペックでファクトリを呼び分けることで違うデータを持ったファクトリを生成することができます。

 

 

しかし、これだと、nameやassosiationの部分が重複しています。

この重複を無くした書き方も以下のようにすることで可能です。

spec/factorys/projects.rb 

FactoryBot.define do
factory :project do
sequence(:name) { |n| "project#{n}" }
due_on 1.week.from_now
association :owner

factory :project_due_yesterday do    // ネストさせた
due_on 1.day.from_now          

end
end
end

factory :project の中に factory :project_due_yesterday を入れ子にすることで、重複していたnameやassosiationの記述、class: Projectの記述を省略できます。

 

また、ファクトリをネストさせる他にも、traitを使った書き方もあります。

spec/factorys/projects.rb 

FactoryBot.define do
factory :project do
sequence(:name) { |n| "project#{n}" }
due_on 1.week.from_now
association :owner

trait :due_yesterday do
due_on 1.day.from_now          

end
end
end

 traitを用いて書いた時、スペックでファクトリを生成する際は、

FactoryBot.create(:project, :due_yesterday)

と引数でtraitを指定します。

 

 

コールバック

あるモデルをcreate・newした後、別のモデルも作成したい場合はコールバックを使用します。

コールバックをtraitを用いて書けば、簡単にコールバックを呼んだり呼ばなかったり選択することができます。

spec/factorys/projects.rb 

FactoryBot.define do
factory :project do
sequence(:name) { |n| "project#{n}" }
due_on 1.week.from_now
association :owner

trait :with_note do
after(:create){|project| create_list(:note, 5, project: project)}       
end
end
end

 こうしておくと、FactoryBot.create(:project, with_note) とすればコールバックが実施され、projectの関連先のnoteのデータも作成してくれます。

FactoryBot.create(:project) と通常通りならコールバックは実施されません。

 

これ以外にも、traitを使えば非常に複雑なデータの作成もスッキリかけるようになります。

 

 

ファクトリを安全に使うには

ファクトリを使うとテスト中に予期しないデータが作成されたり、無駄にテストが遅くなったりする原因になります。

(コールバックを使って関連するデータを作成する必要があるなら、ファクトリを使うたびに呼び出されないよう、トレイトの中でセットアップするようにするなど気をつけます。)

 

 

 

まとめ 

・ファクトリを使うことで、複雑なデータでもスペック内でスッキリと呼び出すことが可能になります。

・テストは理解しやすいものであることが大切なので、初心者の場合、ファクトリではなくnewやcreateでベタ書きするのもありだよ、と翻訳者の1人である魚さんも言っていました。 

・ファクトリの便利さを知れたので、まずは使い方をもっと理解し、パフォーマンスや可読性についても考慮してかけるようになりたいです。

 

 

 

 

 

 

rakeタスクを作る

menuテーブルが持っていたimageカラムの値を、menus_imagesテーブルのimageカラムに移すrakeタスクを作りました。

rakeタスクは初めて作ったので、手順を書き留めておきます。

 

タスクを生成する

以下のコマンドを打つと、タスクがlib/tasks配下に生成されます。

$ rails g task タスクの名前 

 

今回自分は以下のコマンドを実行しました。

$ rails g task move_to_menu_image

      create  lib/tasks/move_to_menu_image.rake

 

 

タスク内容を定義

実行したい内容を task タスク名 do ~ end の中に定義していきます。

今回自分はmenuテーブルが持っていたimageカラムの値を、menus_imagesテーブルのimageカラムに移したかったので、以下のように書きました。

namespace :move_to_menu_image do
desc "menusテーブルのimageカラムの値をmenu_imagesテーブルに移行する"
task move_menu_image: :environment do
Menu.all.each do |menu|
menu_image = MenuImage.new(menu_id: menu.id, image: menu.image)
menu_image.save
end
end
end

 

 

taskを実行

taskを作成したら、そのタスクを実行すれば、定義した通りの内容が実行されます。

以下のコマンドでrakeタスク一覧を確認できます。

$ rake -vT

 

自分の場合は以下のようなコマンド名でしたので、これを実行しました。

$ rake move_to_menu_image:move_menu_image

 

これでrakeタスクを作成して無事実行することができました!!

 

 

参考文献

以下の記事を参考にさせていただきました!!

qiita.com