This is a simplified version of the first shot at the change looked:
def user_data ... if has_dns?(spec) data["dns"] = get_dns_servers(spec) end ... end def has_dns?(spec) spec.has_key?("dns") end def get_dns_servers(spec) spec["dns"]["nameservers"] end
This works, but it doesn't follow the tell don't ask principle, i.e. it first asks about the state and then takes action on it if it is in the expected state, instead of just asking for things to be done.
By refactoring it to use a method that takes a block instead, this is now shorter and easier to read.
def user_data ... with_dns(spec) do |servers| data["dns"] = servers end ... end def with_dns(spec) if spec.has_key?("dns") yield spec["dns"]["nameservers"] end end
The only downside is that it isn't clear what value(s) are yielded when you just see
with_dns(spec). If you name the variable(s) properly, you can remedy that for someone else who reads the code, but you still need know what is yielded. I do that by documenting the method using yard and the