{"record":{"id":"45e3eab793c76332","repo":"instructure/canvas-lms","slug":"cannot-pass-url-and-use-block","errorCode":null,"errorMessage":"Cannot pass url and use block","messagePattern":"Cannot pass url and use block","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"gems/canvas_crummy/lib/canvas_crummy/controller_methods.rb","lineNumber":40,"sourceCode":"    module ClassMethods\n      # Add a crumb to the crumbs array.\n      #\n      #   add_crumb(\"Home\", \"/\")\n      #   add_crumb(\"Business\") { |instance| instance.business_path }\n      #\n      # Works like a before_filter so +:only+ and +except+ both work.\n      def add_crumb(name, *args)\n        options = args.extract_options!\n        url = args.first\n        # I wanted this next line to look more like:\n        # html_options = options.pluck { |k,v| %w{class id}.include? k.to_s  }\n        # but couldn't figure out how\n        html_options = (klass = options.delete(:class)) ? { class: klass } : {}\n        if (id = options.delete(:id))\n          html_options[:id] = id\n        end\n        raise ArgumentError, \"Need more arguments\" unless name || block_given?\n        raise ArgumentError, \"Cannot pass url and use block\" if url && block_given?\n\n        before_action(options) do |instance|\n          url_value = url\n          url_value = yield instance if block_given?\n          url_value = instance.send url_value if url_value.is_a? Symbol\n          name_value = name\n          name_value = instance.instance_eval(&name_value) if name_value.is_a? Proc\n          name_value = instance.instance_variable_get(:\"@#{name_value}\") if name_value.is_a? Symbol\n          record = instance.instance_variable_get(:\"@#{name_value}\") unless url_value || block_given?\n          if record\n            name_value, url_value = record.to_s, instance.url_for(record)\n          end\n\n          # FIXME: url_value = instance.url_for(name_value) if name_value.respond_to?(\"to_param\") && url_value.nil?\n          # FIXME: Add ||= for the name_value, url_value above\n          instance.add_crumb(name_value, url_value, html_options)\n        end\n      end","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/gems/canvas_crummy/lib/canvas_crummy/controller_methods.rb#L22-L58","documentation":"CanvasCrumb's add_crumb builds a before_action that records a navigation crumb. It supports either an explicit url argument or a block that computes the url at request time, but not both, since the block would be discarded or conflict with the static url. Passing both is a programming mistake, so it raises ArgumentError at class/body evaluation time.","triggerScenarios":"Calling add_crumb('Name', '/some/path') (or with a full URL) together with a block: add_crumb('Name', url) { |c| c.polymorphic_path(...) }. Both the url positional/keyword argument and block_given? must be truthy simultaneously.","commonSituations":"Refactoring a crumb that used a static URL into a dynamic one and forgetting to remove the url argument; copy-pasting add_crumb calls and merging the two supported styles.","solutions":["Remove either the url argument or the block from the add_crumb call","If the URL is dynamic, drop the url argument and keep the block (possibly returning a Symbol to call on the instance)","If the URL is static, drop the block"],"exampleFix":"// before\nadd_crumb('Courses', courses_path) { |c| c.courses_path }\n// after\nadd_crumb('Courses', courses_path)\n# or dynamic:\nadd_crumb('Courses') { |c| c.courses_path }","handlingStrategy":"validation","validationCode":"raise ArgumentError, 'choose url or block, not both' if url && block_given?","typeGuard":"def valid_crumb_args?(name: nil, url: nil, block_given:) !block_given? || url.nil? end","tryCatchPattern":null,"preventionTips":["Pick one style per add_crumb call: static url OR block","Code-review refactors that convert static crumbs to dynamic","Lint for add_crumb calls with both a second positional arg and a block"],"tags":["ruby","argumenterror","api-misuse"],"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"}