{"record":{"id":"f75a5aa167a36cb9","repo":"instructure/canvas-lms","slug":"cannot-pass-both-a-module-name-and-a-block","errorCode":null,"errorMessage":"cannot pass both a module_name and a block","messagePattern":"cannot pass both a module_name and a block","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"gems/autoextend/lib/autoextend.rb","lineNumber":66,"sourceCode":"    # If User is already defined, it will immediately include\n    # the MyUserExtension module into it. It then sets up a hook\n    # to automatically include in User if it becomes defined again\n    # (like from ActiveSupport reloading).\n    #\n    # You can make an extension optional, which is for information only,\n    # so that if you have a spec that checks if all extensions were used\n    # it can ignore optional extensions.\n    def hook(const_name,\n             module_name = nil,\n             method: :include,\n             singleton: false,\n             after_load: false,\n             optional: false,\n             before: [],\n             after: [],\n             &block)\n      raise ArgumentError, \"block is required if module_name is not passed\" if !module_name && !block\n      raise ArgumentError, \"cannot pass both a module_name and a block\" if module_name && block\n\n      extension = Extension.new(const_name,\n                                module_name,\n                                method,\n                                block,\n                                singleton,\n                                optional,\n                                Array(before),\n                                Array(after))\n\n      const_extensions = extensions_hash[const_name.to_sym] ||= []\n      const_extensions << extension\n\n      if module_name.is_a?(Module)\n        module_name = module_name.name\n      end\n\n      # immediately extend the class if it's already defined","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/gems/autoextend/lib/autoextend.rb#L48-L84","documentation":"Autoextend.hook is strictly either/or: you may supply a module_name (existing module to mix in) OR a &block (inline module), never both. Supplying both is ambiguous — the gem would not know which extension source to use — so hook raises ArgumentError up front.","triggerScenarios":"Calling Autoextend.hook('Model', 'SomeModule', :method) { ... } — a module_name string plus an attached block in the same call.","commonSituations":"Merging two hook registrations into one call during a refactor; copy-pasting a block-based hook and leaving the old module_name argument in place; IDE snippets that prefill module_name while the developer also writes a block.","solutions":["Remove the block and keep module_name if the extension lives in an existing module","Remove the module_name argument and keep the block for an inline extension","Split into two separate hook calls if both extensions are genuinely needed"],"exampleFix":"// before\nAutoextend.hook('User', 'UserExtensions', :create) { def extra; end }\n// after\nAutoextend.hook('User', 'UserExtensions', :create)","handlingStrategy":"validation","validationCode":"raise 'pass module_name XOR block' if mod_name && block_given?","typeGuard":null,"tryCatchPattern":"begin\n  Autoextend.hook(const_name, mod_name, method, &blk)\nrescue ArgumentError => e\n  Rails.logger.error(\"ambiguous autoextend hook: #{e.message}\")\nend","preventionTips":["Pick one extension style per hook and stick to it","Lint initializer files for hook calls containing both forms","Split mixed registrations into separate hook calls"],"tags":["ruby","dsl","argument-error"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}