💡

Twitter::TweetのFactoryBot作る時にハマった件

2022/02/08に公開

もし普通にテーブル上にレコードを作るならこうなる

FactoryBot.define do
  factory :twitter_tweet, class: 'Twitter::Tweet' do
    sequence(:id) { |n| n }
    sequence(:user) { association(:twitter_user) }
    text             { '我々はばんくし団の団員だ' }
    created_at       { Time.zone.now }
    retweeted_status { nil }
    url              { "https://#{user.screen_name}/status/#{id}" }
  end
end

ところが

ところがテーブル上にレコードを作らないのでこうしないといけない

またTwitter::Tweetはnewでしか属性を受け取ってくれない

tweet = new(id: id)
tweet.text = '....'

みたいなことができない。

なのでこうなる

FactoryBot.define do
  factory :twitter_tweet, class: 'Twitter::Tweet' do
    sequence(:id) { |n| n }
    sequence(:user) { association(:twitter_user) }
    text             { '我々はばんくし団の団員だ' }
    created_at       { Time.zone.now }
    retweeted_status { nil }
    url              { "https://#{user.screen_name}/status/#{id}" }

    initialize_with do
      params = { id: id, text: text, created_at: created_at, user: user, url: url }
      params[:retweeted_status] = retweeted_status if retweeted_status.present?
      new(params)
    end

    to_create do
      # @note 保存できないから何もしない
    end
  end
end

さらに問題があって

userとしてTwitter::Userクラスのインスタンスを渡すとこんなエラーになる。

     NoMethodError:
       undefined method `merge' for #<Twitter::User id=2>

困った時はコードを見る

問題を起こしているコード

https://github.com/sferik/twitter/blob/master/lib/twitter/base.rb#L131-L138

テストの書き方

tweet = Twitter::Tweet.new(id: 28_669_546_014, user: {id: 7_505_382, screen_name: 'sferik'})

https://github.com/sferik/twitter/blob/master/spec/twitter/tweet_spec.rb#L405

ということでこうする

テストは動いた

FactoryBot.define do
  factory 'twitter/tweet', class: 'Twitter::Tweet' do
    sequence(:id) { |n| n }
    sequence(:user) { |n| { screen_name: "test_user_#{n}" } }
    text             { '我々はばんくし団の団員だ' }
    created_at       { Time.zone.now }
    retweeted_status { nil }
    url              { "https://#{user[:screen_name]}/status/#{id}" }

    initialize_with do
      params = { id: id, text: text, created_at: created_at, user: user, url: url }
      params[:retweeted_status] = retweeted_status if retweeted_status.present?
      new(params)
    end

    to_create do
      # @note 保存できないから何もしない
    end
  end

  factory 'twitter/tweet__retweeted', parent: 'twitter/tweet' do
    retweeted_status { { text: text } }
  end
end

Discussion