How to override class initialize method and use FactoryBot?
Asked Answered
D

1

5

I'm using FactoryBot with Rspec on rails.

I have a SpecificKeyword ruby class where I extend the inittialize method:

def initialize(args)
   super(args)
   # Init regexp field immediatly when creating keyword
   self.regexp = make_regexp(args[:specificity])
end

In my Rspec tests, i try to call this: @kw_ex = create(:specific_keyword, name: 'Test Keyword').

But I get this stack trace:

 ArgumentError:
        wrong number of arguments (0 for 1)
      # ./app/models/specific_keyword.rb:19:in `initialize'

It looks like when instantiating a SpecificKeyword with FactoryBot, no args are passed to the init method. Is this a desired behavior, and if so, how am I supposed to proceed to keep using FactoryBot for my tests? It does work when I just do SpecificKeyword.new(name:'Test').

If I do not override the initialize method, it does work.

Dressler answered 10/1, 2018 at 11:14 Comment(0)
N
9

FactoryBot supports custom initializers looks like exactly your case:

FactoryBot.define do
  factory :specific_keyword do
    transient do
      name { 'some default' }
    end

    initialize_with { new(attributes.merge(name: name)) }
  end
end

https://robots.thoughtbot.com/factory-girl-2-5-gets-custom-constructors

Noiseless answered 10/1, 2018 at 12:51 Comment(5)
Great, it works. Just correct initialize_with { SpecificKeyword.new(name: name) } to initialize_with { new(name: name) } and it's perfect. Thank you !Dressler
I think this does not work if I specify other args afterwards: create(:specific_keyword, name: 'test', arg2: 'arg2'). The arg2 is not sent to the initialize method. How can I keep the old syntax where I just pass a hash of params ?Dressler
@Dressler I assume other arguments are not attributes of your model?Noiseless
It is a field :arg2 type of my modelDressler
for attributes, I believe it should be something like: initialize_with { new({your: 'custom'}.merge(attributes)) (attributes is a method which returns factory attributes (except transient ones) according to the documentation).Noiseless

© 2022 - 2024 — McMap. All rights reserved.