A Quick Life Update

Unfortunately it's been a while since I posted something up here. I've been crazy busy, but haven't gotten around to noting it (or all the stuff I've been learning here). Like most excuses, it sounds hollow, I know, so you'll have to excuse me. So I thought I'd catch everyone up with a quick life update.

First off, Holly and I have moved to San Diego! We're in the process of selling our home in San Antonio, but our new place is gorgeous, and after the horrific drought-addled summer we had last year, I'm quite looking forward to San Diego's extremely mild one. Also, I've left the defense industry and have taken a position as an Associate Development Manager for ActiveNetwork.

I'm still plugging myself into the ruby community down here, as well as adjusting to the new company/position, but thus far, I'm truly enjoying all of it.

I'll have a post up soon about some of the side projects I've been doing in the interim.




Weaponizing the Cloud

My talk from AdhearsionConf 2011 was posted a month ago, and somehow it slipped my mind to post it here. It's about AT5001, a war dialer built in my spare time using cloud telephony.

Weaponizing the Cloud: Wardialing with Adhearsion -- AdhearsionConf 2011 from Adhearsion Foundation, Inc. on Vimeo.




Making and Recording Calls with Tropo

Tropo's cloud telephony services are absolutely awesome, and the fact that they make them available free to developers makes them an absolute haven for us to create weird telephony applications. I've recently been working on a wardialer using Tropo's cloud for a talk I'm giving at AdhearsionConf, and I thought I'd take a moment to explain how to work with the originate and recording functions when working with Tropo.

Initiating an outbound call with Tropo is actually a really simple process. After you create your Tropo application, you'll notice on your application page there's a voice outbound token assigned to your application. With that token in hand you can actually form a simple request to initiate the call.

res = Net::HTTP.postform(URI.parse('http://api.tropo.com/1.0/sessions'), "token" => @token, "destination" => number, "tropotag" => call_num)

In this case all I'm doing is using a simple POST to initiate a call via their API (acceptable parameters can be found here). The token field contains the voice token for your application, the destination field contains the number you wish to call (with country code), and in this case I'm also using the tropo_tag field to tag it with a unique identifier that I'll match on the adhearsion side when it comes time to actually control the call.

I've got my tropo application currently configured to use tropo-agitate to forward on control of the call to my adhearsion process (instructions for setting up tropo-agitate can be found here). So once the call is answered and control passes to my adhearsion process the first thing I want to do is begin to monitor the call (Warning: Recording calls may only be done with the consent of both parties in 12 states. In all other states, you only need the permission of one party, in this case yourself), so I'll send off off this little piece of code in my component:

num = JSON.parse(@call.tropoheaders)["tropotag"] res = @call.execute "startcallrecording", { 'uri' => "http://MYSERVER.com:3000/audio/#{num}", :method => "POST", :format => "audio/mp3" }.tojson

Here I'm pulling the tropo_tag out (the unique identifier I originally sent out), and then sending along the command to begin recording the call. Obviously since we don't have access to Tropo's servers, we have to have a way to get the audio afterwards, so you can either have Tropo FTP the file back to you, or provide it with an HTTP address to return the file to. In my case I felt like I'd have better control of my call's workflow if they sent it via an HTTP POST request (that way I can have rails throw it into the queue to be processed when it receives it). With that in mind I send it the address I want that POST request to go to in the uri field, along with the format (acceptable formats are audio/wav and audio/mp3).

Once your call is wrapped up, Tropo will transcribe that call into a temporary file and send it to the uri you specified beforehand. I haven't seen any way to force Tropo to name that file anything on it's return trip, or to include another tag, so this is where that unique id I assigned earlier came in handy. I was able to use it to form an id in the url that the audio is sent to. The file will come across as the 'filename' parameter in the post request, so to scoop it up, here's some simple file transcription code for your controller:

audio = params["filename"] name = "call#{params[:id]}.mp3" directory = "audiodata" path = File.join(directory, name) File.open(path, "wb") { |f| f.write(audio.read) }

This simply reads in the data in the POST and writes it out to a predetermined directory (in this case 'audio_data'). Keep in mind that this particular code does no checking on the incoming file to determine it's veracity, so if you're going to deploy something like this to production, you should verify that you're even waiting for a particular file, or risk people uploading malicious files to your server.

Anyways, that's the basic process I've used for placing and recording outgoing calls in my applications using Tropo. Hopefully this will help someone else in developing their own custom telephony applications.




Lessons in Programming from Fishing with my Father

My father is a skilled fisherman. That's really not even fully accurate, my father is a master fisherman. Some of my earliest memories with my father involve a rod and a reel, and even though I've never caught the fever for it that he did, I still enjoy bonding with him on a lake occasionally. As I spent this weekend doing just that, I found myself reflecting on my own passions as I watched the fire in his eyes as they scanned the lakes. While I never found that fever for fishing, I did find it for programming, and I found that many of the things that he was trying to impart to me about fishing had equal application in my own passion.

Have a Mentor, Be a Mentor. Out on the lake, my father is my mentor, and I'm not the only one. He seems to take a joy in teaching my sister, my cousins, his friends, whoever he can share his acquired knowledge with. What surprised me though was to hear him talk equally as passionately about the people who take him under their wings and teach him as well. Talking about the guides who he had worked with who taught him things about the lakes, guiding or fishing in general. As I reflected on this I realized that I've written some of my best code (and been the most fulfilled) when I had people to share my knowledge with, and others to learn from. Sharing your knowledge reinforces it in your mind. Your students will ask questions to force you to examine yourself and your understanding in ways that you never would have otherwise. And while self-study is always a virtue, having a mentor to guide you and teach you things that you may never have questioned otherwise is a GREAT thing. A mentor pushes you to be better in paths you may not have otherwise explored.

Collaborate with your Peers. My uncle Bobby is uncannily like my father. In many ways I almost feel that they are different flavors of the same dish, and yet like all Barnes men, they share a friendly rivalry. In the middle of a hard day of slow fishing (it was 105 degrees in Texas today), my father received a message from his brother. Uncle Bobby had caught a new kind of fish. Rather then get more frustrated with the slowness of our day, he smiled and studied the picture, then explained to me Uncle Bobby's accomplishment. Your peers are not your really rivals. Even if they may compete with you for promotions later, they are still not your rivals. If you want to be truly great, you have to work with them. Learn from them, and teach them too! In addition to the obvious benefits that most of community has realized by now (Pair Programming anyone?), the camaraderie of the relationship will help keep you dedicated and will provide you a form of emotional release for tense moments in your career for years to come.

Have Passion for your Craft. My father could talk for days about fishing. Continuously. While speaking of nothing else. After he visits, it's not unusual to find a dozen fishing show have appeared on my DVR, with a few more scheduled for regular recording. On the lake, he'll spend 15 minutes analyzing water temperature, lake level, windspeed, sonar data, depth graph, and gps of every spot we go to just to ensure that he's got it as close to perfect as he can. I'm half convinced he only learned to use the internet so that he could find a new group of fishermen to commiserate with. He loves his craft. Programming is no different. If anything, we should find this level of study easier. How many programming blogs do you think there are than fishing blogs on the internet? We pioneered this interactive medium, along with every other form of social networking, and yet, so many of the programmers I know only perform their craft to the minimum extent necessary. They enter the field because they feel it's a good place to make money and not have to do physical labor, and they never learn more than is absolutely necessary to do the job. That kind of passion is a joke to a fisherman. We should be able to do at least as much! Talk about programming to everyone, even to people who are not necessarily programmers! You'd be surprised how many of them would actually be astounded by the magic you do with your keyboard. Join a local users group and work with other programmers. Read about programming! Not just something for your next project at work, something just to expand you as a programmer! (Hint Start Here)

Expect the Best, Prepare for the Worst. No fisherman goes out on the lake expecting to catch nothing, but they're prepared for it. Worse yet, they'll be prepared for the motor to break, the trolling motor to fail, even for the hull itself to crack. It's really no different in your code. Code assertively, code confidently, especially in higher order languages like Ruby. Don't coax results from your methods, assert what they'll be and expect them to return what you tell them to. But don't forget to write the tests to ensure that will happen, and make sure that you have exception handling at the top of your stack to catch the weird exceptions that may bubble up!

It was a strange experience to reflect on code as I'm pulling fish from the water, but the longer I develop, and the deeper my passion for it grows, the more I find myself reflecting on the things that form really great code and really great coding experiences. Hopefully these lessons my father inadvertently taught me about programming will help improve the development experience for others too.




Monkey Patching Models for Fun and Profit

Recently I came across an issue where I had several tables in my rails application that needed options. I really didn't want to just add options fields to each of them for obvious reasons (the options might change, etc). In the code of the project, the options were represented as a hash unique to each individual user ie: { :display_creator => true, :position => 1.1 }. So in order to abstract some of this away I decided to go with a polymorphic table in ActiveRecord, which works like so:

class Option < ActiveRecord::Base   belongsto :owner, :polymorphic => true end class User < ActiveRecord::Base   hasmany :options, :as => :owner end class Operation < ActiveRecord::Base   has_many :options, :as => :owner end

Pretty basic stuff, now every time I reference the options method from an individual user I get back a series of option objects associated with my users. If I reference the options method from my Operation object, I'll get back only the options associated with that particular operation. Rails does this by looking for two columns you must create when you create your model id and type, where name is specified in the :as parameter to the hasmany relationship. In my case it was :as => :owner, which meant my columns were :ownerid and :owner_type.

With this solution in place I was off to the races, however I noticed that I was having to convert all these options back into a hash (they were essentially being stored as a key value pair of strings in the db). Naturally this is an action that would be great to throw into the models, however I began to realize that I'd have to repeat this option object to hash method in each model if I wanted to store it there. And that's certainly not very DRY. Remembering some work I had done on the govkit library, I decided to use an acts_as reference condensing all the attributes of a model that are associated with having options down and creating a method that could add them to any individual model with a single call. (Note the Option class is unchanged)

config/initializers/activerecordaddons.rb module ActiveRecordAddons   def hasoptions     classeval do       hasmany :rawoptions, :as => :owner, :classname => "Option"       def options         opts = {}         rawoptions.each |opt|           opts[opt.key.to_sym] = converter(opt.value)         end         opts       end     private       def converter val         Integer(val)         rescue ArgumentError           Float(val)         rescue ArgumentError           val       end     end   end end ActiveRecord::Base.extend ActiveRecordAddons

You'll note that now when you call options, it's actually referencing the options method which parses out the rawoptions from the database and returns a hash. If I were doing this from an independant library, I would have packaged this all up in a gem and included the gem in my gemfile, however I'm only using this from my one project, so I instead wrote the code out and added it to an activerecordaddons.rb file in the config/initializers directory. This ensured that the method was monkey patched onto the ActiveRecord::Base parent before the models were instansiated. So now ActiveRecord::Base and all it's children have this hasoptions method available, which will add in all the necessary code to make the models able to store their options hashes. So now my models look like so:

class User < ActiveRecord::Base   hasoptions end class Operation < ActiveRecord::Base   hasoptions end

Nice and DRY, and now any changes I need to make to how these models deal with their options can be done from one place.

Hopefully someone else finds this helpful. Enjoy!



 

That's great for reading options. But how do you save them back to options.

 

Hmmm... I'd probably define a options= method to iterate through the hash and update/add the options to the object, so that you can maintain the nice User.first.options = { :key => "value" } format. Though given that the = operator is universally understood to set the value of something I'd probably also add an add_options method to just append options without deleting any or resetting the full object.

Something like this: https://gist.github.com/1158636