I've created a rails engine (full, not mountable) to provide models to a number of different rails apps. I use Factory Girl Rails to test this engine and the tests all run fine for the engine itself.
I now want to be able to use these factories in other apps that include this engine.
The dependencies for the Gemspec look like this:
s.add_dependency "rails", "~> 4.0.3"
s.add_dependency "mysql2", "~> 0.3.15"
s.add_development_dependency "rspec-rails", "~> 3.0.0.beta"
s.add_development_dependency "factory_girl_rails", "~> 4.4.1"
s.add_development_dependency "shoulda-matchers", "~> 2.5.0"
And i have defined my factories in /spec/factories.rb:
factory :user do
...
end
To add the factories.rb to the definition paths in factory girl, I added the following to my /lib/engine_name/engine.rb file:
class Engine < ::Rails::Engine
initializer "model_core.factories", :after => "factory_girl.set_factory_paths" do
FactoryGirl.definition_file_paths << File.expand_path('../../../spec/factories.rb', __FILE__) if defined?(FactoryGirl)
end
end
In my rails apps I include the engine by adding the following to the Gemfile:
gem 'engine_name', git: "<GIT_LOCATION>"
I also add factory_girl_rails to the app (is there a way I can expose this from the engine? rather than having to specify it in the apps Gemfile too?).
And require factory girl rails in spec_helper.rb:
require 'factory_girl_rails'
Now when I write, say, a controller test like the following:
it "saves the user to the database" do
expect{post :create, user: attributes_for(:user)}.to change{User.count}.by(1)
end
I get the error: "Factory not registered: user"
I've double checked the factory girl definition file paths by opening the ruby console and running FactoryGirl.definition_file_paths
and i can see the factories.rb from the engine in the output: "/home/ ... /gems/engine-name-abc123/spec/factories.rb"
Is there anything else i need to do to make these factories available?
(I have found a few similar questions on stackoverflow and beyond that all seem to point to adding those lines in engine.rb, or specifying namespaces in the factories.rb but I am not using namespaces with this engine.)
I found the easiest route to take with this was to add an install generator that simply copies the factories over. I also have the generator run the install migrations rake task as I will need these in any apps that use the engine.
So, in lib/generators/my_engine/install/install_generator.rb
:
module MyEngine
module Generators
class InstallGenerator < Rails::Generators::Base
source_root File.expand_path('../templates', __FILE__)
def copy_migrations
rake("my_engine:install:migrations")
end
def copy_factories
copy_file "../path/to/spec/factories.rb", "spec/factories.rb"
end
end
end
end
Now in projects that use this engine, I simply run rails generate my_engine:install
and the factories (and migrations) are ready for me to use.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With