Railsつかってるけど、知らないことが多くて各駅停車で開発してるような気分だったのですがちょっとづつ慣れてきて、各駅停車状態からちょっとづつ脱しつつあります。
最近はTDD/BDDな感じで作業してるのですがModelのspecを書く時にFactoryGirlの使い方で一部わからなかったことがあって今後また同じことでハマりそうなのでメモっておきます
環境は
- rails 4.2.0
- factory_girl 4.5.0
- factory_girl_rails 4.5.0
- rspec 3.1.0
という感じです
例えば、
- レストラン
- そのレストランに対する口コミ
という感じのモデルを定義したいとします。
generatorで以下のようにモデルを作成
./bin/rails g model restaurant name:string address:string
./bin/rails g model restaurant_review description:text restaurant:references
Restaurantモデルはこんな感じ
restaurant.reviewsで利用できるようにしたいのでclass_nameを利用してみました(これも知らなかった・・)
class Restaurant < ActiveRecord::Base
has_many :reviews, class_name: RestaurantReview.name
end
口コミ情報に対応するモデルはこんな感じ
class RestaurantReview < ActiveRecord::Base
belongs_to :restaurant
end
FactoryGirlの設定を行う
それぞれのモデルに対するFactoryGirlの設定を行います
口コミ情報に対応するRestaurantReviewモデルに対応するFactoryGirlの設定
こちらはそれほど苦労すること無く出来ました。
※sequenceの使い方もよくわかってなかったのですが、Qiitaのこちらの記事を見て改めて理解したのですが、連番で重複しないデータを定義出来るんですね。これは便利!
FactoryGirl.define do
factory :restaurant_review do
sequence(:description) { |n| "restaurant_review_description#{n}"}
end
end
Restaurantモデルに対応するFactoryGirlの設定
で、本題に書いた1対多のモデルに対するFactoryGirlですがこれがわからなかったのですがreviewsに対して以下のようにブロックを渡しつつ、build_listというのを利用することで定義できるんですね
FactoryGirl.define do
factory :restaurant do
sequence(:name) { |n| "restaurant_name#{n}" }
sequence (:address) { |n| "restaurant_address#{n}" }
reviews { build_list :restaurant_review, 1 }
end
end
終わりに
Rails知らないことが多いけど、その分成長が感じられて面白い