articleに対して、authorとtagが関連付けられています。 article.rb
class Article < ApplicationRecord belongs_to :author has_many :tags, through: :article_tags has_many :article_tags . .
author.rb
class Author < Taxonomy has_many :articles end
tag.rb
class Tag < Taxonomy has_many :articles, through: :article_tags end
trait :with_author do transient do sequence(:author_name) { |n| "test_author_name_#{n}" } sequence(:tag_slug) { |n| "test_tag_slug_#{n}" } end after(:build) do |article, evaluator| article.author = build(:tag, name: evaluator.author_name, slug: evaluator.tag_slug) end end
trait :with_tag do transient do sequence(:tag_name) { |n| "test_tag_name_#{n}" } sequence(:tag_slug) { |n| "test_tag_slug_#{n}" } end after(:build) do |article, evaluator| article.tags << build(:tag, name: evaluator.tag_name, slug: evaluator.tag_slug) end end
authorの時は=で書くのに対し、
article.author = build(:tag, name: evaluator.author_name, slug: evaluator.tag_slug)
tagの時は<<で書く理由がわかりませんでした。
article.tags << build(:tag, name: evaluator.tag_name, slug: evaluator.tag_slug)
binding.pryで確認
[1] pry(#<FactoryBot::SyntaxRunner>)> article.tags => []
article.tagsと入力すると、配列になっていることが分かります。
Rails guideのhas_many関連付の詳細より、has_manyで追加されるメソッドに<<がありました。これにより、生成したインスタンスをarticle.tags配列の末尾に挿入してくれます。
article.tags
pry(main)> author.articles [46] pry(main)> article.tags => [#<Tag:0x00007fee1f1b0688 id: 1, type: "Tag", name: "saa", slug: "saae", description: nil, created_at: Thu, 03 Jun 2021 21:20:32 JST +09:00, updated_at: Thu, 03 Jun 2021 21:20:32 JST +09:00>, #<Tag:0x00007fee1f1b0408 id: 5, type: "Tag", name: "アニメ 推理", slug: "ssss", description: nil, created_at: Sat, 05 Jun 2021 07:17:32 JST +09:00, updated_at: Sat, 05 Jun 2021 07:17:32 JST +09:00>]
author.rbでhas_many: tagsとしているので、配列になっている。
article.author
[45] pry(main)> article.author => #<Author:0x00007fee168225b0 id: 3, type: "Author", name: "青山剛昌", slug: "sulug", description: "名探偵コナンの作者", created_at: Sat, 05 Jun 2021 07:05:23 JST +09:00, updated_at: Sat, 05 Jun 2021 07:05:23 JST +09:00> [46] pry(main)>
article.rbでbelongs_to :authorとなっているので配列ではない。
一般的に「=」は代入なので、左辺を全て右辺の値で上書きします。 author.articlesというのは配列ですよね(正確にいうとActiveRecord::Relation)。今回のケースではarticle.tagsを右辺で上書きするのではなく、配列に追加します。
binding.pryで中身を見てみよう!
trait :with_author do transient do sequence(:author_name) { |n| "test_author_name_#{n}" } sequence(:tag_slug) { |n| "test_tag_slug_#{n}" } end after(:build) do |article, evaluator| article.author = build(:tag, name: evaluator.author_name, slug: evaluator.tag_slug) end end
1] pry(#<FactoryBot::SyntaxRunner>)> build(:author, name: evaluator.author_name, slug: evaluator.tag_slug) => #<Author:0x00007fc258193ad0 id: nil, type: "Author", name: "伊藤", slug: "test_author_slug_1", description: nil, created_at: nil, updated_at: nil>
slugはtransientで定義しているtest_author_slug_1になっているが、nameはletで記載している”伊藤”になっています。