Help us understand the problem. What is going on with this article?

FactoryGirlに新しいシンタックスを追加する

More than 3 years have passed since last update.

本来やりたかったこと

DB分割前提のテストを書きたいので、FactoryGirlを拡張して、シャード指定できるようにしたい。
ちなみに分割はOctopusを利用した水平分割です。

FactoryGirlにシンタックスを追加する方法

概要

方法は色々ありそうですが、今回は、FactoryGirl::StrategySyntaxMethodRegistrarを利用します。
非公開APIっぽいのでメンテナーにはあまりいい顔されないかもしれません。
例として、テストコードを書いてるときに🍣が食べたくなった時を想定してcreate_sushiを追加します

コード例

spec/support/factory_girl_ext.rb
class SushiSyntaxRegistrar < FactoryGirl::StrategySyntaxMethodRegistrar
  def define_strategy_methods
    define_sushi
  end

  private

  def define_sushi
    strategy_name = @strategy_name

    define_syntax_method("#{strategy_name}_sushi") do
      Rails.logger.debug "🍣"
    end
  end
end

sushi_create_syntax_registrar = SushiSyntaxRegistrar.new(:create)
sushi_create_syntax_registrar.define_strategy_methods
spec/models/sushi.rb
RSpec.describe Sushi, type: :model do
  it "looks like 🍣" do
    expect(create_sushi).to be true
  end
end

テストを実行するとログに🍣が表示されています。やったね!

ちょっとだけ解説

  • デフォルトだとspec/support/配下は読まなかった気がするので、spec_helper.rb辺りでrequireしてあげてください
  • FactoryGirl::StrategySyntaxMethodRegistrar#initializeの引数は定義するシンタックスに利用されます。
    • 今は:createを引数にしてcreate_sushiを定義していますが、:buildを渡せば build_sushiも定義することが出来ます
  • FactoryGirl::StrategySyntaxMethodRegistrar#define_syntax_methodは、FactoryGirl::Syntax::Methodsに対してメソッドを追加するメソッドです。もし、すでに定義されてしまっている場合はModule#undef_methodしてしまうので、createを定義すると後勝ちでcreateが全て🍣メソッド化します :fearful:

本来やりたかったことの解決

  • 要するに便利なdefine_methodを呼んでいるようなものなので、上のdefine_sushiのように今回は以下のようなコードを書きました
  • 以下を実行すると、create_with_shard :model_name, :shard1 のようなシンタックスが生まれます
def define_singular_strategy_method_with_shard
  strategy_name = @strategy_name

  define_syntax_method("#{strategy_name}_with_shard") do |name, shard, *traits_and_overrides, &block|
    Octopus.using(shard) do
      FactoryGirl::FactoryRunner.new(name, strategy_name, traits_and_overrides).run(&block)
    end
  end
end

まとめ

  • FactoryGirlにsyntaxを追加する方法でした。
the40san
Game Backend/Build/Software Enginner
https://github.com/the40san
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away