Skip to content

Commit

Permalink
version 0.8.0. changing the defaults and option names, updated doc
Browse files Browse the repository at this point in the history
  • Loading branch information
garysweaver committed Nov 7, 2012
1 parent decfb52 commit b183c53
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 33 deletions.
64 changes: 39 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,7 @@ It works just about the same as `Stepford::FactoryGirl` except it is called `Ste

##### RSpec Helpers

`Stepford::FactoryGirl` and `Stepford::FactoryGirlCache` are a lot to type.

Instead put this in your `spec/spec_helper.rb`:
Put this in your `spec/spec_helper.rb`:

require 'stepford/factory_girl_rspec_helpers'

Expand All @@ -117,30 +115,38 @@ Then you can just use `cache_create`, `cache_create_list`, `cache_build`, `cache

cache_create(:foo)

#### Factory Girl CLI
#### CLI

##### How NOT NULL, and Other Database Constraints and Active Record Validations Are Handled
Stepford has a CLI to automatically create your factories file(s).

If the ActiveRecord column `null` property for the attribute is true for the attribute or foreign key for the association, or if there is a presence validator for an attribute or foreign key for the association, then that attribute or association will be defined by the default factory.
##### Creating Factories

Currently uniqueness constraints are ignored and must be handled by FactoryGirl sequence or similar if not automatically populated by your model or the database, e.g. in your factory, if username uniqueness is enforced by a unique constraint on the database-side, you'll need to do something like this manually in the factory:
Autogenerate `test/factories.rb` from all model files in `app/models`:

sequence(:username) {|n| "user#{n}" }
bundle exec stepford factories

##### Creating Factories
If you want one file per model, use `--multiple`. The default path is `test/factories`, which it assumes exists. In that directory, it will create a factory file for each model. If you want separate factory files in `spec/factories`, you'd use:

The default will assume a `test/factories` directory exists. In that directory, it will create a factory file for each model containing example values for all attributes except primary keys, foreign keys, created_at, and updated_at:
bundle exec stepford factories --path spec/factories --multiple

bundle exec stepford factories
##### RSpec

To put all of your factories into `spec/factories.rb`:

bundle exec stepford factories --single --path spec
bundle exec stepford factories --path spec

It will figure out that you want a single file, if the path ends in `.rb`:
This also works:

bundle exec stepford factories --path spec/support/factories.rb

##### Specifying Models

By default, Stepford processes all models found in `app/models`.

Specify `--models` and a comma-delimited list of models to only output the models you specify. If you don't want to overwrite existing factory files, you should direct the output to another file and manually copy each in:

bundle exec stepford factories --path spec/support/put_into_factories.rb --models foo,bar,foo_bar

##### Traits

To generate traits for each attribute that would be included with `--attributes`, but isn't because `--attributes` is not specified:
Expand All @@ -153,27 +159,29 @@ To generate traits for each association that would be included with `--associati

##### Associations

Associations in FactoryGirl aren't that great. There are factory interdependence issues (one factory requires another that requires it, etc.- that doesn't work that well) when you don't use `after(:create)` or `after(:build)`, and those don't work if you presence validate the associations or their foreign_keys have NOT NULL.

However, if you don't have anything that complex or don't mind hand-editing the factories to try to fix issues, go for it. Here are the related methods.

###### Include All Associations

To include all associations even if they aren't deemed to be required by not null ActiveRecord constraints defined in the model:

bundle exec stepford factories --associations

##### Stepford Checks Model Associations
###### Stepford Checks Model Associations

If `--associations` or `--validate-associations` is specified, Stepford first loads Rails and attempts to check your models for broken associations.

If associations are deemed broken, it will output proposed changes.

##### No IDs

If working with a legacy schema, you may have models with foreign_key columns that you don't have associations defined for in the model. If that is the case, we don't want to assign arbitrary integers to them and try to create a record. If that is the case, try `--exclude-all-ids`, which will exclude those ids as attributes defined in the factories and you can add associations as needed to get things working.

##### Ignored Required Assocations
###### Include Required Assocations

With `--ignore-required-associations` it won't include NOT NULL foreign key associations or presence validated associations by default.
With `--include-required-associations` it will include NOT NULL foreign key associations or presence validated associations.

##### Cache Associations
###### Cache Associations

Use `--cache-associations` to store and use factories to avoid 'stack level too deep' errors.
Use `--cache-associations` will use the .

This uses the [factory_girl-cache][factory_girl-cache] gem in the autogenerated factories, so you will need to include it also in your Gemfile:

Expand All @@ -183,11 +191,17 @@ and

bundle install

##### Specifying Models
##### No IDs

Specify `--models` and a comma-delimited list of models to only output the models you specify. If you don't want to overwrite existing factory files, you should direct the output to another file and manually copy each in:
If working with a legacy schema, you may have models with foreign_key columns that you don't have associations defined for in the model. If that is the case, we don't want to assign arbitrary integers to them and try to create a record. If that is the case, try `--exclude-all-ids`, which will exclude those ids as attributes defined in the factories and you can add associations as needed to get things working.

bundle exec stepford factories --path spec/support/put_into_factories.rb --models foo,bar,foo_bar
##### How NOT NULL, and Other Database Constraints and Active Record Validations Are Handled

If the ActiveRecord column `null` property for the attribute is true for the attribute or foreign key for the association, or if there is a presence validator for an attribute or foreign key for the association, then that attribute or association will be defined by the default factory.

Currently uniqueness constraints are ignored and must be handled by FactoryGirl sequence or similar if not automatically populated by your model or the database, e.g. in your factory, if username uniqueness is enforced by a unique constraint on the database-side, you'll need to do something like this manually in the factory:

sequence(:username) {|n| "user#{n}" }

##### Testing Factories

Expand Down
4 changes: 2 additions & 2 deletions lib/stepford/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module Stepford
class CLI < Thor
desc "factories", "create FactoryGirl factories"
method_option :single, :desc => "Put all factories into a single file", :type => :boolean
method_option :multiple, :desc => "Put each model's factory into a single file", :type => :boolean
method_option :path, :desc => "Pathname of file to contain factories or path of directory to contain factory/factories"
method_option :associations, :desc => "Include all associations in factories, not just those that are required due to ActiveRecord presence validation or column not null restriction", :type => :boolean
method_option :validate_associations, :desc => "Validate associations in factories even if not including associations", :type => :boolean
Expand All @@ -13,7 +13,7 @@ class CLI < Thor
method_option :attribute_traits, :desc => "Include traits for attributes that would be output with --attributes that wouldn't be otherwise when --attributes is not specified", :type => :boolean
method_option :association_traits, :desc => "Include traits for associations that would be output with --associations that wouldn't be otherwise when --associations is not specified", :type => :boolean
method_option :cache_associations, :desc => "Use singleton values to avoid 'stack level too deep' circular reference(s)", :type => :boolean
method_option :ignore_required_associations, :desc => "Won't include NOT NULL foreign key associations or presence validated associations by default", :type => :boolean
method_option :include_required_associations, :desc => "Include NOT NULL foreign key associations or presence validated associations by default", :type => :boolean
def factories()
# load Rails environment
require './config/environment'
Expand Down
10 changes: 5 additions & 5 deletions lib/stepford/factory_girl_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ def self.generate_factories(options={})
# if has a foreign key, then if NOT NULL or is a presence validate, the association is required and should be output. unfortunately this could mean a circular reference that will have to be manually fixed
has_presence_validator = model_class.validators_on(assc_sym).collect{|v|v.class}.include?(ActiveModel::Validations::PresenceValidator)
required = reflection.foreign_key ? (has_presence_validator || model_class.columns.any?{|c| !c.null && c.name.to_sym == reflection.foreign_key.to_sym}) : false
should_be_trait = !(options[:associations] || (!options[:ignore_required] && required)) && options[:association_traits]
if options[:associations] || (!options[:ignore_required_associations] && required) || should_be_trait
should_be_trait = !(options[:associations] || (options[:include_required_associations] && required)) && options[:association_traits]
if options[:associations] || (options[:include_required_associations] && required) || should_be_trait
if options[:cache_associations]
if reflection.macro == :has_many
is_default_plural_association_name = (clas_sym.to_s.pluralize.to_sym == assc_sym)
Expand Down Expand Up @@ -133,10 +133,10 @@ def self.get_factories_rb_pathname(options)
if options[:path].end_with?('.rb')
path = options[:path]
else
if options[:single]
path = File.join(options[:path],'factories.rb')
else
if options[:multiple]
path = options[:path]
else
path = File.join(options[:path],'factories.rb')
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/stepford/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Stepford
VERSION = '0.7.0'
VERSION = '0.8.0'
end

0 comments on commit b183c53

Please sign in to comment.