Today I was working on autofixing rubocop offences and Lint/Void
gave me a nasty surprise. Supposedly in Ruby the return value of assignment methods like def field=(value)
will be special in that it's always the value passed, irrespective of what the last expression in the method body was. While true, this rule has an unusual exception - being called via super
. In that case the last expression is returned, confusoring everyone.
Try this code and see:
class Parent
def value=(v)
@value = v
:p # should never be returned, but using super in an inheriting class does get to it.
end
def value
@value
end
end
class Child < Parent
def value=(v)
parent_value = super
parent_explicit_value = super(v)
puts "Parent's value assignment returns #{parent_value}, whereas passing arg explicitly returns #{parent_explicit_value}"
@value = v*10
:c
end
end
Child.new.value = 1
Parent's value assignment returns p, whereas passing arg explicitly returns p
#=> 1
Not sure what the takeaway here is. The cop is useful because it warns about code that will have no effect, but I guess it has a false positive case in assignment methods.
Top comments (0)