diff --git a/README.md b/README.md index 088dff4..8393563 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,12 @@ factory_girl_rails is available in the development group. If it's not, Rails will generate standard .yml files instead of factory files. factory_girl takes an option `suffix: 'some_suffix'` to generate factories as -`modelname_some_suffix.rb`. +1modelname_some_suffix.rb`. + +If you use factory_girl for fixture replacement and already have a +`factories.rb` file in the directory that contains your tests, +factory_girl_rails will insert new factory definitions at the top of +`factories.rb`. ## Contributing diff --git a/features/generators.feature b/features/generators.feature index 446795a..547b02b 100644 --- a/features/generators.feature +++ b/features/generators.feature @@ -8,7 +8,7 @@ Feature: And I cd to "testapp" And I add "factory_girl_rails" from this project as a dependency - Scenario: The factory_girl_rails generators create a factory file for each model that I generate + Scenario: The factory_girl_rails generators create a factory file for each model if there is not a factories.rb file When I run `bundle install` with a clean environment And I run `bundle exec rails generate model User name:string --fixture-replacement=factory_girl` with a clean environment And I run `bundle exec rails generate model Namespaced::User name:string --fixture-replacement=factory_girl` with a clean environment @@ -17,12 +17,12 @@ Feature: And the file "test/factories/users.rb" should contain "factory :user do" And the file "test/factories/namespaced_users.rb" should contain "factory :namespaced_user, :class => 'Namespaced::User' do" - Scenario: The factory_girl_rails generators create a factory file with a custom name for each model that I generate + Scenario: The factory_girl_rails generators does not create a factory file for each model if there is a factories.rb file in the test directory When I run `bundle install` with a clean environment - And I set the FactoryGirl :suffix option to "factory" + And I write to "test/factories.rb" with: + """ + FactoryGirl.define do + end + """ And I run `bundle exec rails generate model User name:string --fixture-replacement=factory_girl` with a clean environment - And I run `bundle exec rails generate model Namespaced::User name:string --fixture-replacement=factory_girl` with a clean environment - Then the output should contain "test/factories/users_factory.rb" - And the output should contain "test/factories/namespaced_users_factory.rb" - And the file "test/factories/users_factory.rb" should contain "factory :user do" - And the file "test/factories/namespaced_users_factory.rb" should contain "factory :namespaced_user, :class => 'Namespaced::User' do" + Then the file "test/factories.rb" should contain "factory :user do" diff --git a/lib/generators/factory_girl/model/model_generator.rb b/lib/generators/factory_girl/model/model_generator.rb index d01cbcb..21d6bca 100644 --- a/lib/generators/factory_girl/model/model_generator.rb +++ b/lib/generators/factory_girl/model/model_generator.rb @@ -4,28 +4,82 @@ require 'factory_girl_rails' module FactoryGirl module Generators class ModelGenerator < Base - argument :attributes, :type => :array, :default => [], :banner => "field:type field:type" - class_option :dir, :type => :string, :default => "test/factories", :desc => "The directory where the factories should go" + argument( + :attributes, + type: :array, + default: [], + banner: "field:type field:type" + ) + + class_option( + :dir, + type: :string, + default: "test/factories", + desc: "The directory or file root where factories belong" + ) def create_fixture_file - filename = [table_name, filename_suffix].compact.join('_') - template 'fixtures.erb', File.join(options[:dir], "#{filename}.rb") + if File.exist?(factories_file) + insert_factory_into_existing_file + else + create_factory_file + end end private + def factories_file + options[:dir] + ".rb" + end + + def insert_factory_into_existing_file + insert_into_file( + factories_file, + factory_definition, + after: "FactoryGirl.define do" + ) + end + + def create_factory_file + filename = [table_name, filename_suffix].compact.join('_') + file = File.join(options[:dir], "#{filename}.rb") + create_file(file, single_file_factory_definition) + end + + def factory_definition +<<-RUBY + factory :#{singular_table_name}#{explicit_class_option} do + #{factory_attributes} + end +RUBY + end + + def single_file_factory_definition +<<-RUBY +FactoryGirl.define do +#{factory_definition} +end +RUBY + end + + def factory_attributes + attributes.map do |attribute| + "#{attribute.name} #{attribute.default.inspect}" + end.join("\n") + end + def filename_suffix factory_girl_options[:suffix] end + def factory_girl_options + generators.options[:factory_girl] || {} + end + def generators config = FactoryGirl::Railtie.config config.respond_to?(:app_generators) ? config.app_generators : config.generators end - - def factory_girl_options - generators.options[:factory_girl] || {} - end end end end diff --git a/lib/generators/factory_girl/model/templates/fixtures.erb b/lib/generators/factory_girl/model/templates/fixtures.erb deleted file mode 100644 index 71d7da4..0000000 --- a/lib/generators/factory_girl/model/templates/fixtures.erb +++ /dev/null @@ -1,9 +0,0 @@ -# Read about factories at https://github.com/thoughtbot/factory_girl - -FactoryGirl.define do - factory :<%= singular_table_name %><%= explicit_class_option %> do -<% for attribute in attributes -%> - <%= attribute.name %> <%= attribute.default.inspect %> -<% end -%> - end -end