red888 red888 - 2 months ago 8
Ruby Question

What are attribute methods of a Chef LWRP and what can I pass them?

I have the following attribute in a chef resource:

attribute :attribName, kind_of: String, name_attribute: true, default: 'big string sldkjslkdflksdksdlkff'


I want to break this up so it looks nice, so I did this:

attribute [
:attribName,
kind_of: String,
name_attribute: true,
default: 'big string sldkjslkdflksdksdlkff'
]


But I get an error when converging:

NoMethodError
-------------
undefined method `to_sym' for #<Array:0x00000004a63b60>
Did you mean? to_s
to_yaml
to_set

Platform:
---------
x64-mingw32

Running handlers:
[2016-10-01T19:07:39-07:00] ERROR: Running exception handlers
Running handlers complete
[2016-10-01T19:07:39-07:00] ERROR: Exception handlers complete
Chef Client failed. 0 resources updated in 11 seconds
[2016-10-01T19:07:39-07:00] FATAL: Stacktrace dumped to C:/Users/ADMINI~1/AppData/Local/Temp/kitchen/cache/chef-stacktrace.out
[2016-10-01T19:07:39-07:00] FATAL: Please provide the contents of the stacktrace.out file if you file a bug report
[2016-10-01T19:07:39-07:00] FATAL: NoMethodError: undefined method `to_sym' for #<Array:0x00000004a63b60>
Did you mean? to_s
to_yaml
to_set


So I thought
attribute
s in resource files were just methods that accepted an array of arguments and passing [..args..] to it was the same thing. Why doesn't this work? I think I'm confused about what type of ruby object attributes are in this context and what their behavior is.

Answer

The attribute method is trying to symbolize the first argument, which is the name of the attribute. The second argument seems like a hash of options, so the method signature should look something like this: def attribute(name, options={}). You sent an Array as the first argument when you wrapped everything inside brackets.

Try reformatting it like this:

attribute :attribName,
  kind_of: String,
  name_attribute: true,
  default: 'big string sldkjslkdflksdksdlkff'

If you really don't that first argument in the same like, you can use splat(I don't like this at all):

attribute *[
  :attribName,
  {
    kind_of: String,
    name_attribute: true,
    default: 'big string sldkjslkdflksdksdlkff'
  }
]

That will turn the array elements into arguments.