{"record":{"id":"cb3730e215e81a37","repo":"activerecord-hackery/ransack","slug":"invalid-argument-groupings-class-supplied-to","errorCode":null,"errorMessage":"Invalid argument (#{groupings.class}) supplied to groupings=","messagePattern":"Invalid argument \\(#(.+?)\\) supplied to groupings=","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/ransack/nodes/grouping.rb","lineNumber":104,"sourceCode":"      def groupings\n        @groupings ||= []\n      end\n      alias :g :groupings\n\n      def groupings=(groupings)\n        case groupings\n        when Array\n          groupings.each do |attrs|\n            grouping_object = new_grouping(attrs)\n            self.groupings << grouping_object if grouping_object.values.any?\n          end\n        when Hash\n          groupings.each do |index, attrs|\n            grouping_object = new_grouping(attrs)\n            self.groupings << grouping_object if grouping_object.values.any?\n          end\n        else\n          raise ArgumentError,\n            \"Invalid argument (#{groupings.class}) supplied to groupings=\"\n        end\n      end\n      alias :g= :groupings=\n\n      def method_missing(method_id, *args)\n        method_name = method_id.to_s.dup\n        writer = method_name.sub!(/\\=$/, ''.freeze)\n        if attribute_method?(method_name)\n          if writer\n            write_attribute(method_name, *args)\n          else\n            read_attribute(method_name)\n          end\n        else\n          super\n        end\n      end","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/activerecord-hackery/ransack/blob/e82f6bab3956c5597e7debbefa218d9e94e58ceb/lib/ransack/nodes/grouping.rb#L86-L122","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use the indexed form: grouping.g = { '0' => { m: 'or', name_eq: 'x' } } or an array [{ m: 'or', name_eq: 'x' }]","Prefer the public params API: Person.ransack(g: { '0' => { m: 'or', name_eq: 'x' } })","Inspect what a real Ransack form submits (q[g][0][...]) and mirror that shape"],"exampleFix":"# before\nsearch.base.groupings = { m: 'or', name_eq: 'x' }\n# (Hash values are condition attrs, not indexed groupings -> may not raise here, but a String does)\ngrouping.groupings = 'name_eq'\n# => ArgumentError: Invalid argument (String) supplied to groupings=\n\n# after\ngrouping.groupings = [{ m: 'or', name_eq: 'x' }]","handlingStrategy":"validation","validationCode":"groups = [groups] if groups.is_a?(Hash) && groups.values.any?(::Hash) && !groups.key?('m')\ngrouping.groupings = groups  # normalize to Array of grouping hashes or indexed Hash","typeGuard":"def valid_groupings_arg?(arg)\n  arg.is_a?(Array) || arg.is_a?(Hash)\nend","tryCatchPattern":null,"preventionTips":["Use Ransack's own g form fields as the canonical params shape: q[g][0][c][0][...]","When building OR groups in code, pass an array of per-group hashes: [{ m: 'or', name_eq: 'x' }]","Validate external/JSON payloads against the indexed-hash shape before feeding them to the search"],"tags":["ruby","rails","ransack","nodes","groupings","argumenterror"],"backgroundTag":"invalid-params-structure","analyzedSha":"e82f6bab3956c5597e7debbefa218d9e94e58ceb","analyzedAt":"2026-08-21T19:30:23.639Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}