When using one of the `*_list` methods, allow the block to receive array
index for each object:
```ruby
posts = build_list(:post, 10, title: 'Post number') do |post, i|
post.title = "#{post.title} #{i + 1}"
end
posts.first.title # => "Post number 1"
posts.last.title # => "Post number 10"
```
A block that only takes in the object still works as before, as does
leaving off the block entirely.
Co-authored-by: Mike Countis <mike.countis@gmail.com>
Most of this was fixed by adding the `attribute-defined-statically-cop`
branch of `thoughtbot/rubocop-rspec` to the Gemfile and running:
```sh
rubocop \
--require rubocop-rspec \
--only FactoryBot/AttributeDefinedStatically \
--auto-correct
```
I had to update the cucumber tests manually, and I realized our changes
don't handle `ignore` blocks or blocks with arity 1 that use the yielded
DefinitionProxy. I will update
https://github.com/rubocop-hq/rubocop-rspec/pull/666to handle these
cases.
Instead of calling before_create, after_build, after_create, or
after_stub, you can now call:
before(:create) {|instance| instance.name = "overridden!" }
after(:create) {|instance| instance.name = "overridden!" }
after(:build) {|instance| instance.name = "overridden!" }
after(:stub) {|instance| instance.name = "overridden!" }
Additionally, you can declare callbacks longhand:
callback(:after_stub) {|instance| instance.name = "overridden!" }
This allows for custom callbacks to be defined:
callback(:custom_callback) {|instance| instance.name = "overridden!" }
Which can then be used from a custom strategy:
class CustomStrategy
def association(runner); end
def result(evaluation)
evaluation.object.tap do |instance|
evaluation.notify(:custom_callback, instance)
end
end
end
FactoryGirl.register_strategy(:custom, CustomStrategy)
This would allow for calling:
FactoryGirl.custom(:user)
Which would return the user instance but execute the :custom_callback callback
on the user instance first.