Skip to content

RSpec/SpecFilePathFormat allow multiple values for same key in IgnoreMetadata#2070

Closed
sriedel wants to merge 16 commits into
rubocop:masterfrom
sriedel:sr/allow_multiple_values_to_spec_file_path_format_ignore_metadata
Closed

RSpec/SpecFilePathFormat allow multiple values for same key in IgnoreMetadata#2070
sriedel wants to merge 16 commits into
rubocop:masterfrom
sriedel:sr/allow_multiple_values_to_spec_file_path_format_ignore_metadata

Conversation

@sriedel

@sriedel sriedel commented Apr 4, 2025

Copy link
Copy Markdown

RSpec/SpecFilePathFormat allows ignoring certain values in rspec metadata through the IgnoreMetadata option, as given in the documentation:

      # @example `IgnoreMetadata: {type=>routing}` (default)
      #   # good
      #   whatever_spec.rb         # describe MyClass, type: :routing do; end

However the current implementation does not seem to allow supplying multiple values for the same key - e.g. if you have some specs marked type: controller, others as type: :model etc, only one of controller, model, ... can be supplied to be ignored.

This is probably due to an oversight (or me not being able to figure out how to properly supply an array of values to be ignored).

The PR allows for either an array or a single value to be given for a key in the IgnoreMetadata option.

While it would also be desirable to give a true value to ignore all metadata, in the format that IgnoreMethods use, this should probably be part of a different PR.

@sriedel sriedel requested a review from a team as a code owner April 4, 2025 10:51
end
end

context 'when configured with `IgnoreMetadata: { "foo" => ["bar"] }`' do

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think maybe you should write a spec for IgnoreMetadata: { "foo" => ["bar", "baz"] } and validate that it ignores specs with either value. And that it does not ignore a spec without another value for foo, or no foo metadata at all.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair, are the amended specs what you had in mind? I needed to play around with the wording a bit, since I was over the line length limit by one and two characters respectively, by using the existing phrasing.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for ignorance, but what if the value of the metdata value is an array of bar baz?
Or an array of just bar?

I haven’t glanced over the changes, but if we happen to want to allow multiple values, there will be less ambiguity if we accept accept a list of metadata to ignore. Will it work?

Comment thread config/default.yml Outdated
IgnoreMetadata:
type: routing
VersionAdded: '2.24'
VersionChanged: "<<next>>"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is unnecessary. Could you please revert?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, however I'd like to confirm that the revert would be correct, as the Pull Request template specifically states:

If you have modified an existing cop's configuration options:

- [ ] Set `VersionChanged: "<<next>>"` in `config/default.yml`.

and this PR does change an existing cops configuration options.

@ydah ydah Apr 4, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to my understanding, "modified an existing cop's configuration options" refers to instances such as when adding a new configuration option, changing a name, or for example, when adding autocorrect functionality and adding Autocorrect: true, we should add VersionChanged: "<<next>>".

Comment on lines +81 to +82
ignore_values = ignore_metadata[key.to_s]
ignore_values = [ignore_values] unless ignore_values.is_a?(Array)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use Array() instead:

Suggested change
ignore_values = ignore_metadata[key.to_s]
ignore_values = [ignore_values] unless ignore_values.is_a?(Array)
ignore_values = Array(ignore_metadata[key.to_s])

@ydah

ydah commented Apr 4, 2025

Copy link
Copy Markdown
Member

Could you rebase to the latest master branch?

Comment thread CHANGELOG.md Outdated
# # good
# whatever_spec.rb # describe MyClass, type: :routing do; end
#
# @example `IgnoreMetadata: {type=>[routing,models]}` (default)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it really configured like this in YAML?

# @example `IgnoreMetadata: {type=>[routing,models]}` (default)
# # good
# whatever_spec.rb # describe MyClass, type: :routing do; end
# whatever_spec.rb # describe MyClass, type: :models do; end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the metadata's value IS an array?

RSpec.describe Airplane, prepare: [:fuel] do

How do we define IgnoreMetadata in YAML?

private

def register_offense(node, change_node)
return unless node.parent.send_type?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated?


def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
return if node.each_ancestor(:def, :defs).any?
return if node.each_ancestor(:any_def).any?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This, too, and related specs

# @example `IgnoreMetadata: {type=>[routing,models]}` (default)
# # good
# whatever_spec.rb # describe MyClass, type: :routing do; end
# whatever_spec.rb # describe MyClass, type: :models do; end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Side note: how do we ignore any value for a key?

# @example `IgnoreMetadata: {type=>[routing,models]}` (default)
# # good
# whatever_spec.rb # describe MyClass, type: :routing do; end
# whatever_spec.rb # describe MyClass, type: :models do; end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm hinting towards:

IgnoreMetadata:
  - prepare
  - type: model
  - type: routing
  - skip: [database]

Luckily enough, YAML allows to mix all that, and to cover all ignored cases unambiguously.

@sriedel

sriedel commented Apr 7, 2025

Copy link
Copy Markdown
Author

I seem to have fat-fingered the rebase. I'll close this PR and reopen a new one with the current state of changes tomorrow.

@sriedel

sriedel commented Apr 10, 2025

Copy link
Copy Markdown
Author

Clean rebase PR in #2076

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants