10
\$\begingroup\$

I have an initialize method for a class that looks like this:

def initialize(
  site:,
  name:,
  date_online: '-',
  date_offline: '-',
  date_modified: '-',
  date_tagged: '-',
  tags: []
)
  @site          = site
  @name          = name
  @date_online   = date_online
  @date_offline  = date_offline
  @date_modified = date_modified
  @date_tagged   = date_tagged
  @tags          = tags
end

However, RuboCop is telling me that I should:

Metrics/ParameterLists: Avoid parameter lists longer than 5 parameters. [7/5]

So, what is the best way to rectify this? It's an initializer, so all those parameters are necessary. Is the desired solution to use a hash?

def initialize(args)
  @site          = args[:site]
  @name          = args[:name]
  @date_online   = args[:date_online]   || '-'
  @date_offline  = args[:date_offline]  || '-'
  @date_modified = args[:date_modified] || '-'
  @date_tagged   = args[:date_tagged]   || '-'
  @tags          = args[:tags]          || []
end

Then how should I manually handle the fact that site and name are required? I could add some code after the assignments that will throw an error if the required fields aren't present:

raise ArgumentError unless @site && @name

That makes sense to me. But I assume the makers of RuboCop know what they're talking about, which leads me to suspect that there's a standard for this sort of thing.

\$\endgroup\$
2
  • \$\begingroup\$ I have rolled back your last edit. Please do not update the code in your question to incorporate feedback from answers, doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers. \$\endgroup\$
    – Heslacher
    Commented Jul 27, 2018 at 15:51
  • \$\begingroup\$ @Heslacher: Cool no problem, thanks for the info. \$\endgroup\$
    – Nossidge
    Commented Jul 27, 2018 at 16:12

1 Answer 1

10
\$\begingroup\$

An in-between solution for you might be:

def initialize(site:, name:, **options)
  @site          = site
  @name          = name
  @date_online   = options[:date_online]   || '-'
  @date_offline  = options[:date_offline]  || '-'
  @date_modified = options[:date_modified] || '-'
  @date_tagged   = options[:date_tagged]   || '-'
  @tags          = options[:tags]          || []
end

You would probably want to raise an error if an unexpected key was passed in as part of options.

\$\endgroup\$
3
  • \$\begingroup\$ That's great! I didn't realise you could split up parameters like that! This has helped me a lot, thank you. \$\endgroup\$
    – Nossidge
    Commented Jul 27, 2018 at 15:38
  • \$\begingroup\$ Thx, but now I have Cyclomatic complexity for initialize is too high. [7/6] lol! Hmm, maybe have a hash with default values, then loop through that default hash, and assign to options if key doesn't exist or something.. might not improve readability though :o \$\endgroup\$ Commented Dec 16, 2019 at 16:07
  • \$\begingroup\$ @EmileVrijdags personally I take a cyclomatic complexity warning with a pinch of salt. If the code is easily understood by future maintainers, then I'll disable it for that method. \$\endgroup\$ Commented Dec 17, 2019 at 10:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.