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.
Related
Exumerant Ctags does not work well with Ruby, you can see there are many hacks in the ruby.c code and basically it fails recognizing many cases. One of the most important is this bit:
class SomeModule::SomeClass
end
Ctags generates:
SomeModule someclass.rb /^class SomeModule::SomeClass$/;" c
which is wrong. The correct and expected entry is:
SomeClass someclass.rb /^class SomeModule::SomeClass$/;" c
This is very limiting. There are some patches for ctags available which does not work, e.g. https://github.com/xtao/overlay/blob/master/dev-util/ctags/files/ctags-5.5.4-ruby-classes.patch but looking on the ctags ruby codebase, this really needs complete rewrite.
So I have been playing with other option which is https://github.com/rdoc/rdoc-tags which works nicer, but it is slow. I mean really SLOW. Generating tags on my project is 2 seconds with ctags but one hour with this tool. Really.
I found one old project that was parsing Ruby on it's own and generating tags, but it was only for Ruby 1.8. It was slower than ctags, but not that bad.
So I am searching for some alternatives. Do you know about any other working ruby ctags generators which give you proper output and are fast?
Thanks!
Edit: I have found very nice project that works with Ruby 1.9+ and is accurate and fast. I recommend it:
https://github.com/tmm1/ripper-tags
Ripper-tags effort does solve everything described here. It is based on official Ruby parser which is also quite fast. https://github.com/tmm1/ripper-tags
gem install ripper-tags
cd your_project/
ripper-tags -R
It does also support Emacs as well.
Exuberant ctags out of the box doesn’t do a number of useful things:
It doesn’t deal with:
module A::B
It doesn’t tag (at least some of) the “operator” methods like ‘==’
It doesn’t support qualified tags, —type=+
It doesn’t output tags for constants or attributes.
Patch available, but it is only for version 5.5 and does not work anymore.
Other projects:
https://github.com/tmm1/ripper-tags (best option for Ruby 1.9+)
https://rubygems.org/gems/rdoc-tags (very slow but works with 1.8)
Source
Add following to your ~/.ctags
--regex-ruby=/(^|;)[ \t]*(class|module)[ \t]+([A-Z][[:alnum:]_]+(::[A-Z][[:alnum:]_]+)+)/\3/c,class,constant/
So you can:
deal with: module A::B
See more here: https://github.com/bltavares/dot-files/blob/master/ctags
A patch is available as of 2013-02
https://github.com/fishman/ctags (ctags patch for Ruby, including rspec)
the rspec tag generator will not properly recognize describe blocks that start with semicolor (:some-method), but other than that, it's great.
There is also https://github.com/eapache/starscope
It doesn't support the extended tag format (yet) but it does other things such as exporting cscope databases.
Below is a small screenshot from within RubyMine 3.1. I am just starting to learn Ruby. The code here is from the Presenter-First MVP C# code generator over at atomicobject.com.
I am using this project along with a book to learn Ruby. The documentation for puts shows that it expects at least one parameter. Yet this code appears "somewhat legal" for two reasons:
The code appears to work fine when I
step thru it via the debugger.
Searching online, and even here at SO, shows that puts w/o arguments creates a newline.
However, is it bad practice to do this (hence the RubyMine warning)? The code I am looking at is from 2006. I'm running it with Ruby 1.9.2 if that matters any.
This is perfectly fine, as puts provides 'default' value for the first parameter:
def puts(obj='', *arg)
As for RubyMine, it doesn't show any errors for me. May it happen that you define method puts somewhere else in your code? You can cmd+click on it, to get to the definition.
Anyway, if you're able to reproduce problem in a clean new project, you can freely submit a bug report to JetBrains.
No, it can be helpful to create the physical line break in your source as well as the output, and like you have seen already, puts is perfectly capable of accepting zero arguments.
Personally, if I'm creating a multi-line output I prefer to use here-doc syntax.
In the python world, there are a number of alternative python interpreters that add cool additional features. One particularly useful example is bpython, which adds dynamic syntax highlighting, automatically pulls documentation, and displays live autocomplete information. In the Ruby world, I have yet to uncover any projects which add to the basic IRB interpreter even a subset of these features. Am I just not looking hard enough, or is this just something the Ruby community is lacking?
Use Pry: https://github.com/pry/pry
Let's you:
start sessions at runtime
view method source code
view method documentation (not using RI so you dont have to pre-generate it)
pop in and out of different contexts
syntax highlighting
gist integration
view and replay history
open editors to edit method using edit-method obj.my_method syntax
A tonne more great and original features
What a coincidence. Rubyflow just yesterday announced the irbtools gem, which is a meta-gem containing lots of cool irb enhancement gems. It contains:
Colorized and output as comment by wirb and fancy_irb
Nice IRB prompt and IRB’s auto indention
Includes stdlib’s FileUtils: ls, cd, pwd, ln_s, rm, mkdir, touch, cat
Many debugging helpers: ap, q, o, c, y, Object#m, Object#d
ap – awesome_print
q – like p, but on one line
Object#m – ordered method list (takes integer parameter: level of nesting)
Object#d – puts the object, returns self (using tap)
“Magical” information constants: Info, OS, RubyVersion, RubyEngine
OS.windows?
RubyEngine.jruby?
RubyVersion.is.at_least? 1.9
Clipboard features: copy and paste
also available: copy_input and copy_output for session history
Call vim (or another supported editor) to edit a file, close it and it gets loaded into your current irb session, powered by interactive_editor
Another way of live loading into irb: sketches
Highlight a string with olorize('string') or a file with ray('path'), powered by coderay
Displays ActiveRecord database entries as tables with hirb
Restart irb with reset! or change the Ruby version with the use method and rvm!
Includes the current directory in the load path (was removed in 1.9.2 for security reasons, but is pretty annoying in IRB)
Shorter requiring like this: rq:mathn
And rerquiring with rrq
Try the included Object#ri helper, powered by ori!
Access to a lot of more commands with boson – call commands to get started
There are nice screenshots on the irbtools page. One nice thing about it is that each of the utilities can stand on its own, in case you just want to cherry-pick one or two features.
2013 Update
Since I wrote this, Pry has become a popular IRB replacement. It doesn't do as much as irbtools out of the box, but it extensible with plugin gems that add cool features. You can browse source code like it was a unix directory:
pry(main)> cd FileUtils
pry(FileUtils):1> show-method rm
From: /opt/ruby/lib/ruby/1.9.1/fileutils.rb # line 556:
Number of lines: 10
Owner: FileUtils
def rm(list, options = {})
fu_check_options options, OPT_TABLE['rm']
list = fu_list(list)
fu_output_message "rm#{options[:force] ? ' -f' : ''} #{list.join ' '}" if options[:verbose]
return if options[:noop]
list.each do |path|
remove_file path, options[:force]
end
end
pry(FileUtils):2>
You can also browse Ruby documentation, issue shell commands, and if you're a Rails user, you can use the pry-rails gem to get pry in your Rails console. There's also a way to hook it into Sinatra and use it with Heroku.
There's ample documentation--there are a bunch of screencasts including a Railscast. It's definitely worth looking into.
I've never heard of a (popular) alternative to IRB, but there certainly are several useful gems that make the IRB experience a lot nicer:
awesome_print pretty prints Ruby objects with indentation and coloring, very useful when trying to look at nested hashes or other complicated data structures.
looksee is pretty awesome too, it provides a method lp (lookup path) that shows you where a Ruby object gets its methods from (class, superclass etc).
Sketches connects your editor and IRB, so it's especially useful if you are the type who likes interactive development. Emacs with inf-ruby is also good for this.
Wirble is a whole set of IRB enhancements, like tab completion and syntax highlighting. There's also Utility Belt, but I don't personally use that, so can't comment on its features.
Edit
I forgot Hirb, which is very useful for e.g. showing the results of an ActiveRecord query in a Rails console.
There's http://github.com/alloy/dietrb.
JRuby ships with jirb_swing, which provides code completion.
There's not much in the area of alternatives to irb, but there are a couple of gems that add useful features to irb.
Most notably wirble, which, among other things, gives you colored output (not input though) and a history that goes beyond the current session.
Check out ripl, a modular irb alternative which is designed to be extendable. You may also get some answers from Is there something like bpython for Ruby?.
rib is a modular and light Ruby interactive shell.
It, like Pry, uses Ruby's parser so has consistent behavior with Ruby thus less bugs (e.g. https://stackoverflow.com/a/39271791/474597)
It is modular so one can easily extend it with more functionalities.
It is also still actively maintained as of 2016.
I made a pure Ruby console, inspired off Google Chrome's JavaScript console.
https://github.com/sancarn/RubyConsole
It's still mostly a WIP project as I keep finding bugs with the current algorithm, however I'm building it to be 1.9.3+ compatible.
This question already has answers here:
Encoding Ruby on Rails code?
(5 answers)
Closed 4 years ago.
Is there a ruby obfuscator or "compiler"?
There are a few options, like RubyScript2Exe or AllInOneRuby. However, all obfuscators of interpreted languages tend to have a serious flaw: they usually don't understand more sophisticated metaprogramming techniques.
That is, they can't necessarily tell that something like foo.send(:bar, ...) is an invocation on the bar method in a completely different library, or that eval("require %w{abc def ghi}") means to require three different libraries. These are trivial examples -- things get much more complex when you throw method_missing and its ilk into the mix.
When an obfuscator encounters this sort of code, it will dutifully compile the appropriate instructions, but it may not know to also include certain libraries or other code from elsewhere. That can cause serious issues, since the dynamically included or required will not be available at runtime in a statically linked executable.
Unfortunately, many gems and libraries use sophisticated metaprogramming techniques. You'll likely get into trouble here if you try to use obfuscation and expect your program to have the same behavior. Worse still, because there are so many levels of indirection, if a bug occurs in the obfuscated version, you may never know what exactly happened or how to reproduce it.
Depending on what you are trying to do, there is a Gem that will allow you to create a C extension from a Ruby script which can then be used as a require inside your Ruby app. Its called ruby2cext. It will obfuscate all of your code into C and the you can require the .so in a separate Ruby script and it will function like a normal Ruby script.
RubyScript2Exe - http://www.erikveen.dds.nl/rubyscript2exe/
Here's a perfect example of the problem: Classifier gem breaks Rails.
** Original question: **
One thing that concerns me as a security professional is that Ruby doesn't have a parallel of Java's package-privacy. That is, this isn't valid Ruby:
public module Foo
public module Bar
# factory method for new Bar implementations
def self.new(...)
SimpleBarImplementation.new(...)
end
def baz
raise NotImplementedError.new('Implementing Classes MUST redefine #baz')
end
end
private class SimpleBarImplementation
include Bar
def baz
...
end
end
end
It'd be really nice to be able to prevent monkey-patching of Foo::BarImpl. That way, people who rely on the library know that nobody has messed with it. Imagine if somebody changed the implementation of MD5 or SHA1 on you! I can call freeze on these classes, but I have to do it on a class-by-class basis, and other scripts might modify them before I finish securing my application if I'm not very careful about load order.
Java provides lots of other tools for defensive programming, many of which are not possible in Ruby. (See Josh Bloch's book for a good list.) Is this really a concern? Should I just stop complaining and use Ruby for lightweight things and not hope for "enterprise-ready" solutions?
(And no, core classes are not frozen by default in Ruby. See below:)
require 'md5'
# => true
MD5.frozen?
# => false
I don't think this is a concern.
Yes, the mythical "somebody" can replace the implementation of MD5 with something insecure. But in order to do that, the mythical somebody must actually be able to get his code into the Ruby process. And if he can do that, then he presumably could also inject his code into a Java process and e.g. rewrite the bytecode for the MD5 operation. Or just intercept the keypresses and not actually bother with fiddling with the cryptography code at all.
One of the typical concerns is: I'm writing this awesome library, which is supposed to be used like so:
require 'awesome'
# Do something awesome.
But what if someone uses it like so:
require 'evil_cracker_lib_from_russian_pr0n_site'
# Overrides crypto functions and sends all data to mafia
require 'awesome'
# Now everything is insecure because awesome lib uses
# cracker lib instead of builtin
And the simple solution is: don't do that! Educate your users that they shouldn't run untrusted code they downloaded from obscure sources in their security critical applications. And if they do, they probably deserve it.
To come back to your Java example: it's true that in Java you can make your crypto code private and final and what not. However, someone can still replace your crypto implementation! In fact, someone actually did: many open-source Java implementations use OpenSSL to implement their cryptographic routines. And, as you probably know, Debian shipped with a broken, insecure version of OpenSSL for years. So, all Java programs running on Debian for the past couple of years actually did run with insecure crypto!
Java provides lots of other tools for defensive programming
Initially I thought you were talking about normal defensive programming,
wherein the idea is to defend the program (or your subset of it, or your single function) from invalid data input.
That's a great thing, and I encourage everyone to go read that article.
However it seems you are actually talking about "defending your code from other programmers."
In my opinion, this is a completely pointless goal, as no matter what you do, a malicious programmer can always run your program under a debugger, or use dll injection or any number of other techniques.
If you are merely seeking to protect your code from incompetent co-workers, this is ridiculous. Educate your co-workers, or get better co-workers.
At any rate, if such things are of great concern to you, ruby is not the programming language for you. Monkeypatching is in there by design, and to disallow it goes against the whole point of the feature.
Check out Immutable by Garry Dolley.
You can prevent redefinition of individual methods.
I guess Ruby has that a feature - valued more over it being a security issue. Ducktyping too.
E.g. I can add my own methods to the Ruby String class rather than extending or wrapping it.
"Educate your co-workers, or get better co-workers" works great for a small software startup, and it works great for the big guns like Google and Amazon. It's ridiculous to think that every lowly developer contracted in for some small medical charts application in a doctor's office in a minor city.
I'm not saying we should build for the lowest common denominator, but we have to be realistic that there are lots of mediocre programmers out there who will pull in any library that gets the job done, paying no attention to security. How could they pay attention to security? Maybe the took an algorithms and data structures class. Maybe they took a compilers class. They almost certainly didn't take an encryption protocols class. They definitely haven't all read Schneier or any of the others out there who practically have to beg and plead with even very good programmers to consider security when building software.
I'm not worried about this:
require 'evil_cracker_lib_from_russian_pr0n_site'
require 'awesome'
I'm worried about awesome requiring foobar and fazbot, and foobar requiring has_gumption, and ... eventually two of these conflict in some obscure way that undoes an important security aspect.
One important security principle is "defense in depth" -- adding these extra layers of security help you from accidentally shooting yourself in the foot. They can't completely prevent it; nothing can. But they help.
If monkey patching is your concen, you can use the Immutable module (or one of similar function).
Immutable
You could take a look at Why the Lucky Stiff's "Sandbox"project, which you can use if you worry about potentially running unsafe code.
http://code.whytheluckystiff.net/sandbox/
An example (online TicTacToe):
http://www.elctech.com/blog/safely-exposing-your-app-to-a-ruby-sandbox
Raganwald has a recent post about this. In the end, he builds the following:
class Module
def anonymous_module(&block)
self.send :include, Module.new(&block)
end
end
class Acronym
anonymous_module do
fu = lambda { 'fu' }
bar = lambda { 'bar' }
define_method :fubar do
fu.call + bar.call
end
end
end
That exposes fubar as a public method on Acronyms, but keeps the internal guts (fu and bar) private and hides helper module from outside view.
If someone monkeypatched an object or a module, then you need to look at 2 cases: He added a new method. If he is the only one adding this meyhod (which is very likely), then no problems arise. If he is not the only one, you need to see if both methods do the same and tell the library developer about this severe problem.
If they change a method, you should start to research why the method was changed. Did they change it due to some edge case behaviour or did they actually fix a bug? especially in the latter case, the monkeypatch is a god thing, because it fixes a bug in many places.
Besides that, you are using a very dynamic language with the assumption that programmers use this freedom in a sane way. The only way to remove this assumption is not to use a dynamic language.