This PR adds the Ruby 3.1 and Rails 7 elements to the CI matrix. To support those changes a number of other changes were required:
- Adding a basic Rails 7 Gemfile and updating `Appraisals`
- Quoting 3.0 in the `.github/workflows/build.yml` file so that this entry pulls Ruby 3.0.x and not Ruby 3.1
- Adding the "--disable-error_highlight" value for RUBYOPT in the build environment to disable Ruby 3.1 error highlighting
- Bumping the version of `standard` and configuring it to run against our oldest supported version
## Enum traits
Given a Rails model with an enum attribute:
```rb
class Task < ActiveRecord::Base
enum status: {queued: 0, started: 1, finished: 2}
end
```
It is common for people to define traits for each possible value of the enum:
```rb
FactoryBot.define do
factory :task do
trait :queued do
status { :queued }
end
trait :started do
status { :started }
end
trait :finished do
status { :finished }
end
end
end
```
With this commit, those trait definitions are no longer necessary—they are defined automatically by factory_bot.
If automatically defining traits for enum attributes on every factory is not desired, it is possible to disable the feature by setting `FactoryBot.automatically_define_enum_traits = false` (see commit: [Allow opting out of automatically defining traits](5a20017351)).
In that case, it is still possible to explicitly define traits for an enum attribute in a particular factory:
```rb
FactoryBot.automatically_define_enum_traits = false
FactoryBot.define do
factory :task do
traits_for_enum(:status)
end
end
```
It is also possible to use this feature for other enumerable values, not specifically tied to ActiveRecord enum attributes:
```rb
class Task
attr_accessor :status
end
FactoryBot.define do
factory :task do
traits_for_enum(:status, ["queued", "started", "finished"])
end
end
```
The second argument here can be an enumerable object, including a Hash or Array.
Closes#1049
Co-authored-by: Lance Johnson <lancejjohnson@gmail.com>
Co-authored-by: PoTa <pota@mosfet.hu>
Co-authored-by: Frida Casas <fridacasas.fc@gmail.com>
Co-authored-by: Daniel Colson <danieljamescolson@gmail.com>
In this PR the cop Style/MethodMissing was split into
Style/MethodMissingSuper and Style/MissingRespondToMissing.
https://github.com/rubocop-hq/rubocop/pull/5811
This commit goes through the disables and updates them to reflect the
appropriate new Cops.
This code was a bit confusing before this change.
The only time we care about `args.first` is if we are creating an
association, so this PR gives `args.first` the name
`association_options` to reflect that.
The PR also pulls out a predicate method to give a name to the step of
validating that `args.first` are in indeed association options.
Some people upgrade straight from factory_bot < 4.11 to factory_bot >=
5.0 and miss the deprecation cycle for static attributes. I have gotten
some feedback that the NoMethodError is confusing. Since we know that in
most cases people are seeing the NoMethodError when trying to define
static attributes, we offer them a "Did you mean?"-style suggestion for
how they might update to dynamic attributes.
I removed the extra test for setter methods. It was a remnant of
something I had removed in #1200. I see no reason to have special
treatment for setters at this point.
Closes https://github.com/thoughtbot/factory_bot/issues/1272
Fixes#1257
When sequence rewinding was first introduced in #1078 it only applied to
globally defined sequences. To get rewinding to work for inline
sequences as well we registered them "privately" in the global registry
in #1164. Unfortunately in #1164 we did not take inline sequences inside
traits into consideration. Since trait names are not unique, it is
possibly to get a `FactoryBot::DuplicateDefinitionError` when defining
two sequences that have the same name in two traits that have the same
name.
This PR abandons the idea of "privately" registering inline sequences,
and instead keeps a separate list of all the inline sequences just for
the purpose of rewinding them.
We had configured RuboCop to allow lines with up to 142 characters. This
PR fixes a few of the worst offenders so we can bring that number down
to 110.
To make it obvious that these are non-standard cases.
Also add respond_to_missing? to the decorator.
We are using Style/MethodMissing rather than
Style/MethodMissingSuper and Style/MissingRespondToMissing because we
are still on RuboCop 0.54.
Closes#1033
> Arguably, association should raise and let the developer know
> they're using it in an unexpected way. I'd love to see a PR for
> that (with a test!), so if you're interested in contributing that,
> please do!
> https://github.com/thoughtbot/factory_girl/issues/1032#issuecomment-329297006
Co-authored-by: Daniel Colson <danieljamescolson@gmail.com>
Inside `super` Ruby calls `inspect`, but since we have undefined
`inspect` on the definition proxy we end up declaring an implicit
`inspect` attribute. We do the same thing with `methods` and
`singleton_methods`, and then `inspect` again. By the time we finally
see the NoMethodError, we see it on a
`FactoryBot::Declaration::Implicit` instead of the definition proxy.
By raising the NoMethodError manually we avoid this nonsense and have
the added benefit of showing the name of the factory where the missing
method came from.
I am leaving the Static Attributes section in the README for now, since
it might still be helpful for people upgrading, but I took out the
example because I don't want to show invalid code.
I removed reference to static attributes in the definition_proxy
documentation, and updated the signature of add_attributes. I also
got rid of the bit about yielding a FactoryBot::Strategy, which is not
correct. We document correctly in the GETTING_STARTED that we yield an
evaluator instance.
This changes the signature of `add_attribute`, so if you pass a value at
all you will now get an `ArgumentError`. Any `method_missing`-style
static attribute definitions will become `NoMethodError`s.
This was originally opened as #1078, but this addresses the review
comments on that PR.
By registering the inline sequences, we allow them to get rewound with
`FactoryBot.rewind_sequences`. We register them with
`__#{factory_name}_#{sequence_name}__` to avoid conflicting with any
reasonably named global sequences, and to hint that we should not be
generating values from these sequences directly.
Co-authored-by: Damian Le Nouaille <dam@dln.name>
Co-authored-by: Damian Galarza <galarza.d@gmail.com>