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

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...

Related

Can't list source using debug in ruby 1.8 [duplicate]

With this minimal ruby code:
require 'debug'
puts
in a file called, e.g. script.rb
if I launch it like so: ruby -rdebug script.rb
and then press l on the debug prompt, I get the listing, as expected
if I instead run it normally as ruby script.rb
when pressing l I get:
(rdb:1) l
[-3, 6] in script.rb
No sourcefile available for script.rb
The error message seems misleading at best: the working directory hasn't changed, and the file is definitely still there!
I'm unable to find documentation on this behavior (I tried it on both jruby and mri, and the behavior is the same)
I know about 'debugger' and 'pry', but they serve a different use case:
I'm used to other scripting languages with a builtin debug module, that can let me put a statement anywhere in the code to drop me in a debug shell, inspect code, variables and such... the advantage of having it builtin it's that it is available everywhere, without having to set up an environment for it, or even when I'm on a machine that's not my own
I could obviously workaround this by always calling the interpreter with -rdebug and manually setting the breakpoint, but I find this more work than the alternative
After looking into the debug source code, I found a workaround and a fix:
the workaround can be:
trace on
next
trace off
list
this will let you get the listing without restarting the interpreter with -rdebug, with the disadvantage that you'll get some otherwise unwanted output from the tracing, and you'll be able to see it only after moving by one statement
for the fix: the problem is that the SCRIPT_LINES__ Hash lacks a value for the current file... apparently it's only set inside tracer.rb
I've changed line 161, and changed the Hash with a subclass that tracks where []= has been called from, and I wasn't able to dig up the actual code that does the work when stepping into a function that comes from a different file
Also: I haven't found a single person yet who actively uses this module (I asked both on #ruby, #jruby and #pry on freenode), and together with the fact that it uses a function that is now obsolete it leads me to be a bit pessimistic about the maintenance state of this module
nonetheless, I submitted a pull request for the fix (it's actually quite dumb and simple, but to do otherwise I'd need a deeper understanding of this module, and possibly to refactor some parts of it... but if this module isn't actively maintaned, I'm not sure that's a good thing to put effort on)
I suspect the Ruby interpreter doesn't have the ability to load the sourcefile without the components in the debug module. So, no -rdebug, no access to the sourcefile. And I agree it is a misleading error. "Debugging features not loaded" might be better.

Is there a way to check what's inside method's code in Ruby or even modify it?

I'm currently creating a my own plugin for Redmine. I found the following method in its core (not exact code, but the idea is preserved):
def method(foo, bar, array)
# Do some complex stuff with foo and bar
#array = array
#array.uniq!
#array = #array[0:3]
# Do some complex weird stuff with #array
end
I have to change this '3' to '6', because three elements in array is not enough for my plugin's purposes. I can change it manually and nothing crashes, but I don't want to patch Redmine's core. So, I'm writing a plugin which replaces this method with my own implementation, which does the same thing, but three is changed to six.
Here's the problem: if this file updates, outdated method will be used. Is there any way to check what's written inside method in runtime (for example, when server starts)?
By the way, is there any method to directly modify this constant without overriding the whole method?
If you are able to access the file, then you can use the pry gem to check the source code. Or without such gem, you can manually check the location of the method by doing puts method(:foo).source_location, and read that part.
The easiest for you to change the behaviour is to override the entire method.
No, there is no way to get a method's source code at runtime in Ruby. On some Ruby implementations there may be a way to get the source code which works some of the time, but that will be neither reliable nor portable. After all, there isn't even a guarantee that the source code will even be Ruby, since most implementations allow you to write methods in languages other than Ruby (e.g. C in YARV, Java in JRuby etc.)

Delayed require - Uninitialized constant error

I have a conditional bit of code that only can be loaded under certain conditions. It's platform specific code.
module MyGem
module MyPlatformSpecificThing
#stuff
end
end
My current attempt at lazily requiring this is performed like:
module MyGem
class AClass
def DoSomething
if thing_is_true
require 'my_platform_specific_thing.rb'
MyGem::MyPlatformSpecificThing.init
#more stuff
end
#even more stuff
end
end
This seemed like a solid enough plan, unfortunately it is not working. This code results in an error:
uninitialized constant MyGem::MyPlatformSpecificThing (NameError)
The stack trace indicates the source of the error is the call to init within the DoSomething method.
I am not entirely sure why Ruby is giving me fits here. What am I doing wrong, and how should I be doing this?
edit:
For specifics, I'm referring to the Platform class located here. The above should help narrow down the details of what I'm referring to, but in case anyone wanted/needed to see the specific classes/modules I'm work with.
You've almost got it right. Remember that the require method loads relative to the load path. As you're making a gem you've added the gem lib directory to the load path. Change the require to:
require 'my_gem/bcm2835'
Or for PiPiper:
require 'pi_piper/bcm2835'
This should load only when a driver hasn't been set.
Your pseudo-code is bit incomplete and confusing, but I think this may be the problem. If I am mistaken, seeing your real code as complete as necessary could help.
Check this response as a reference.
Your example shows:
MyGem::MyPlatformSpecificThing.init
However, that format should have Module::Class.method. Your sample shows Module::Module.method.
The error message
uninitialized constant
is very specific in that it is recognizing the call as a constant, not a class.
The error you've specified...
uninitialized constant MyGem::MyPlatformSpecificThing (NameError)
... will only occur if the inner module (PiPiper::Bcm2835) is never actually defined; if the problem was with the actual call to the module function (init), you'd get a different error.
I notice you've commented out the require on line 10, platform.rb:
#require 'bcm2835.rb'
... and required the file elsewhere. Let me guess, this is solving your problem, no?
Taking another look, in its original form the require statement should have failed, unless you've already added the pi_piper directory to $LOAD_PATH. Try changing the lazy require to this:
require './bcm2835.rb'
But note that this will not work either if you change the working directory (Dir.chdir) at any point prior to executing this line.

Calling another ruby file that is not a gem

I want to create a static ruby class with a library of function. I am on Vista with ruby 1.9.2
My class is this one :
class TestClass
def say_hello
puts "say hello"
end
end
in a TestClass.rb file (I assume I am correct as all ruby tutorials on classes are a complete mess putting everything in a single magic something (file?) as if IRB was the begining and the end of all thing).
My ruby main() (yes I come from Java) or program entry or wathever it is called in ruby is :
require 'TestClass.rb'
puts "start"
say_hello
But it fails with :
C:\ruby_path_with_all_my_classes>ruby classuser.rb
<internal:lib/rubygems/custom_require>:29:in `require': no such file to load --
TestClass.rb (LoadError)
from <internal:lib/rubygems/custom_require>:29:in `require'
from classuser.rb:1:in `<main>'
How does it work? Is it possible to call other files in Ruby or are you trapped in only one file containing all your classes?
Is the TestClass file in the same dir?
Make the TestClass.rb file lowercase and load it with
require './testclass'
no need for the .rb
I'd suggest putting any classes in a lib folder.
Then you require file as follows:
require './lib/testclass'
In 99% of all cases when a computer tells you that it couldn't find a thing, it is because the thing isn't there. So, the first thing you need to check is whether there actually is a file named TestClass.rb somewhere on your filesystem.
In 99% of the rest of the cases, the computer is looking in the wrong place. (Well, actually, the computer is usually looking in the right place, but the thing it is looking for is in the wrong place). require loads a file from the $LOAD_PATH, so you have to make sure that the directory that the file TestClass.rb is in actually is on the $LOAD_PATH.
Alternatively, if you do not want to require a file from the $LOAD_PATH but rather relative to the position of the file that is doing the requireing, then you need to use require_relative.
Note, however, that your code won't work anyway, since say_hello is in instance method of instances of the TestClass class, but you are calling it on the main object, which is an instance of Object, not TestClass.
Note also that standard naming conventions of Ruby files are snake_case, in particular, the snake_case version of the primary class/module of the file. So, in your case, the file should be named test_class.rb. Also, require and require_relative figure out the correct file extension for themselves, so you should leave off the .rb. And thirdly, standard Ruby coding style is two spaces for indentation, not four.
None of these will lead to your code not working, of course, since it is purely stylistic, but it may lead to people being unwilling to answer your questions, since it shows that you don't respect their community enough to learn even the most basic rules.
Try using
require './TestClass.rb'
Related: Ruby: require vs require_relative - best practice to workaround running in both Ruby <1.9.2 and >=1.9.2

Where can I find an actively developed lint tool for Ruby?

Most of the code I write is in Ruby, and every once in a while, I make some typo which only gets caught after a while. This is irritating when I have my scripts running long tasks, and return to find I had a typo.
Is there an actively developed lint tool for Ruby that could help me overcome this? Would it be possible to use it across a system that works with a lot of source files, some of them loaded dynamically?
Take this snippet as an example:
a = 20
b = 30
puts c
To win bounty, show me a tool that will detect the c variable as not created/undefined.
ruby -c myfile.rb will check for correct Ruby syntax.
Reek checks Ruby code for common code smells.
Roodi checks Ruby code for common object-oriented design issues.
Flog can warn you about unusually complex code.
[Plug] If your project is in a public Github repository, Caliper can run the latter three tools and others on your code every time you commit. (Disclaimer: I work on Caliper)
You could give Diamondback Ruby a try. It does a static typecheck of Ruby code, and will thus blame you for using an undefined variable.
While DRuby is an ongoing research project, it already works quite well for small, self-contained Ruby scripts. Currently, it is unable to analyze much of the Ruby standard library “out-of-the-box”. Currently they are working toward typing Ruby on Rails (see their most recent papers).
RubyMine (http://www.jetbrains.com/ruby) does the trick:
alt text http://img707.imageshack.us/img707/5688/31911448.png
None of the below will do all the analysis that RubyMine does.
NetBeans Ruby pack
Aptana RadRails
gVIM (with syntastic plugin by scrooloose)
Each of these has the capacity to identify syntax errors such as wrong number of parentheses, too many defs, ends, braces, etc. But none will identify invalid method calls the way RubyMine does.
Here's why: it's difficult.
Since Ruby is extremely dynamic (and methods like 'c' could easily be generated on the fly), any editor that tries to identify non-existent variables/methods would need to have a large part of the entire evironment loaded and multiple program flow paths constantly tested in order to get accurate 'validity' results. This is much more difficult than in Java where almost all programming is static (at least it was when I dropped that hat).
This ability to easily generate methods on the fly is one of the reasons the community holds testing to such high esteem. I really do reccomend you try testing as well.
Have a look at RuboCop. It is a Ruby code style checker based on the Ruby Style Guide. It's maintained pretty actively and supports all major Ruby implementations. It works well with Ruby 1.9 and 2.0 and has great Emacs integration.
Yes. Test::Unit
Ok, I know you already know this and that in some sense this is a non-helpful answer, but you do bring up the negative consequence of duck typing, that there kind of is (at this time) no way around just writing more tests than something like Java might need.
So, for the record, see Test::Unit in the Ruby Standard Library or one of the other test frameworks.
Having unit tests that you can run and rerun is the best way to catch errors, and you do need more of them (tests, not errors :-) in dynamic languages like Ruby...
nitpick might be what you're lookng for.
With this code:
class MyString < String
def awesome
self.gsub("e", "3").gsub("l", "1").uppercase
end
end
puts MyString.new("leet").awesome
... it outputs:
$ nitpick misspelling.rb
*** Nitpick had trouble loading "misspelling.rb":
NoMethodError undefined method `uppercase' for "133t":MyString
Nothing to report boss! He's clean!
Have not used it yet, but sounds promising (will update when I've tested this).
https://github.com/michaeledgar/laser
Static analysis and style linter for Ruby code.
Pelusa is nice, but is working in rubinius only. This shouln't be a proplem for people familar with RVM though.
avdi#lazarus:~$ irb
>> a = 20
=> 20
>> b = 30
=> 30
>> puts c
NameError: undefined local variable or method `c' for main:Object
from (irb):3
>>
There ya go, the tool is called "IRB". Do I get the bounty?
I'm only half joking. I wrote this second answer to hopefully drive home the point that in Ruby, if you want to know that something is defined or not, you have to run the code.

Resources