"method redefined" warning: unclear why it exists, unclear if I can fix it on my end - ruby

I added sorbet to a pet project of mine: https://github.com/Trevoke/SGFParser
When I run the tests, I get a lot of the following warning (here's a link to a travis-ci build):
/Users/trevoke/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/sorbet-runtime-0.4.4314/lib/types/private/methods/call_validation.rb:807:
warning: method redefined; discarding old add_error
/Users/trevoke/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/sorbet-runtime-0.4.4314/lib/types/private/methods/_methods.rb:127:
warning: previous definition of add_error was here
Where "add_error" is a method of mine -- the other warnings show different method names.
I'd like to know if this is something which belongs entirely on the sorbet side or whether I can do something to get rid of them.

There doesn't seem like you can do anything on your side right now. It might be related to Sorbet#1150: "sorbet-runtime causes many warnings with Ruby $VERBOSE mode".
There's an open PR (Sorbet#1266) that could help.

Related

Detecting Ruby typos in VIM

I write tests and I use guard but my issue is: I don't want to wait for guard to run my test case to figure out that I am using a variable that hasn't been 'declared' due to a typo.
The question is, is there a VIM plugin that can warn is such instances?
:w !ruby -c
returns syntax ok for
def foo
return far
end
It would be great if I could see a warning that, at least within my current file, far is neither a method, an argument or assigned in the scope I'm in.
Suggestions or pointers are greatly appreciated!
Not sure undeclared variable can be caught, but many other syntax errors can be caught using vim-rubocop.

(Ruby) Error: `set_encoding': can't convert String to Hash in sinatra file (base.rb, line 1760)

I'm trying to run an example app from github. their app runs fine. which means that my setup is wrong, but I don't know what it is. this is my first time trying ruby.
what I did:
1- downloaded the code from github
2- made a gemfile:
source "https://rubygems.org"
ruby "2.0.0"
gem "sinatra", "1.4.4"
gem "haml", "4.0.3"
gem "sass", "3.2.12"
3- ran bundle install
4- when I run my .rb file (on heroku or on my computer), I get this error everytime:
/Library/Ruby/Gems/2.0.0/gems/sinatra-1.4.4/lib/sinatra/base.rb:1760:in `set_encoding': can't convert String to Hash (String#to_hash gives Symbol) (TypeError)
from /Library/Ruby/Gems/2.0.0/gems/sinatra-1.4.4/lib/sinatra/base.rb:1760:in `block in detect_rack_handler'
from /Library/Ruby/Gems/2.0.0/gems/sinatra-1.4.4/lib/sinatra/base.rb:1758:in `each'
from /Library/Ruby/Gems/2.0.0/gems/sinatra-1.4.4/lib/sinatra/base.rb:1758:in `detect_rack_handler'
from /Library/Ruby/Gems/2.0.0/gems/sinatra-1.4.4/lib/sinatra/base.rb:1420:in `run!'
from /Library/Ruby/Gems/2.0.0/gems/sinatra-1.4.4/lib/sinatra/main.rb:25:in `block in <module:Sinatra>'
--> I should signal that the github repo I'm trying to run is old (hasn't been touched since 2010)
It seems that this is an error in the used gem "sinatra".
Try to change the gemfile like this (without giving explicit version number), so that the application installs the latest version of the gems.
source "https://rubygems.org"
ruby "2.0.0"
gem "sinatra"
gem "haml"
gem "sass"
Probably there is a newer version of the sinatra gem.
Ok. so it turns out it wasn't my setup. (I tried using gems and ruby versions from 2009 and it didn't make the error go away either.)
I narrowed it down by gradually commenting things out in the script (since ruby wouldn't give me a line in my own files, only in sinatra files, I thought at first it wasn't due to my code).
--> it was a single line of code that, now that I commented it out in my script, made the error disappear forever with seemingly no negative side effects. (see code below).
If someone can briefly comment on that method (is it some kind of sinatra framework callback, for error handling a call to a nonexistent method? I assume this since it's never called in my files!) and why it could cause the error described in the question, I will pick their answer, otherwise I will pick this (my) answer. (just write anything you know or can find about this method and I'll pick your answer, Thanks).
def method_missing(methId)
method_name=methId.id2name.intern
if #lists.respond_to? method_name
#lists.send(method_name).pick
else
# method_name # line that caused the error in the sinatra source files.
end
end
================================================
so here's my own quick research on method_missing ... trying to learn ruby a bit here:
some info about method_missing:
http://www.alfajango.com/blog/method_missing-a-rubyists-beautiful-mistress/#/when-to-use-method-missing
http://rubylearning.com/blog/2010/10/07/do-you-know-rubys-chainsaw-method/
second link is a great intro.
basically method_missing is, yes, a kind of error handler for calling nonexistent methods. it's a ruby language thing (it calls method_missing when it can't find the method). so it's not tied to a framework, just to ruby.
besides simple error handling, one common usage for it is to be able define actions according to the (non-existent) method name (make up actions based on the nonexistent method name!), for example in the case where you have a great number of methods that do very repetitive things and you can deduce/base their behavior on their name.
a way to limit your pool of "methods you're going to make up behavior for, on the spot" is to have an if with a regular expression match (or in our case a match in a predefined list of items). if it's not matched, then you can for example throw an exception yourself or just return to see what happens next in the calling code.
so here in our code:
if the method name doesnt exist, they check if it exists in a list and act accordingly (they return a list, picked among #lists).
but if it is not found in #lists … they return that very method name, a string, that we didnt have a match for.
...but now the question is: --> how is the calling code dealing with that return value? (obviously not well, it seems to expect a hash or an array, not a method name string) a safe way to deal with "not finding a match for your nonexistent method" is to call super, to resume normal execution of the calling code (according to first link).
so one question remains: was it a good idea to return the method name? would returning the method name ever work? or was it really wrong, and super (or nothing) should be put in its place?
… my temporary conclusion is that --> you shouldn't return a list sometimes and a string some other times. so it would be a plain mistake, that surprisingly never caused problems or was never found in the original repo...

What are the serious problems caused by undefining object_id and __send__ on classes?

If I undefine all instance methods on a class then I get the following warnings:
warning: undefining `object_id' may cause serious problems
warning: undefining `__send__' may cause serious problems
What are some examples of "serious problems" this may cause?
(In particular, I am also curious as to whether this has any implications for garbage collection?)
In short, these methods are used for meta purposes (such as error reporting) as well as for ordinary purposes, so they are more important than other methods.
When something goes wrong, Ruby gives back an error message and backtraces. By default, an error message displays the inspection of the offending object. Except for a few special classes such String and Numeric, an inspection displays the object id. In order to display the error messages correctly, having object_id defined is essential. If it were not defined, then the error displaying routine itself would raise an error, which would need to be displayed, causing an infinite loop that cannot be reported. Under such situation, you have no way to tell what is going wrong. This is serious.
Perhaps the same can be said for __send__. It is the method that underlies send for most classes, and is crucial in sending instructions to objects.

Suppress particular warning in Ruby

I've seen plenty of posts providing the -W0 flag as an answer to this issue, but I don't want to suppress all warnings, just warnings of a particular value.
I'm running a non-rails app (which uses ActiveRecord, notwithstanding) on Ruby 1.8.7. I want to keep all warnings except for the following DEPRECATION WARNING:
Object#id will be deprecated; use Object#object_id
If that's not possible, I'd like to jettison all deprecation warnings. Java, at least, lets you do this. How about Ruby?
Update: I've upvoted both answers but checked the one that later searchers will expect to find here.
If there's a specific section of code that produces the warnings, you could try mixing in the Kernel module from ActiveSupport and wrap it with a silence_warnings block (example pulled straight from the RDoc):
silence_warnings do
value = do_something_that_causes_warning # no warning voiced
end
noisy_call # warning voiced
Is it absolutely necessary to suppress it? It's not like you're compiling something and have to sift through a ton of warnings all at once...
Edit: If you use read_attribute(:id), then you should avoid the waring. Thanks Jeremy!
I'm not a Rails developer, but isn't there a method that allows you to say "I want the database field id, not the id method of the object"?

Can you ask ruby to treat warnings as errors?

Does ruby allow you to treat warnings as errors?
One reason I'd like to do this is to ensure that if heckle removing a line of code means that a warning occurs, I have the option of ensuring that the mutant get killed.
There is unfortunately no real way of doing this, at least not on most versions of Ruby out there (variations may exist), short of monitoring the program output and aborting it when a warning appears on standard error. Here's why:
Ruby defines Kernel.warn, which you can redefine to do whatever you wish (including exiting), and which you'd expect (hope) to be used consistently by Ruby to report warnings (including internal e.g. parsing warning), but
methods implemented natively (in C) inside Ruby will in turn directly invoke a native method called rb_warn from source/server.c, completely bypassing your redefinition of Kernel.warn (e.g. the "string literal in condition" warning, for example, issued when doing something like: do_something if 'string', is printed via the native rb_warn from source/parse.c)
to make things even worse, there is an additional, rb_warning native method, which can be used by Ruby to log warnings if -w or -v is specified.
So, if you need to take action solely on warnings generated by your application code's calling Kernel.warn then simply redefine Kernel.warn. Otherwise, you have exactly two options:
alter source/error.c to exit in rb_warn and rb_warning (and rb_warn_m?), and rebuild Ruby
monitor your program's standard error output for ': warning:', and abort it on match
You can finally do that by overriding Warning.warn like
module Warning
def warn(msg)
raise msg
end
end
This will turn the warning into an exception. This solution works at least since 2.4 branch.
You could also potentially use DTrace, and intercept the calls to rb_warn and rb_warning, though that's not going to produce exceptions you can rescue from somewhere. Rather, it'll just put them somewhere you can easily log them.

Resources