factory_boy icon indicating copy to clipboard operation
factory_boy copied to clipboard

Transform a field before save to database

Open kosciej16 opened this issue 3 years ago • 3 comments

I am trying to create UserFactory with sqlalchemy engine. The problem is I need to hash password before saving to database. I tried many things but nothing worked.

I tried to use lazy attributes but it looks like I can use only not lazy attributes i lambda body. I tried post_generate hook, but it looks like row is saved before that hook. I found transformer but it looks like it didn't exist now. I tried to override _create function, but didn't know how to call super there (and would have to override _build too).

class UserFactory(factory.alchemy.SQLAlchemyModelFactory):
    class Meta:
        model = UserModel
        sqlalchemy_session = test_db
        sqlalchemy_session_persistence = "commit"

    username = factory.Faker("pystr")
    password = factory.transform(lambda pass: my_hash(pass)) # how to achieve that?

Thanks in advance!

kosciej16 avatar Apr 02 '21 17:04 kosciej16

The Transformer is what you are looking for, but needs to be released. @rbarrois usually handles the releases, he schedules time to handle the support for bugs reported.

In the meantime, you can make do with LazyFunction.

class UserFactory(SQLAlchemyModelFactory):
    class Meta:
        model = UserModel
        sqlalchemy_session = test_db
        sqlalchemy_session_persistence = "commit"

    password = factory.LazyFunction(lambda: make_pass("hunter2"))

# Create a user with password hunter2
UserFactory.create()
# Create a user with password foo
UserFactory.create(make_pass("foo"))

francoisfreitag avatar Apr 02 '21 17:04 francoisfreitag

@francoisfreitag Thank you for reply! Unfortunately it doesn't solve my problem because I cannot still just pass raw password into create function and it cause much code redundance. But it's not so crucial that I couldn't wait unit transformers will appear ;)

And... what is the reason of LazyFunction? Wouldn't that be the same?

    password = make_pass("hunter2")

kosciej16 avatar Apr 03 '21 16:04 kosciej16

That’s correct, password = make_pass("hunter2") would be the same as using a LazyFunction. It would even be slightly more efficient, as the value is resolved at import time, rather than on each factory call.

francoisfreitag avatar Apr 06 '21 09:04 francoisfreitag