I'm a fairly accomplished developer, and know enough Ruby to shoot my foot from several polymorphic directions. Honestly, I have no interest in Rails and want to work with Ruby strictly as a Mac command line scripting alternative to php or Python. I'm stumped on where to even start with RubyMine. I'd like to use RubyMine for all of its features, and I use JetBrains' AppCode and IntelliJ so RubyMine seems like a no-brainer. But am I limited to writing .rb files and simply running them from the Terminal command line? I'd like to be able to debug code without waiting for an exception.
So, I guess what I'm asking for is a simple checklist to get to a command-line app. Which project type, how should I organize it, how to test, and how to run from inside RubyMine? Thanks in advance. (We were all newbies once...)
TLDR; Just code away, use RubyMine when you can, and you'll be fine. I include my own process here, but just as an example.
I use RubyMine without doing any rails and doing just what you ask. I write a lot of simple scripts, and large applications, both often usable from a command line.
I still organize my code into a 'project directory'. And point RM at that directory. Instead of just working entirely in a file, and trying to point RM at the file alone. This seems to be what IDE's prefer. This lets RM create its
.idea directory to hold all of its project related settings.
This may mean that some projects consist of nothing more than a directory (for the project) and a single file in that directory (the single script which is really the only content in that project).
You'll soon find you add more files to any project anyways. Both additional coding and various utilities which are part of the great benefit of ruby.
project directory pattern, also lets you version the code with popular VCS such as git, and even upload to social coding sites like github.
I don't bother with any sort of "project type". In fact I don't create projects from with RubyMine at all. I just create a directory, and then open that directory with RM (whether from the File Menu, or via the "mine" command line tool that RM installs).
project isn't the real name of the project, or the directory I create, I'm just using it as a generic name here. I would actually name the directory (and project) after the scripts or subject matter of the work they do.
NOTE: currently there is a bug in the
mine command in RM 5 where it won't open a second project window.
Obviously if this is a project that includes any command line scripts I'll put those in a
bin directory, just for organization purposes. I don't like to clutter the root project directory with all sorts of things. There are too many tools that require their settings files in the project root, so the fewer the better.
Like I said, various other utilities prefer their settings files in the project root, so you may find yourself using some of them.
project/Gemfile project/Rakefile project/project.gemspec project/README.md project/.rdoc_options ...
As soon as I have some automated testing for the scripts (which I admit isn't immediate) I put all test code under a
test directory, but I further categorize those according to the scope of the tests or how often I would run them during development. And I'll go so far as to add quck Rake tasks that are just aliases for the commands necessary to run the tests. So I dont' have to remember which test runner, or type the full paths each time.
project/test/ project/test/unit/ project/test/unit/some_component_test.rb project/test/integration/
Finally, as the project grows, and I add more scripts or want to reuse some of the code within external projects, I'll add a
lib directory, and use some standard practices for how to organize that.
And as the project continues to grow and get more complicated, more organization of the content is required, after a little refactoring. Note the
cmd directory to contain the actual top-level code of various workflows a particular script can go through.
project/lib/project/ project/lib/project/other_stuff.rb project/lib/project/cmd/ project/lib/project/cmd/one_command.rb project/lib/project/cmd/another_command.rb
Of course the original
project.rb 'requires' all of these lib files. Ruby loads pretty fast, so I don't bother too much with managing dependencies between the ruby files within the same project. Its really all about code readability.
There is nothing wrong with starting with a single script file and writing minimal boiler plate coding. And thats probably the best way to start.
#!/usr/bin/env ruby =begin this is a script blah which does whatever EXAMPLE $ script <options> <arguments =end def main(args) whatever end main(ARGV) exit(0)
But writing even better command line apps in ruby is pretty easy. There are popular gems which handle a lot of the infrastructure for you.
You can start with something as simple as OptionParser
Then as you build more code in your scripts you can graduate to a bit more infrastructure with a gem like Methadone
Finally, when you're writing full blown command line applications, with many "internal" commands like "git submodule init ", you can ascend to something much more heavy-weight like GLI
Unit testing is the pretty much the same, no matter what type of application your writing. You're not using real services or combining components, but just isolating the internal components and using them in a purely internal manner. So not much changes there for command line tools.
But when it comes to integration or full command-line testing of my scripts, I'm actually a big fan of
cucumber/aruba. I'm not big on TDD, I'm a bit too pragmatic for that. But for command line tools, the series of use cases is already laid out pretty plainly in the set of options available. Even for interactive commands this makes a series of
feature files conveniently double as documentation for the tool.
Feature: Create and manipulate notes in Evernote. Background: Given I am logged in as me And I have 0 notes Scenario: Show note Given that I have 1 note named "foo" with content "bar" When I run `rnote show note --title "foo"` Then the output should contain "bar" Scenario: Show note, from multiple notes Given that I have 2 notes named "foo" When I run `rnote show note --title "foo"` interactively And I type "1" Then the output should contain "foo"
As for installation and packaging for your scripts, so that they can be shared and reused by the rest of the world, look no further than the same 'gem' utility that you've already been using all along in ruby for depenencies.
gemspec you create when writing a new gem to share, can be told about your scripts and other command line utilities. It will then wrap them up with the rest of your code, install them in a good location, and even fix up the PATH so the user can find them when the time comes.
In fact this works so well, your gem can be composed of nothing but these
bin scripts. With no other re-usable code included.
cat-dog is a harmless little gem I whipped up as an example for something else. It contains no lib directory at all and no other ruby other than a single command line script.
I've run into a lot of Rails developers who aren't cognisant of what is Rails and what is ruby. i.e. what you're left with when you remove the Rails. Obviously the server and templating, databasing, MVC are all gone, as are a portion of convenience methods added to every-day objects.
The goods new is that you're still left with quite a lot. And if you find you miss something, its easy to add it back in with by including a gem or two. For instance, if you enjoy using an ORM like active-record it can be included back into your application, without rails, with little fuss.
Finally, using RubyMine features more heavily during development. Everything available when working with rails is available for command line applications.
You can run your commands from RM and use its debugger just the same as rails. Just like any IDE you can set up "run" profiles with the arguments you want to test the script on, and run or debug the script through the IDE. Personally, I never use a command-line debugger. If I need to fire up a debugger to troubleshoot some issue, then I'll launch the program in an IDE. The benefits of an IDE debugger with "heads-up" display of all the pertinent details, and visually following the script through execution, is just irreplaceable.