Structure of Ruby Programs - ruby

I need some insight into the construction of Ruby programs. I'm trying to learn how to write Ruby (independent of Rails) so I'm translating some Perl scripts I wrote in a bioinformtatics project into Ruby code. Basically creating classes where useful and whatnot.
My issue is how do I execute it? The Perl scripts are just long blocks of commands, one after the other. What's appropriate in Ruby? Should I define my classes in their own .rb files and call those and their methods in a sepearate rb file that sort of uses them to execute my program?
What is normally done? Any examples would be greatly apreciated. I'd also appreciate any tips in general on how to go about learning this kind of thing.

Ruby does have what's usually called the top level execution environment, and so a long string of commands will execute immediately just like Perl. Or, you can define classes and modules and go all OOP on your problem if you want, or you can mix the approaches.
You will need at least one line at the top level or top level of a class to start everything off. So:
p :hello
or
class A
p :hello
end
or
class A
def run
p :hello
end
end
A.new.run
or, my favorite:
class A
def run
p :hello
end
self
end.new.run

I'd highly recommend looking at some of your other favorite gems to see how their code is structured (like on Github). That's how I found my start. Thinking of your project as a "gem", being released or not, is a good way to wrap your mind around the problem.

Related

How is called the feature that let's ruby execute code inside classes while interpreting the file

When I have the following ruby code
#file a.rb
class A
puts '2'
end
if I execute rb a.rb I get 2 printed onto the screen. This is because of the way ruby interprets the code, but, what is the name of this behavior?
The reason it prints something is because in the course of defining class A you asked it to. Anything inside a class block is treated as regular Ruby code, it's not special, so printing, exiting, making network connections, opening files, that all works as it would anywhere else.
This is in stark contrast to things like JavaScript and C++ where that is absolutely not allowed.
Ruby, being a dynamic programming language, has a lot more latitude. This permits things like defining methods based on input from files, or pretty much anything you can imagine.
The name of this behaviour is basically "evaluation", as in when Ruby evaluates that code, that is it parses and runs it.
This allows you to do things in Ruby not possible in other languages without employing macros, pre-processor tricks, or other techniques:
class A
if (Date.today.saturday? or Date.today.sunday?)
def party!
:on
end
end
end
Where that will only define the party! method when the code is run on a weekend.

Scripting in Ruby

I've developed a set of Ruby scripts. Each of them should be 'self-contained', so a user can run it on its own. But also I would like to use them to build other scripts, I mean for example to use its methods but also to run it as a whole, without doing ` script.rb`.
So far what I have is just a couple of scripts (separate files) where I have no classes, just a couple of methods. The processing of taking user input and running those methods is outside of any functions. I see that this model may be not right.
My question is, what should I do now to keep every script self contained but also to allow other scripts to use it? Should every script just contain a class with a main method that I would run object.main?
Or maybe my approach of writing a simple scripts, no classes is also good?
If I start a new script, should I always go the objective way?
When I write a one off script, I often wrap it in a class. You've pointed out some advantages of doing this including reuse and cleaner documentation.
I find that there are several levels of polish for scripts depending on how they are going to be used. If the script is run once and never used again, I may not wrap it in a class. If it's important (taking backups of production systems), it's probably worth putting it in full gem form and writing tests. Somewhere in the middle is the single purpose class. Generally this means you're taking the code that's not in a method and putting it in the class constructor.
This:
#!ruby
def amethod(i)
i+1
end
ARGF.each do |l|
if l.chomp.to_i > 0
puts amethod(l.chomp.to_i)
end
end
Becomes:
#!ruby
class OneAdder
def amethod(i)
i+1
end
def initialize
ARGF.each do |l|
if l.chomp.to_i > 0
puts amethod(l.chomp.to_i)
end
end
end
end
OneAdder.new

In Ruby, is there a way for classes to be accesible by package, or are all of the classes to be written in the same file of code?

I'm using Netbeans to program in Ruby and I can't seem to access other classes I write from the main class in Ruby until I place that code inside the main class itself. Is there a way to fix this so that it works like Java classes do?
If I understand you correctly, you are looking to import a class you wrote in a separate file into your current file. If this is what you are looking to do, take a look at require_relative
# cow.rb
class Cow
def moo
'Moooooooo'
end
end
# main.rb
require_relative 'cow.rb'
milford = Cow.new
puts milford.moo #=> 'Moooooooo'
Things to look out for is that require_relative searches for the file in the current location of the file you call it in. For instance:
# If cow.rb is in folder 'animals'
require_relative 'animals/cow.rb' #=> Fine
require_relative 'cow.rb' #=> LoadError
I would suggest finding some good tutorials on Ruby or finding a beginners book. Some of them are even available online like Programming Ruby The Pragmatic Programmer's Guide. This question covers some pretty basic Ruby concepts.
Also, I would not suggest using Netbeans since they cut out their support for Ruby. This is fine if you want to continue to use the old version of Netbeans but you will soon find it lacking support for newer Ruby versions.
For one thing, Ruby has no concept of "packages". There are files, and modules. To import all of the global variables, constants, modules, and classes from a file in the same directory, type:
require_relative "myfile.rb"
You can now use any classes, modules, constants, and global variables defined in myfile.rb in your code.

Rspec test case for array method

I am a fairly new to programming (3 months in), and am attempting to learn via TDD.
Obviously the point to TDD is write the test cases first, this particular piece I wasn't sure how to.
The code snippet is:
class PhraseFactory
def initialize
#sentence = ''
end
def make_sentences_from
for i in 0 ... self.length
#sentence += self[i] + ' '
end
end
How I was thinking to test it was using:
describe "When sent a message(<< is that proper terminology?) from an array of strings"
it "Builds a sentence"
my_word_array.should_have (here is where I am unclear)sent_a_message_to(make_sentences_from)
Thanks for any help.
i like TDD but i would not recommend anyone to use TDD to learn something new! it's always a good idea to use the REPL (irb) to experiment with code.
your example is full of WTFs for any ruby developer:
you are missing all the ENDs (looks kinda like python?!)
you are naming something Factory (are you a java guy?)
you use for instead of each
you are doing stuff in a class that should be a oneliner
you reinvent the wheel by rebuilding core functionality
besides that, i don't really understand your question and code...
what should the result of your code be? what is the input to your "factory"
$ irb
> %(you can just use join to build a sentence from an array of words).join
"you can just use join to build a sentence from an array of words"
Learning both a new language (Ruby) and technique (TDD) at once may be a bit too much. On the other hand, I find unit tests a great way to clarify code behavior, and as such a good learning tool. One suggestion here would be to look into something like the Ruby Koans: http://rubykoans.com/
I am not a Rubyist, so I can't comment on their quality, but I used the F# Koans, which were adapted from the Ruby ones, and were pretty good. This should both give you a good entry point into the language, as well as a familiarity with unit testing, which should serve you well once you start working on your own project and get into TDD.

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