Basic Networking | Writing About Healthcare and Technology

Casting off on Node.js with Sails.js

I cam across Sails.js a month or two ago and decided that, since I’m using AngularJS on the frontend, I might as well use Sails on the backend and keep the whole project in Javascript.  Makes sense, right?  It can’t be all that different writing Javascript (well, I prefer writing Coffeescript, but they’re interchangeable when it comes to this blog article) from the frontend, right?  Not.

I dove into the very nice screencast on Sails and was captivated – a framework that does a lot of the work for me!  This could be great.  I did check – briefly – for a leading MVC framework for Node.js (akin to Rails for Ruby, Django for Python, etc.), but did not find a true leading project that stood out.  Even though Sails was pre-v1, it seemed complete enough to get going.

I installed it, and got to hacking away creating a nice backend API for my project.  Creating controllers and models went well.  Policies seemed to work OK – I got hung up on exactly what was going on for quite some time, as I did not recognize that if a model exists, the same controller will be automatically created behind-the-scenes; however, the framework did differentiate between singular vs plural.  And coming from a recent Rails background, I was rather opinionated about how I wanted it structured.  So I ended up having to write all my own controllers, along with all my own routes.  Very quickly my hopes of a framework that would let me build quickly fell apart.

Coupled with these challenges was the fact that although I knew Javascript fairly well, I did not know it nearly as well as Ruby, and did not know Node at all.  So any time I wanted to do something like create packages, I was entering a whole new world I had absolutely no experience with.  So it turned from picking up a framework that followed well-known principles to picking up a framework that followed well-known principles while learning essentially a new language.

The asynchronous nature of Node really tripped me up.  I’m very much used to the blocking nature of other languages, and I find it easy to work with.  For example, if I’m creating an instance of a model, which has associated models, and I need to save the parent instance before saving the associated models, I end up in callback hell.  Why can’t it be as simple as making a method call, and then on the next line making the next method call?  I ended up with the async.js library doing a lot of work, which clearly took away from the benefits of using node.  This is not a gripe about Node – it’s a gripe about my skills (or lackthereof, in this case).

Finally, I came upon two realizations that led me switch back to Rails as the backend for my project.  First, I recognized that I need to support browsers that aren’t supported by Angular, and I really, really want to keep using Angular.  So I need another version of the site – which I might as well make pure HTML with no Javascript (this would allow me to also handle situations where users have Javascript turned off).  My mind instantly went to Rails’ ability to respond with multiple formats; I didn’t even look into how I would handle that with Sails.

The second factor was a conversation I had with a colleague about using tools for building new projects.  He brought up a few good points – first, using tools you know allows you to prototype much faster, as you’re not stuck learning something new in addition to building something that you don’t even know will be around in a few months.  Secondly, the experience you have from those tools can really only be a benefit going forward – yes, in my case, Ruby is “slow”, and Rails has a lot built into it, but it’s also got a humongous community that I can tap into about how to speed up Ruby, and how I can make Rails perform much faster if necessary.  I also know enough about Ruby and Rails to not be completely lost when researching, talking with others in the community, or needing to write extensions of my own or dive into the source code.

There you have it.  The challenges I faced with Node, Sails, combined with the benefits of using technologies I already know led me to abandon Sails for this project, and keep going with Rails.  But for those of you that are familiar with Node, and are looking for an actively-developed MVC framework, I strongly recommend you check out Sails.  It’s fantastic, and it’s got a great, growing community.  I just don’t have the time to learn nor to contribute (as much as I would love to); perhaps my next project will be in Sails!

Getting up and running with Ruby 2.0, Rails 4, Rspec, Guard and Zeus in Rubymine

I recently decided to switch to using Rails for a new project from Sails.js (I’ll detail the reasons in another post), and decided to take advantage of the latest-and-greatest. Ruby 2.0 is officially released and Rails 4 is on rc1, so I figured it’d be worth some small headaches to just jump on the bandwagon now, rather than using 3.x and attempting to port in all the nice things Rails 4 provides.

Having worked with Rails for the last year, and getting more and more comfortable with rspec as time goes on, I decided to start this project the “right way” and do TDD.  To that end, I decided to start the app by installing rspec, guard and zeus to make sure I have a fast test suite.  The following is the adventure these gems took me on as I attempted to get them all playing nice with Rails 4.

So to start, I installed the gems (and associated gems):

 

source 'https://rubygems.org'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 4.0.0.rc1'

gem 'pg', '~> 0.15'

group :development, :test do
  gem 'rspec-rails', '~> 2.13'
  gem 'guard-rspec', '~> 3.0'
end

group :test do
  gem 'capybara', '~> 2.1'
  gem 'rb-fsevent', '~> 0.9'
  gem 'growl', '~> 1.0'
  gem 'factory_girl_rails', '~> 4.2'
  gem 'simplecov', '~> 0.7'
  gem 'database_cleaner', '~> 0.9'
  gem 'faker', '~> 1.1'
  gem 'capybara-webkit', '~> 0.14'
  gem 'zeus'
  gem 'guard-zeus'
end

`bundle install` that and we’re off to the fun parts.  I started off following this post from pivotallabs: http://pivotallabs.com/running-tests-with-zeus/.  I’m going to recap it here so it’s all in one place:

Create a `script` directory, and in it create the following file:

This will be used to configure RSpec within Zeus to play nice with Rubymine (since Rubymine brings a lot of its own libraries and packages).

Next, we need to start zeus with the correct RUBYLIB environment variable, again to account for Rubymine:

To finish setting up RSpec within Rubymine, we need to update the default configuration to use the new runner we just created.

Go into your Run/Debug configurations, select “Defaults”, then “Rspec”.  Check the box that says “Use custom RSpec runner script:”, and in the text field that becomes editable enter the appropriate path to the runner script we created; e.g. “/path/to/my/project/script/rspec_runner.rb”.

Now that we have zeus and RSpec set up to play nicely within Rubymine, the last step is to set up Guard to automatically run our tests when we change a file.  A good SO answer provides some steps for that; I’ll reiterate them here as well: http://stackoverflow.com/questions/11996124/is-it-impossible-to-use-guard-with-rubymine.

To start, create a new run configuration by selecting “IRB Console”, and fill in the “IRB Script” line with the path to your rspec bin file.  If you’re using RVM on OS X, it’ll be something like: “/Users/pragone/.rvm/gems/ruby-2.0.0-p0@example-app/bin/guard”.  Set the working directory to the project’s root directory, and you’re off to the races!

The one downside is that I still haven’t found a nice way to *start* zeus within Rubymine; I still start it in the console (using our new script/start_zeus script: `ruby script/start_zeus`); after that, however, I just run the “Guard” configuration we created in the last step.

After all this, however, I still ran into problems.  In the end, it was a misconfiguration in my spec_helper.rb file that was causing problems.  Specifically, I had `require ‘rspec/autorun’` in there, and it should’ve been removed.  I’ve attached my spec_helper.rb and Guardfile for reference here:

 

Essentials