New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Override or extend entire factories #229
Comments
@roooodcastro, did you ever find a workaround for this? I'd like to do the same. I have an engine we reuse for all of our apps with three models. I append those factories to the host application, but in one case we have a breaking customization. I'd hate to have to load the gem factories by hand in five applications to fix the one that can't use them. I'm using this technique BTW to load them: engine.rb ...
# https://stackoverflow.com/questions/20261585/how-to-use-factorygirl-factories-from-an-engine
initializer "model_core.factories", :after => "factory_girl.set_factory_paths" do
FactoryGirl.definition_file_paths << File.expand_path('../../../spec/factories', __FILE__) if defined?(FactoryGirl)
end
... |
I couldn't find an ideal solution, I thought of a hackish solution, but I still don't think it would work:
Even if this works, it's still a very hackish solution, and there should be a method to specify that the factory is to be overwritten, and that the duplication is not only a mere error. |
I think I figured it out. In addition to If I change my engine to insert it's definitions at the front of the list rather than the end, then use engine.rb initializer "model_core.factories", after: "factory_girl.set_factory_paths" do
FactoryGirl.definition_file_paths.unshift File.expand_path('../../../spec/factories', __FILE__) if defined?(FactoryGirl)
end Redefined factory: FactoryGirl.modify do
factory :foo do
# MAIN APP CHANGES HERE
end
end I haven't actually gottten tests passing yet, but I'll update this comment with fixes if any are needed. Thanks @roooodcastro |
Didn't know about |
Followup: It works!
There is one trick, you can't add aliases in your modify call. It's easy enough to work around by duplicating the FactoryGirl.modify do
factory :gem_engine_name_long_model_name do
# MAIN APP CHANGES HERE
end
end
FactoryGirl.define do
factory :model_name, parent: :gem_engine_name_long_model_name
end |
I can confirm that this strategy works when you need to add or change attributes defined in the factory from engine, but I can't seem to figure out how to remove attributes in the overriding factory. Example: # in engine
FactoryGirl.define do
factory :user do
first_name "John"
last_name "Doe"
end
end
# in main app
FactoryGirl.modify do
factory :user do
name "John Doe"
end
end Results in NoMethodError:
undefined method `first_name=' for #<User:0x007f8db9451138> A dirty workaround would be to define virtual attributes, but, yuck. |
I wonder if you could misuse a # in engine
FactoryGirl.define do
factory :user do
first_name "John"
last_name "Doe"
end
end
# in main app
FactoryGirl.modify do
factory :user do
transient do
first_name nil
last_name nil
end
name "John Doe"
end
end I've never tried this but it's worth a shot. |
It worked! Thanks, @duffyjp |
It looks like between Another option in you wanted to remove specific attributes would be to just remove the entire factory and redefine it. We do have a PR for removing factories: thoughtbot/factory_bot#910 |
Hello, where I work we have multiple apps that share the same database, thus sharing most of the models. Because of this, we created a "core" gem that defines these models with common validations and methods, so we don't need to duplicate it.
However, we now want to do the same with factories, as they also are basically the same in our case. We managed to bundle the factories with the gem and "merge" them with each app's specific factories using something like this:
The problem is, if we need to change an already registered factory to fit the needs of a single app's tests, we can't, because it would throw the error
FactoryGirl::DuplicateDefinitionError
. The only other way would be to either create a new factory with another name, which defeats the whole purpose of this, or to change the factory directly in our gem, which is not ideal and can cause conflicts and break other app's tests.Is there a way to override an already registered factory, or maybe a way to "unregister" a single factory so I can register it again?
Btw, if this turns to be a feature request issue, I'll be glad to help.
The text was updated successfully, but these errors were encountered: