activerecord-hackery/ransack · error · ArgumentError

Invalid argument (#{groupings.class}) supplied to groupings=

Error message

Invalid argument (#{groupings.class}) supplied to groupings=

What it means

Nodes::Grouping#groupings= (aliased g=) accepts only an Array of grouping attribute hashes or an indexed Hash ({'0' => {...}, '1' => {...}}), as produced by Rails nested form params for OR/AND sub-groups. Anything else — a String, a single attributes hash without index nesting, a scalar — raises this ArgumentError.

Source

Thrown at lib/ransack/nodes/grouping.rb:104

      def groupings
        @groupings ||= []
      end
      alias :g :groupings

      def groupings=(groupings)
        case groupings
        when Array
          groupings.each do |attrs|
            grouping_object = new_grouping(attrs)
            self.groupings << grouping_object if grouping_object.values.any?
          end
        when Hash
          groupings.each do |index, attrs|
            grouping_object = new_grouping(attrs)
            self.groupings << grouping_object if grouping_object.values.any?
          end
        else
          raise ArgumentError,
            "Invalid argument (#{groupings.class}) supplied to groupings="
        end
      end
      alias :g= :groupings=

      def method_missing(method_id, *args)
        method_name = method_id.to_s.dup
        writer = method_name.sub!(/\=$/, ''.freeze)
        if attribute_method?(method_name)
          if writer
            write_attribute(method_name, *args)
          else
            read_attribute(method_name)
          end
        else
          super
        end
      end

View on GitHub (pinned to e82f6bab39)

Solutions

  1. Use the indexed form: grouping.g = { '0' => { m: 'or', name_eq: 'x' } } or an array [{ m: 'or', name_eq: 'x' }]
  2. Prefer the public params API: Person.ransack(g: { '0' => { m: 'or', name_eq: 'x' } })
  3. Inspect what a real Ransack form submits (q[g][0][...]) and mirror that shape

Example fix

# before
search.base.groupings = { m: 'or', name_eq: 'x' }
# (Hash values are condition attrs, not indexed groupings -> may not raise here, but a String does)
grouping.groupings = 'name_eq'
# => ArgumentError: Invalid argument (String) supplied to groupings=

# after
grouping.groupings = [{ m: 'or', name_eq: 'x' }]
Defensive patterns

Strategy: validation

Validate before calling

groups = [groups] if groups.is_a?(Hash) && groups.values.any?(::Hash) && !groups.key?('m')
grouping.groupings = groups  # normalize to Array of grouping hashes or indexed Hash

Type guard

def valid_groupings_arg?(arg)
  arg.is_a?(Array) || arg.is_a?(Hash)
end

Prevention

When it happens

Trigger: search.base.groupings = { m: 'or', name_eq: 'x' } (a plain condition-style hash instead of an indexed hash of groupings); grouping.g = 'name_eq' (String); programmatically assigning a Hash whose values are not per-index grouping hashes.

Common situations: Building composite OR searches in code and passing one flat condition hash where an indexed wrapper is required; JSON-to-params conversion flattening the g nesting level; specs hand-crafting grouping params.

Related errors


AI-assisted analysis of activerecord-hackery/ransack@e82f6bab39 (2026-08-21). Data as JSON: /api/errors/cb3730e215e81a37. Report an issue: GitHub.