Skip to content

Fix ArgumentError when filtering by scopes with array arguments#1590

Merged
scarroll32 merged 4 commits intomainfrom
copilot/fix-b3efa35e-f386-4677-abd2-1bc9467e369c
Sep 24, 2025
Merged

Fix ArgumentError when filtering by scopes with array arguments#1590
scarroll32 merged 4 commits intomainfrom
copilot/fix-b3efa35e-f386-4677-abd2-1bc9467e369c

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Sep 24, 2025

Fixes #XXX where filtering by scopes that accept arrays as single arguments would raise ArgumentError: wrong number of arguments (given 2, expected 1).

Problem

When using scopes with arity 1 that expect an array as a single parameter, Ransack would incorrectly splat the array arguments, causing argument count mismatches:

class Person < ActiveRecord::Base
  scope :domestic, ->(countries) { where(country: countries) }
  
  def self.ransackable_scopes(auth_object = nil)
    [:domestic]
  end
end

# This would raise ArgumentError
Person.search(domestic: ['US', 'JP'])
# ArgumentError: wrong number of arguments (given 2, expected 1)

# Users had to work around this with nested arrays
Person.search(domestic: [['US', 'JP']])  # Workaround

Root Cause

The chain_scope method in lib/ransack/context.rb was always using the splat operator (*args) when calling scopes, regardless of the scope's arity. For scopes expecting a single array argument, this would split ['US', 'JP'] into two separate arguments 'US', 'JP', violating the lambda's arity constraint.

Solution

Added special handling in chain_scope to detect when a scope has arity 1 and receives an array argument. In this case, the array is passed as a single argument instead of being splatted:

def chain_scope(scope, args)
  return unless @klass.method(scope) && args != false
  @object = if scope_arity(scope) < 1 && args == true
              @object.public_send(scope)
            elsif scope_arity(scope) == 1 && args.is_a?(Array)
              # For scopes with arity 1, pass the array as a single argument
              @object.public_send(scope, args)
            else
              @object.public_send(scope, *args)
            end
end

Testing

Added comprehensive test coverage for various scope arity scenarios:

  • Arity 1 scopes: Arrays are now passed as single arguments (main fix)
  • Flexible arity scopes (negative arity): Arrays continue to be splatted as expected
  • Multi-parameter scopes (arity > 1): Arrays continue to be splatted as expected
  • Backwards compatibility: The nested array workaround continues to work

Impact

  • Fixes the reported issue: Person.search(domestic: ['US', 'JP']) now works
  • No breaking changes: All existing functionality preserved
  • Backwards compatible: Existing workarounds continue to work
  • Minimal change: Only 3 lines of code added for surgical fix

This change makes Ransack's scope handling more intuitive and eliminates the need for users to understand lambda arity details when using array arguments with scopes.

Fixes #404


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Copilot AI and others added 2 commits September 24, 2025 14:06
Co-authored-by: scarroll32 <11340230+scarroll32@users.noreply.github.com>
Co-authored-by: scarroll32 <11340230+scarroll32@users.noreply.github.com>
Copilot AI changed the title [WIP] Filtering by scopes with an array as an argument raises ArgumentError Fix ArgumentError when filtering by scopes with array arguments Sep 24, 2025
Copilot AI requested a review from scarroll32 September 24, 2025 14:10
@scarroll32 scarroll32 marked this pull request as ready for review September 24, 2025 19:13
@scarroll32 scarroll32 requested review from Copilot and removed request for scarroll32 September 24, 2025 19:14
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes an ArgumentError that occurred when filtering by scopes with array arguments in Ransack, specifically for scopes with arity 1 that expect an array as a single parameter. The fix adds special handling to prevent incorrect array splatting while maintaining backwards compatibility.

  • Added conditional logic to handle scopes with arity 1 receiving array arguments
  • Added comprehensive test coverage for various scope arity scenarios
  • Maintained backwards compatibility with existing workarounds

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
lib/ransack/context.rb Added special case handling for arity 1 scopes to pass arrays as single arguments instead of splatting
spec/ransack/search_spec.rb Added comprehensive test coverage for array argument handling across different scope arities

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@scarroll32 scarroll32 enabled auto-merge (squash) September 24, 2025 19:19
@scarroll32 scarroll32 merged commit e830390 into main Sep 24, 2025
25 checks passed
@scarroll32 scarroll32 deleted the copilot/fix-b3efa35e-f386-4677-abd2-1bc9467e369c branch September 24, 2025 19:21
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.

Filtering by scopes with an array as an argument raises ArgumentError

3 participants