4 ms·
> (irb):5:in `<main>': undefined method `name=' for #<data Person name="John", dob=#<Date: 1990-01-01 ((2447893j,0s,0n),+0s,2299161j)>> (NoMethodError) > Did
by laurent123456 4y ago
> (irb):5:in `<main>': undefined method `name=' for #<data Person name="John", dob=#<Date: 1990-01-01 ((2447893j,0s,0n),+0s,2299161j)>> (NoMethodError)
> Did you mean? name
Is that the best they could do to express that `person.name` is readonly?
The "did you mean" part especially is really where they could add info that would make sense to a human, but clearly that didn't happen.
- TulliusCicero 4y agoProgramming error messages are almost always so terrible.
- eropple 4y agoSo I get your point, but to this reasonably-Ruby-familiar human, this is not surprising. `name=` is the name of the setter method that you'd need to have here if you were to set the field; it doesn't exist, so Ruby's telling you so. It's a pretty common idiom. It could be improved--not easily; a setter method does not necessarily have to map to a data type, and Ruby itself doesn't know what you mean here because the Data type is in the stdlib but doesn't appear to be a compiler special case--but this is a bit nitpicking, and I would perhaps gently push back on changing the error message because it's representing what you really do need to know in Ruby once you're past the level one "driving Rails" usage of Ruby. Getting an error message other than this one would obfuscate what's happening and leave me as a long-time Ruby user pretty confused.
- tenderlove 4y agoMaybe we could do something like reparse the line and check the arity? We know the reader doesn't take a parameter, but the user clearly provided one, so maybe we could eliminate suggestions that have the wrong arity.
- eropple 4y agoThat's a neat idea! I might limit it to 0-arity vs. N-arity suggestions, to not create odd behavior for other situations (assuming Data is, as I expect, just Ruby and doesn't have any compiler special-sauce to it). I guess it would then also provide a better message for `attr_reader` vs `attr_accessor` usage, too, right?
- djur 4y agoI submitted a pull request to did_you_mean for a simpler solution: only suggest methods ending with = if the user tried to call one, and vice versa.
- irishsultan 4y agoThat's not always the right behaviour either. `#set_table_name` was replaced by `#table_name=` in ActiveRecord, so (especially around the time this changed when you might have projects in older and newer versions) it would be a likely mistake to make. I'm reasonably certain this is not the only case where a setter existed without `=` as part of the name where later library updates changed it to one with `=` (or the other way around).
- djur 4y agoThat's a good point, but according to my tests DYM already won't suggest `table_name=` for `set_table_name`. The spellchecker is based on Jaro-Winkler and Levenshtein distances, not substring matches. An alternative would be just to not suggest "foo=" for "foo" and vice versa.
- maxfurman 4y agoData could override method_missing to throw a different error for method names ending in =
- eropple 4y agoDoes anything else in Ruby do so idiomatically? My point is that would be different, and as a rule, different is surprising and surprising is wrong.
- fknorangesite 4y agoDiscussed further down here: https://news.ycombinator.com/item?id=33793994 https://news.ycombinator.com/item?id=33793994 tldr You tried to call name= on an object that has no such method defined on it. So you get...NoMethodError. name is defined, however, so you got a "is this the typo you made?" message.
- randomdata 4y agoThey could have intercepted the message and handled it differently, but that would likely break someone else’s expectations about what should happen.
- kayodelycaon 4y agoIf you do ruby for any length of time, you’ll have run into assignment actually being a method call. object.attr = 1 is object.send(:attr=, 1) And yes, setters can take multiple arguments. They are just methods. Nothing special about them.
- yxhuvud 4y agoNot true, there is special things about them, like always returning their argument.
- byroot 4y agoYou are confusing setters with the assignment evaluation. Setters are just normal methods. ?> def you_are_wrong=(a) ?> a * 2 >> end => :you_are_wrong= >> send(:you_are_wrong=, 24) => 48 However yes, the `foo.bar = 24` expressions translates to `(foo.send(:bar=, 24); 24)`. The reason is so that `foo = bar.baz = 12` works as you expects, it's absolutely not some kind of cruft or black magic.