System Tools to Debug Rails

Want to share this amazing link.  Was having an issue yesterday with a silent failure of a rails app- no error message, no server logs.  The browser just kept waiting for a response from the app.  I suspect the issue had something to do with a gem, and a bundle update fixed the issue.  But while I was looking for resources, I found this:  Debugging Rails with Operating System Tools.

Deconstructing the qbo_api gem

I recently built a CSV parser and Quickbooks importer using the qbo_api gem.  The documentation for the gem was not easy for me to understand, but I was able to hack the functionality I needed into the sample Sinatra app that’s provided with the gem.

I now want to create another Quickbooks import tool and use it with a rails app that I’ve already built.  The trouble is figuring out how to set up a rails app to use the qbo_api gem.  There are no explicit instructions on how to do this in the gem’s documentation.

After a few hours of hacking around last night with a buddy, I have a slightly better understanding of what’s going on under the hood with the gem.

Looking at the example app provided with the gem, you can see from the require statements that there are a few other gems required:  omniauth and omniauth-quickbooks.  Omniauth-quickbooks is a strategy for omniauth to connect to quickbooks, specifically.

Lines 19-21 of the example app tell Sinatra to use the omniauth-quickbooks strategy, with tokens that are stored in the .env file.  Lines 31 – 36 set up the index page of the app, where you connect to quickbooks:

qbo-apiQboApi::APP_CENTER_BASE is a url where some Quickbooks JavaScript is hosted:  “https://appcenter.intuit.com“.  This is used in a script src tag on index.erb which loads the Quickbooks javascript library for connecting the api.  oauth_data is a method that returns a hash with oauth tokens.

ouath_data

In the hash, consumer_key and consumer_secret are constants, pulled from the .env file when the app loads.  But the token, token_secret, and realm_id are pulled from the session.  When the index page is first loaded, these haven’t been saved to the session yet.

The assignment to the session happens in the last route, starting at line 64:

get authThis method is called from index.erb, which is mainly two javascripts, explained here.

I haven’t yet figured out what env[“omniauth.auth”][:credentials] are, but I assume it is created by the omniauth gem and holds the tokens returned from Quickbooks when you connect.

Optimize Conditionals with a Branch Table

I learned a little trick today, courtesy of this answer on quora.

Basically, rather than using a bunch of if statements, you can use an array for each option.  For example, here’s some code I created to benchmark multiple if statements vs. a switch vs. a branch table:

testing branch tables
I tried a few different ways but the branch table is consistently fastest, with the case statement coming in second.

One thing about my benchmark tests is that the first two required an array lookup in the CHOICES constant, while the branch table doesn’t require this, so that could throw off the results.  So I tried a different test:

alternate benchmarkIt turns out that CHOICES lookup was a performance hit for the first two tests, but  the branch table was still faster.

This seems obvious in hindsight.  I’m kind of surprised I never learned it before now.

Updating Multiple Fields with Ajax

A few months ago I was working out how to deal with multiple database entries at the same time.  We were using a CSV file to import clients.  Each client could have multiple account numbers.  For each account number, there would be an additional line with all the same info, except for the account number.

In other words, after uploading, there would be multiple clients with the same info but each with different account numbers.  I created another view to merge these clients into one client, but I needed a way to update each client without an http request for each one.

This app is a very simple mockup of how to update multiple objects in your database from a single view.  It uses jquery and ajax to send a request to the database each time you change a value in the select box.  Change the select box values, then click on the “All Users” link to see the changes.

In order to get the ajax to work with strong params, I had to use params.fetch in the update action in the controller

The code is on github here.

Water Monitoring Database

I built a Rails App that could be used by environmental groups to monitor water quality.  It uses the Google Maps API.  Users can create locations by entering GPS coordinates, or by clicking on a map.  Clicking a location on the map automatically enters the GPS coordinates into the form.  It also has different custom map icons depending on the type of location.

googlemaps

This project took about 8 hours all told.  It uses Devise for authentication and Bootstrap for the layout.  Feel free to check out the public version on heroku.  You will need to create an account in order to add locations.

Using JavaScript in Rails

I’ve been busy the past few months with a contracting gig, so my blogging has suffered. I’ve learned a lot, especially about using JavaScript and Ajax in a rails app. I’m just going to leave this link here for now:  Rails with no JS Framework.

I’m currently seeing no point in using a JavaScript framework on top of a Rails app, with all the functionality that’s built into Rails.  Of course my opinion on that might change over time.

Why Would You Need a Linked List in Ruby?

I am learning more about linked lists, and one question that kept coming up for me is, what would you use a linked list for in Ruby or Rails programming?

This resource says that you use linked lists to avoid problems and complexity with memory allocation in C.

Basically, to create an array in C, you have to allocate memory, and you have to have some idea of how big the array will be if you want to do that. If the array gets much bigger than the original size, you will have to reallocate memory for the new elements.

Using a linked list is much simpler, because each element or node only needs memory for its content, and a pointer to the next node. Each time you add to the list, you are only adding memory for a new node. And you can add any datatype, of any size, at any node (although I’m not sure this is an issue for Ruby arrays).

But Ruby does all this for us, right?

This excellent article on sitepoint explains that yes, Ruby does this for us, and it does a pretty good job. But you still might want to use a linked list in special cases.  Allocating new memory to add more elements to an array still takes time. So if you have an array with thousands of elements, you might want to look at using a linked list for optimization if you will be adding to it.

But in most cases, it’s fine to add elements to an array, and Ruby will only resize the array if needed.  (It is faster, for larger arrays, to use push or pop instead of shift or unshift.)

Linked lists are also useful immutable data structures for functional programming, if you’re into that sort of thing.

And finally, searching an array and searching a linked list are both O(n) (aka linear) complexity.  You have to search through every element to find a specific element.  If you need a faster lookup time, you’ll need a hash table.

Atom Text Snippets

Text editors are powerful tools to increase your efficiency.  I’ve finally gotten around to learning about customizing Atom’s text snippets, and I have a few tips to share here.

In all the time I’ve been learning to code, I have tried to avoid optimizing my text editor or even learning too much about its functionality.  I believe in muscle memory.  Typing code, over and over, helps me to internalize the syntax and structure of a programming language.  This is not entirely scientific on my part, but I come from a background of first learning to play guitar, and then practicing martial arts for many years.  Both of these disciplines require hours of repetition, day after day.

When I started learning to code, I found that Zed Shaw’s Learn Ruby the Hard Way gave me the most bang for my buck (yes, I know it’s free) because he requires you to type out the code, and then reread it, instead of just reading about the concepts.

But at some point, learning becomes doing, and now I find myself getting paid to reskin an app.  This requires entering the same code in multiple places across many files.  Providing value to my client requires speed.

Ag is a useful tool for finding the code I want to change (if you aren’t using it, stop reading this and start reading this).  But knowing is only half the battle.  I also have to go into each file, delete the old code, and type in the new.

Snippets allow you to type a short abbreviation, and expand that to whatever you want.  As an example, I have the following code in my snippets.cson file:

example-snippet

This allows me to open a new file, save it as an html file, and then type ‘html5sk’ and hit enter.  An tabbed-in html page appears in a puff of smoke!

The atom/snippets page really has all the information you’ll need to get things set up, and there are several tutorials out there as well.  But setup can be a little finicky.  One of the most useful bits of information is figuring out what context your snippets need – especially with Rails.  I struggled with this for a while, because ‘.text.html’ seems to work in some cases but not others, ‘.text.erb’ works in a different set of cases, and so on.

The easy way to determine this is to open a file that you want to use a snippet in.  Then hit ctrl-shift-p.  A box will open up at the top.  Type “Editor: Log” and you’ll see “Editor: Log Cursor Scope”.  Click on that or hit enter if it’s highlighted, and you’ll see the scope for that file.

Also, don’t forget to put a dot before the scope in your cson file, eg ‘.text.html.ruby’.

With a little experimentation you should be well on your way!

Installing Linux Mint on VirtualBox, on a Windows 10 Laptop

So last month my trusty old Windows 7 laptop (which I grabbed at a great price right when Windows 8 was getting pushed out) died, or at least the monitor did.  My life situation was a little hectic and I needed a laptop fast.  So I rushed out and bought a new one.

I’ve still been using the old laptop for rails development, dual booting Ubuntu, just plugged into a monitor. Meanwhile I’ve been trying to set up Virtual Box to run linux on the new laptop, with a good deal of trouble.

I was finally able to get Linux Mint running, after several hours spread out over a month.  It turns out that I had to follow these instructions to allow any virtual machine to run.  Once that was done, installation was relatively straightforward.

I’ve been struggling with VirtualBox ever since I started learning rails.  I’m excited to start playing around with it now!

How Can I Get Better Error Messages in Angular?

I was wondering how on earth people debug their Angular Apps when all the error messages in the console look like this:

Failed to instantiate module movieApp due to:
[$injector:nomod] http://errors.angularjs.org/1.4.8/$injector/nomod?p0=movi...
G/<@http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js:6:416
de/</</<@http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js:24:186
b@http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js:23:251
de/</<@http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js:23:1
g/<@http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js:38:117
n@http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js:7:331
g@http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js:37:488
eb@http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js:41:249
yc/c@http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js:19:463
yc@http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js:20:274
Zd@http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js:19:83
@http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js:294:192
b@http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js:175:62
If@http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js:35:365
Hf/d@http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js:35:314

But it turns out the error messages are actually readable if you use the non-minified version of Angular.

Thanks Stack Overflow!