Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 4 Use Factory Girl factories from Engine

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.)

like image 322
cast01 Avatar asked Oct 31 '22 18:10

cast01


1 Answers

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.

like image 191
cast01 Avatar answered Nov 15 '22 06:11

cast01