user2367593
user2367593

Reputation: 181

Ruby ArgumentError: unknown keyword, but not sure why

I'm trying to make a simple Ruby on Rails plugin. When the redcarpetable function is called with a hash for render_opts, I get "ArgumentError: unknown keyword: render_opts." The code for the function:

def redcarpetable(*fields, renderer: :default, as: [nil], prefix: "rendered", render_opts: {})
    fields.each do |field|
      if fields.count > 1
        define_method "#{prefix}_#{field}" do
        Carpet::Rendering.render(read_attribute(field), renderer_opts: render_opts, rc_renderer: renderer).html_safe
        end # End defining the method dynamically.
      else
        if as[0]
          as.each do |method_name|
            define_method "#{method_name}" do
            Carpet::Rendering.render(read_attribute(field), render_opts: render_opts, rc_renderer: renderer).html_safe
            end # End defining the method dynamically.
          end
        else
          define_method "rendered_#{field}" do
          Carpet::Rendering.render(read_attribute(field), render_opts: render_opts, rc_renderer: renderer).html_safe
          end # End defining the method dynamically.
        end
      end
    end # End the fields loop.
  end # End the redcarpet method.

How the function is called:

redcarpetable :name, renderer: :simple_parser, as: [:cool_name, :rendered_name], render_opts: {:generate_toc_data: true}

In order to allow for a hash of render options, what must be done to the function declaration? The full code (not documented well or refactored yet) is here.

Upvotes: 4

Views: 14283

Answers (2)

max pleaner
max pleaner

Reputation: 26758

I think your issue might be caused by putting the *fields splat before the other arguments.

Though I'm not specifically sure what's causing your error, you can get an options hash using the following approach:

def redcarpetable(options={}, *fields)
  defaults = {
    foo: "bar",
    bar: "foo"
  }
  options= defaults.merge(options)
  puts options[:foo] # => "bar"
end

This way you can set defaults and override them when you call the method.

In your method body, you're going to have to reference the variables via the options hash, i.e. options[:foo] and not just foo.

When you call the method, unless your passing nothing to *fields you're going to have to include the braces in your options argument.

For example:

redcarpetable({foo: bar}, ["field1" "field2"])

And not:

redcarpetable(foo: bar, ["field1", "field2"])

Also, if you're passing any fields but not passing any options, you'll have to include empty braces.

For example:

redcarpetable({}, ["field1", "field2"])

Upvotes: 2

spickermann
spickermann

Reputation: 106782

You call the Carpet::Rendering like this:

Carpet::Rendering.render(read_attribute(field), 
  render_opts: render_opts, rc_renderer: renderer
).html_safe

But the option is actually called renderer_opts. Just change it to:

Carpet::Rendering.render(read_attribute(field), 
  renderer_opts: render_opts, rc_renderer: renderer
).html_safe

You might also want to change it in the methods' signature too.

Upvotes: 2

Related Questions