New Adhearsion Feature: Sexy Rails integration 3
This feature has been in trunk for a while so it’s time to bring it into the limelight.
Let’s say you’ve a really fancy Ruby on Rails web application with which you wish to integrate your new Adhearsion app. Though you may only need five or so of the thirty models that exist within the app, they’re inter-related somehow with has_many :through, belongs_to and a dozen other SQL fragments sprinkled about. That’s no good—looks like it’s all or nothing. Oh, and you’ve eight Rails plugins installed, of which five heavily modify ActiveRecord’s internals for your obscure purposes. That’s no good, either. Looks like it all of Rails or nothing.
You can now do this “all of Rails” integration extremely easily in Adhearsion. When you create a new Adhearsion app with trunk, you’ll see the following option in config/startup.rb:
config.enable_rails :path => “/path/to/your/rails/project”, :env => :developmentAnd voila! Just uncomment this line and point it to the appropriate path. Adhearsion will do the rest.
Still more features to blog about! Stay tuned…
New Adhearsion Feature: Dialplan Menus 5
Those who watch the Adhearsion trunk commits probably noticed a new feature I snuck in recently: the menu() dialplan command. Now that I’ve had a chance to actually use the feature myself, it’s time I cover it in more detail here.
For the record, I’m totally excited about it. I’ve wished for something like this for over a year and only recently did I discover a way to get around the one technical limitation to implement it.
The problem
The menu() command solves the problem of building enormous input-fetching state machines in Ruby without first-class message passing facilities or an external DSL. After completely scrapping the feature several times and starting over, I eventually settled on my design of a state machine using a second-class message passing pattern. I’ll be writing about this pattern soon here.
Meet menu()
For now, here’s an example of menu():
from_pstn {
menu 'welcome', 'for-spanish-press-8', 'main-ivr',
:timeout => 8.seconds, :tries => 3 do |link|
link.shipment_status 1
link.ordering 2
link.representative 4
link.spanish 8
link.employee 900..999
link.on_invalid { play 'invalid' }
link.on_premature_timeout do |str|
play 'sorry'
end
link.on_failure do
play 'goodbye'
hangup
end
end
}
shipment_status {
# Fetch a tracking number and pass it to a web service.
}
ordering {
# Enter another menu that lets them enter credit card
# information and place their order over the phone.
}
representative {
# Place the caller into a queue
}
spanish {
# Special options for the spanish menu.
}
employee {
dial "SIP/#{extension}" # Overly simplistic
}If you haven’t, take a minute to read the dialplan above before reading on.
The main detail to note is the declarations within the menu() command’s block. Each line seems to refer to a link object executing a seemingly arbitrary method with an argument that’s either a number or a Range of numbers. The link object collects these arbitrary method invocations and assembles a set of rules. The seemingly arbitrary method name is the name of the context to which the menu should jump in case its argument (the pattern) is found to be a match.
With these context names and patterns defined, the menu() command plays in sequence the sound files you supply as arguments, stopping abruptly if the user enters a digit. If no digits were pressed when the files finish playing, it waits :timeout seconds. If no digits are pressed after the timeout, it executes the on_premature_timeout hook you define (if any) and then tries again a maximum of :tries times. If digits are pressed that result in no possible match, it executes the on_invalid hook. When/if all tries are exhausted with no positive match, it executes the on_failure hook after the other hook (e.g. on_invalid, then on_failure).
When the menu() state machine runs through the defined rules, it must distinguish between exact and potential matches. It’s important to understand the differences between these and how they affect the overall outcome:
| exact matches | potential matches | result |
|---|---|---|
| 0 | 0 | Fail and start over |
| 1 | 0 | Match found! |
| 0 | 1 | Get another digit |
| 0 | >1 | Get another digit |
| >1 | 0 | Go with the first exact match |
| 1 | >0 | Get another digit. If timeout, use exact match |
| >1 | >0 | Get another digit. If timeout, use first exact match |
Database integration
To do database integration, I recommend programatically executing methods on the link object within the block. For example:
menu do |link|
for employee in Employee.find(:all)
link.internal employee.extension
end
endor this more efficient and Rubyish way
menu do |link|
link.internal *Employee.find(:all).map(&:extension)
endIf this second example seems like too much Ruby magic, let me explain — Employee.find(:all) effectively does a “SELECT * FROM employees” on the database with ActiveRecord, returning (what you’d think is) an Array. The map(&:extension) is fanciness that means “replace every instance in this Array with the result of calling extension on that object”. Now we have an Array of every extension in the database. The splat operator (*) before the argument changes the argument from being one argument (an Array) into a sequence of n arguments, where n is the number of items in the Array it’s “splatting”. Lastly, these arguments are passed to the internal method, the name of a context which will handle dialing this user if one of the supplied patterns matches.
Handling a successful pattern match
Which brings me to another important note. Let’s say that the user’s input successfully matched one of the patterns returned by that Employe.find... magic. When it jumps to the internal context, that context can access the variable entered through the extension variable. This was a tricky design decision that I think, overall, works great. It makes the menu() command feel much more first-class in the Adhearsion dialplan grammar and decouples the receiving context from the menu that caused the jump. After all, the context doesn’t necessary need to be the endpoint from a menu; it can be its own entry point, making menu() effectively a pipeline of re-creating the call.
I encourage you to give this command a try and let me know what you think! Feel free to post on the mailing list or here on my blog.
Enjoy, folks!
The Year of Adhearsion 6
I get dizzy when I think of the flash flood of memories 2007 has been. I remember what I was doing precisely one year ago as if it were yesterday:
Sitting in my cozy dormitory bedroom, the first signs of relief set in as the stretch lasting almost two months was coming to an end—I was tying up the loose ends of my first publicly released version of Adhearsion. The start of the stretch was marked by my irreverent albeit desperate sneaking into Astricon 2006, the big Asterisk conference held ironically just six miles away in downtown Dallas at which security was surprisingly lax. It was there that I first demoed an alpha of Adhearsion to respected players in the telecom industry. My demo’s reception motivated me to pursue Adhearsion further, potentially toward something big. Through connections established there, I was invited to the headquarters of Asterisk’s corporation Digium twice, wrote an article for Linux Journal magazine, and got my first notable Adhearsion speaking opportunity at Emerging Telephony 2007. That was the tipping point.
Since those days I’ve spoken at eleven more conferences and tech meetups, collected hundreds of business cards, written an Adhearsion chapter for O’Reilly’s Asterisk book, and visited three other countries and fifteen states on Adhearsion-related business. To afford the absurd amount of travel, I took up an interesting style of living I later labelled peer-to-peer living: I had no fixed residence and considered myself, basically, homeless. Throughout my travels I managed to develop a support network of individuals with couches to spare for a few days or a few weeks. Needless to say, this all came as a shock to this boy from Texas who had never been out of the South.
This fruitful year is now over, the name Adhearsion is more widely known and, as of last week, I live in a fantastic part of beautiful San Francisco. After twelve months of testing myself and countless days of personal reflection, I’ve confidently decided that Adhearsion is my career now.
Big ’08 holds a lot. In addition to continued development, I want to bring in sub-contractors to assist on increasingly substantial consulting projects and encourage others to start their own independent Adhearsion consulting practice. If you’re a Ruby developer either with VoIP experience or a genuine, keen desire to gain VoIP experience, talk to me. My email address is in the right column of this blog. If you’re a company needing a better phone system or a startup with some telephony component not yet developed, talk to me too and let’s see if using Adhearsion makes sense.
I’ll continue promoting Adhearsion in ways other than speaking at a dozen conferences. Think screencasts, video podcasts, writing, and a revamped website. Development will continue regardless of whether I have work. My first order of business is to get the version 0.8.0 gem out the door. For those that don’t want to wait, you can play with 0.8.0 in Adhearsion’s trunk.
Happy new year folks! Let’s make 2008 the year the telecom industry really changed.
The Lack of Emerging Telephony 4
The telephony industry sickens me. I make it a point to follow things closely. I sift through the nauseatingly boring Del.icio.us VoIP feeds, catching the occasional library I hadn’t seen before that mildly captures my interest. I hear that SuperBigComm has bought TinySmallVox every week or so. I subscribe to the feeds of the VoIP’s biggest bloggers (of which there are surprisingly few) and usually read their posts last, procrastinating the tedium. I don’t unsubscribe and keep the faith because I want to believe this industry is going somewhere.
But last night my feeds agreed with my doubts. Resounding through the VoIP blogosphere, O’Reilly announced they have cancelled their Emerging Telephony conference and blog. To help paint the picture, Emerging Telephony was widely considered to be one of the actually fun, innovative conferences every year in this space.
Therein lies the problem. Too little fun and innovation exists in this industry to make a full conference out of it.
Remember the last episode of Star Trek: The Next Generation where the omnipotent Q places all of humanity on trial for being a savage, inferior species? Q asserts that the years since the first time he placed humanity on trial has been squandered with virtually no progress toward enlightenment. I’m convinced Q was so pissed off because of this ridiculous blemish in our history. We are a savage, uncivilized race apparently.
This is a frustration I’ve had since I created Adhearsion. The framework’s name reflects my attempt to unify this godforsaken wilderness. I’m herding cats and fighting the good fight simultaneously.
But I’m not giving up yet.
There are many wonderful things brewing under the covers of the new version of Adhearsion. It’s a maverick, opinionated approach but it may just work. The effect could be truly disruptive:
- A significantly next-generation approach reaches hackers who can finally develop actual open-source VoIP applications.
- An open-source ecosystem forms.
- More people become professional VoIP developers.
- Additional global expertise increases the number of open-source VoIP applications.
- The ability to host the applications becomes predictable and inexpensive through standardization.
- Startups form around new applications.
- A few startups succeed and contribute back.
- Years of contributions improves software quality and lowers barrier to entry.
- Disruptively innovative companies catch big telecom companies with their pants down and chip away at their market share.
The fight will be a long and difficult one, though the next baby step is to get Adhearsion v0.8.0 out the door. Near the end of the this month I’ll outline the changes in the new version of Adhearsion which should see a release by RubyConf on November 4th, 2007!
Superators Add New Operators to Ruby 27
This one’s for the fellow DSL mavens. I’m releasing now a new library I’ve developed that adds new operators to Ruby. Install the superators gem and run the following code in irb:
require 'rubygems'
require 'superators'
class Array
superator "<---" do |operand|
self << operand.reverse
end
end
["jay"] <--- "spillihp"Dear demagogues of domain specificity! Yes, this actually works. Now, how about this cutie:
require 'rubygems'
require 'superators'
class String
superator "++" do |operand|
upcase + operand.upcase
end
superator "-~+~-" do |operand|
puts "Using pretty superators"
self + operand
end
end
p "Tangy" ++ "Erlangy"
p "Super" -~+~- "ators"Superators are a superset of Ruby operators. And they’re pretty super too.

To elaborate more, they work by exploiting the way Ruby parses binary and unary operators. For example, the code
foo ++- baris equivalent to
foo.+(bar.-@().+@())and the Superators library keeps track of the unary operators called on the operand in their appropriate order. A valid Superator’s format is simple: take (almost) any Ruby binary operator and tail on an indefinite number of unary operators after it.
These are the Ruby binary operators you can use: ** * / % + - << >> & | ^ <=> >= <= < > === == =~And here are the unary operators: - ~ +
The only operators you can’t use are the logical ones (e.g. &&, ||, !, and, or, not, etc.) Ruby offers no way of overloading these.
I’m releasing this into the wild to hopefully see what mischief it stirs. But take heed! Superators are second-class citizens still and are victims of vicious discrimination in certain circumstances. In the current implementation the second operand is extend()ed with a Ruby module (unobtrusively setting a flag for later inspection), therefore a Superator can only have a second operand capable of possessing its own eigenclass. Superators will not work with second operands such as true, false, nil, Symbols or Fixnums yet. I’m working on a branch that could fix this if my mad scientist lab experiments bear fruit (or a resentful monster whom I chase to the Arctic Circle after he destroys those I love). Stay tuned.
Despite this limitation, Superators can still be used effectively! Use it when you expect the second operand to be an Array, String, Hash, Range, Regexp, Class, or whatever.
I should note that I strongly frown upon any use of Superators outside of the DSL space. Don’t use it in your company’s Rails app controllers. Use it in your tenderly crafted Ruby DSLs where they make sense.
Enjoy, comrades.
Update: There seems to be some confusion that Superators are a C extension that modify Ruby’s internals. A valid Superator is actually just valid Ruby—something we’ve had at our disposal this whole time!
The Methodphitamine 23
What amazes me most about Ruby is the emergence of hidden, powerful subtleties that lie under its surface just waiting to be discovered. A few months ago I discovered this useless, albeit cute snippet of Ruby’s fringe English-like qualities and, despite tens of thousands of people using Ruby, it wasn’t until just last year that the Symbol#to_proc hack was discovered that happily changed the way we refine and iterate our collections.
Well, ladies and gentlemen, I think I’ve developed a way that trumps Symbol#to_proc. Observe a few examples:
(1..100).select &it % 2 == 0
File.read("/etc/passwd").split.sort_by &it.split(":")[2]
User.find(:all).map &its.contacts.map(&its.last_name.capitalize)I call it The Methodphitamine. That’s Method ph it amine, a drug for Ruby addicts to code faster. Unlike Symbol#to_proc...
- arguments can be given to the method
- it’s not limited to just one method. Tail on as many as you like.
- it’s more English-like with the intuitive use of it or its
- even a method with its own block can be given to it
Let’s take the last of the examples above and convert this into its equivalent pure-Ruby and Symbol#to_proc way.
First, the pure-Ruby way:
User.find(:all).map{|x| x.contacts.map{|y| y.last_name.capitalize }}And now with Symbol#to_proc:
User.find(:all).map{|x|x.contacts.map(&:last_name).map(&:capitalize)}And now with the Methodphitamine once more:
User.find(:all).map &its.contacts.map(&its.last_name.capitalize)Notice how even with Symbol#to_proc a block literal is still necessary because it simply can’t do nested arguments. The Methodphitamine fixes this by preserving all arguments and being more readable to boot.
So now, without further ado, here’s The Methodphitamine’s code, weighing in at just over 20 lines.
module Kernel
protected
def it() It.new end
alias its it
end
class It
undef_method(*(instance_methods - %w*__id__ __send__*))
def initialize
@methods = []
end
def method_missing(*args, &block)
@methods << [args, block] unless args == [:respond_to?, :to_proc]
self
end
def to_proc
lambda do |obj|
@methods.inject(obj) do |current,(args,block)|
current.send(*args, &block)
end
end
end
endSo how does The Methodphitamine work?
The it() and its() protected methods are added to Kernel so it can be called from anywhere in a Ruby script but not on any particular Object instance. They each simply return a new It instance.
The It class has all instance methods stripped from it (except the ones Ruby complains about) to ensure method_missing() catches everything. In the example [1,"2",3].map &its.class.name, the It object first receives the class() method with no arguments via method_missing(). This gets enqueued in the @methods Array and it returns itself to receive any more methods. It then receives the next method, namely name(), and enqueues that alongside the previous method. When no more methods exist, Ruby determines if the It instance has a to_proc() method by calling respond_to?(:to_proc) so this has to be ignored and self suffices as a Ruby true boolean.
Then the magic happens. Because map() takes a block (essentially a Proc argument), this can be substituted with a variable or method that returns a block as long as an ampersand prepends it to let the Ruby interpreter know to call to_proc() on it. The It#to_proc() method is invoked, building a custom, dynamic Proc. Because these enumerations yield a variable, the dynamic Proc is executed for each item in the collection and obj consequentially becomes a reference to the current item in the collection. We then run through the enqueued methods with inject(), passing along the return value of executing each method in the order received with arguments intact. When inject() is done, it simply returns the grand product which becomes the return value of the Proc itself. Simple, right? :)
I chose to define both it() and its() since methods in Ruby can semantically either mean “the result of this action” or the possessive “this attribute.” For example, it.to_s and it.sort_by are both conceptual actions and its.class.name and its.last are both conceptual attributes.
The idea of an it implied block argument comes from the Groovy guys. For example, this is valid Groovy:
[1,2,3,4].each { println it }From the Groovy documentation on closures, “A closure always has at least one argument, which will be available within the body of the closure via the implicit parameter it if no explicit parameters are defined. The developer never has to declare the it variable – like the this parameter within objects, it is implicitly available.”
It’s about time for Ruby be on the receiving end of language beauty cross-pollination among the current generation of scripting languages.
I released this code in the public domain on RubyForge as the methodphitamine gem. To use, simply do
- gem install methodphitamine
- require 'methodphitamine'
When I wrote the Methodphitamine’s RSpec specifications, I noticed that RSpec’s own it() method gets undefined within the scope of each assertion’s block, allowing The Methodphitamine to behave normally even in specs. Very cool, RSpec!
If you discover any issues or have any improvement suggestions, feel free to post on The Methodphitamine Google Group.
It’s now standard in Adhearsion v0.8.0 among many other metaprogramming goodies. :)
Adhearsion v0.8.0 and Beyond
It was about one year ago that the Adhearsion name came to be, along with an invigorating second wind to develop it after writing Rails apps for several months and seeing real Ruby development. The ease and sense I saw Ruby make in the web development scene was an enormous inspiration to build Adhearsion into what it is today and what it will soon become.
It's this near future that excites me the most. For the past few months I've been intensively working on a rewrite of the Adhearsion core and it's showing great promise. Since I've never formally announced my intentions, here is what the community can expect from Adhearsion v0.8.0:
- Sustained quality. An enormous problem with Adhearsion 0.7.x has been avoiding regression when changes are made. The codebase today is unfortunately very monolithic and, consequentially, very easy for a change in one area to affect the rest of the framework without my knowing until someone reports it on the mailing list. This time around I am working on 100% RSpec coverage of Adhearsion and using the development principles of Behavior Driven Development. The telecom world expects rock solid dependability and Adhearsion should never be a question mark.
- First-class community portal. Another big issue in the Adhearsion scene I'm noticing is a weak adhesion (pun intended) of the Adhearsion community. My vision long ago was to facilitate the exchanging of Adhearsion-related source code on the official Adhearsion website. The problem has been in finding time to develop this community portal. Thankfully an opportunity arose to work with Alex Pilafian of Sikanrong.com on the site. In just the one month we've been developing it we've made enormous headway. Imagine this: a community-maintained open-source call center application exists online at Adhearsion.com; the "ahn" command allows dead-simple ease of deployment with only "ahn install appname"; suddenly you receive a fully functional call center PBX with AJAX-enabled web frontend, PBX clustering support, Java integration (mentioned below), easily maintainable application code, and all of the other benefits of Adhearsion. Yes, it's pretty exciting, disruptive stuff. I'll write more about this as it nears completion.
- Steps toward PBX independence. In doing some consulting for Gaboogie, I've been steadily working on FreeSwitch bindings to Adhearsion for them which will ultimately become open-source and standard with Adhearsion. FreeSwitch is still pre-beta at the moment but does tackle scalability very well. Unlike Asterisk where most of the functionality is already written and must be abstracted, FreeSwitch simply opens APIs for the implementor to develop his own functionality. This means more work on my end but, ultimately, a more robust and modifiable set of VoIP applications.
- New Asterisk Manager Interface library. Adhearsion AMI features are presently based on the two-year old RAMI library which exposes an API to read and execute Asterisk events outside of live phone calls. The library definitely shows its age, being a very tangly mess of unintuitive code that I'd expect from the non-Prototype Javascript world but not from the Ruby '07 scene. Dave Troy and I sat down at the Asterisk Developers Conference in Atlanta a few months ago and pounded out an unprecedented new library that vastly improves Asterisk integration.
- JRuby compliance. At RailsConf 2007, Charles Nutter and Thomas Enebo demonstrated deploying Mephisto on Glassflish in front of our eyes during a three-hour tutorial session. In the lobby immediately after their presentation I was able to replicate their success by deploying a simple "hello world" Rails app. Now with JRuby v1.0.0 stable out in the wild with "complete" 1.8.5 compliance, Adhearsion can be deployed seamlessly with other Java technologies. With Microsoft's efforts in the IronRuby space, a Ruby interpreter written in .NET, Adhearsion's use of the Ruby platform will make integration with that microcosm native, too. Of course, provided Microsoft doesn't fork our language! (J#, anyone?)
- More on Micromenus. With both the advent of the iPhone and its need for a good SDK, I've been working on the new Micromenus namespace that will render special iPhone-specific interfaces. With this complete, database-driven Micromenus applications can be busted out in minutes, complete with Asterisk integration out of the box. I don't want to spill these beans quite yet so stay tuned. :)
There are a few other things I'll leave in as surprises for the 0.8.0 release but this list should whet your appetite.
Beyond Adhearsion v0.8.0 there are many things on the roadmap, some of which will be axed and some of which will remain. Perhaps the biggest feature in my mind for version 1.0.0 stable will be a real abstraction of the PBX, letting the implementor not worry about any of the inconsistencies of the underlying framework. Adhearsion v0.9.x will be the first step toward the PBX independence and, when sufficient and stable, the 1.0 release will be triggered.
In the meantime, I'd love for others' help in this exciting ramping up phase! Let me know if you've like to lend a hand!
Extended Adhearsion Excerpt from the New Asterisk Book 1
As alluded to in my last post, today O’Reilly’s Emerging Telephony blog published an extended excerpt I wrote about Adhearsion for the new Asterisk book. Content-wise it’s on par with my Linux Journal Magazine article, though quite a bit more current.
If you’ve not seen much of Adhearsion, this is a great starting resource! If you’ve friends or colleagues who you think may find Adhearsion useful, send along the URL!
Adhearsion in Asterisk The Future of Telephony 2nd Edition
Having many, many fond memories of thumping the O'Reilly Asterisk bible since I began Asterisk development in Houston, I never imagined I'd write a section for it!
I'm pleased to announce that the second edition of the book, scheduled to hit the shelves later this year, will have a section about installing and using Adhearsion. This will be an enormous booster to the community adoption of Adhearsion -- I can't think of any better publication to feature the framework!
O'Reilly's Emerging Telephony blog will also soon feature an "extended excerpt" from the book about Adhearsion. It is much longer than the section in the book, much more in-depth, and free! For newcomers, there is also the Linux Journal Magazine publication from last March.
Many thanks to O'Reilly for these fantastic opportunities!
Adhearsion Roadshow Tour Dates
Perhaps "roadshow" isn't the right term but I am doing quite a bit of Adhearsion and VoIP promotion. Below is the current list. As I land more, I'll expand it:
Past speaking events:
- Emerging Telephony, San Francisco, Feb 27th
- Gotham Ruby Conference, NYC, April 21st
- Boulder/Denver.rb, May 15th
- Asterisk Developers Conference, Atlanta, May 22nd
Upcoming speaking events:
- Cluecon, Chicago, June 26th
- PDX.rb, Portland, July 3rd
- Ruby Hoedown, Raleigh, Aug. 10th
- Lone Star Ruby Conference, Austin, Sept. 8th
- Astricon, Phoenix, Sept. 24th
Unconfirmed Events:
- FOSCON, Portland, July 26th
If you are a member of a Ruby brigade or Asterisk users group and would like me to present, shoot me an email. My contact info is available on the Adhearsion contact page.
Adhearsion Just Got Way Fast 1
Ahh, it’s such a good feeling when you know you just wrote a really awesome feature. Last Saturday, late at night as I was trying to force myself asleep, I had an epiphany that solved the last hurdle I had with implementing a caching system in Adhearsion. The next morning I sat down and busted out a nineteen line method that took me about twenty minutes to write but another ninety minutes to document!
This cache method now lets Adhearsion totally bypass interpreting the dial plan for incoming calls which have already been cached. Does your dial plan make heavy use of your database? Does it use a really “expensive” helper that’s very resource-intensive? Are you pushing hundreds of calls a minute? So what? You can cache now!
For those that want the nitty-gritty, real documentation, see Adhearsion’s RDocs at http://rdocs.adhearsion.com. Scroll down in the top-right pane until you find cache().
I feel if Rembrandt had written this method, its usage still wouldn’t have come out as beautiful.
cache :for => 1.hour do
play weather_report('Dallas, Texas')
end
... or, how about this hottie:
cache :per => extension do
user = User.find_by_extension extension
speak "Calling #{user.name}"
dial user, :for => 1.minute
end
... which will store different caches based on the extension the user dialed. Since many IVRs route depending solely on this variable, caching in this case is both smart and fast. The variable per which the caches are stored can be virtually anything.
For the Ruby hackers, here’s the cache method I implemented.
The epiphany I had was to use the return value of Ruby’s handy Kernel#caller method as a Hash key which uniquely identifies the FILE and LINE which invoked cache. Without this, I wouldn’t be able to distinguish between stored caches which occur in the same file or the same context. In the global cache variable ($cache_dir), this Hash of caller()s maps stack traces to another Hash which contains the constraints for the call—that is any use of the :per Hash key argument. This second nested Hash’s constraining keys map to an Array accessed as a queue of Strings which are simply rawr()ed to Asterisk. The time-to-live (specified with the :for Hash key argument) is stored as index 0 of the Array as a Time object. You can see this being stored with the “ttl.from_now” line and accessed with the “queue.first < Time.now” comparison.
For the bolder Adhearsion hackers, I’d like to call to arms anyone who’d be willing to really destroy Adhearsion with stress tests. There’s an open-source SIP stress tester developed by Hewlett Packard called SIPp with which you could pound your Adhearsion-managed Asterisk PBX.
This is the first of many substantial performance improvements coming. I’ve a few other tricks up my sleeves. :)
Adhearsion in Linux Journal Magazine 1
Woot! Linux Journal Magazine, the original magazine of the Linux community and a fantastic barometer for exciting new open-source technologies, has published an article I wrote about Adhearsion in their March 2007 issue. These are the guys that had DHH’s smug mug on the cover of their issue devoted almost entirely to Ruby a few months ago.
This issue’s concentration is VoIP, hence Adhearsion’s inclusion. Thus far it’s the best overview of Adhearsion for a newbie so I recommend to everyone reading this now a trip down to your closest Barnes & Nobles to pick up this copy. No really. Go get a copy. Stop reading my blog, grab your keys, and go.
I chose to send Linux Journal my article because I have an enormous respect for them. I’ve been a reader of their issues for many months and with every issue I find something great. Hopefully people can say the same with this issue referring to Adhearsion. :)
Jay’s got pics:
What is Adhearsion?
“Adhearsion! Adhearsion! Adhearsion!” has been my mind’s mantra for many months now. Though Adhearsion.com went live Christmas along with the first release, it’s never received due announcement on my blog. Well, here you go folks.
Adhearsion is new twist on collaboration technologies. Its name derives from its VoIP-oriented origins as “adhesion you can hear” because it understands the VoIP picture and ties many VoIP-related (or, rather, collaboration related) technologies together in a comprehensive solution. From Adhearsion.com, these technologies include:
- Writing call-processing instructions
- Trading VoIP functionality
- Integrating with on-phone XML-based microbrowsers
- Collaborating with technology beyond VoIP
- Database integration for DB-driven VoIP apps
- Sophisticated relationships with Asterisk’s internals
- Opening up your PBX to RPC distributed computing
...to name a few. The end result is an exciting albeit lightweight package that is simply fun to hack with and beautifully simple. I wake up each morning giddy to resume my programming on Adhearsion from the previous night because each day brings some new and exciting possibility. This passion too is now shared — more are joining the project and more are seeing this vision. It’s great how all this is falling in place.
So great in fact my company Codemecca LLC is now the Adhearsion company. It will be the official sponsor of Adhearsion’s development and proliferation while bringing Adhearsion to the small business and enterprise markets through training, consulting, support, and so forth.
Technically, Adhearsion is written in Ruby with a sweet helper architecture. These “helpers” or framework extensions can be written in Ruby or C (more languages coming) and plug right into your app to extend, for example, the dial plan instructions or to introduce instant messaging functionality over Jabber.
In the spirit of “adhearing” things together, functionality brought by helpers can be used for your PBX, by other helpers, or — and this is the key — over Remote Procedure Calls (RPC). Take for example credit card processing. A new company wants to provide a public number into which customers can call and place orders for particular items. Also, because we’re living in the 21st century, they want to have the same credit card processing logic available to their PHP/Rails/Django/J2EE/whatever web apps. Writing the credit card processing logic in Adhearsion makes the functionality available to the PBX, but also to any other program or service needing it within the company. And by the way, writing that actual logic and having it set up like this would require nearly no effort whatsoever.
Stay tuned on this blog for more updates on Adhearsion. I’m hitting a wall with my custom blogging software Gosling and will soon be switching over to Typo. This will make the blog a much nicer place to facilitate my ramblings. :)
Merry Christmas Indeed!
To those in the Ruby scene, the preferred weapon of choice for programming is unquestioned: the venerable TextMate. When I bought my shiny, new iMac a little over a month ago, I can shamelessly say it was greatly motivated by the thought I could actually use this sweet, sweet software. Too bad I spent all my money on the computer itself with none left to actually buy it! 
And so my trial period of TextMate ended. Suddenly, the sky always seemed overcast. Green lights would turn red because I approached. My motivation to get out of bed in the morning plummeted.
And then a miracle happened! A miraculous bug in the software! Some how, some way, TextMate happened to get opened and not tell me it was time to register. It actually stayed open and let me use it! Hallelujah! Suddenly flowers smelled better again.
Now this new iMac never shuts off. You won’t get away from me that easy, TextMate!
UPDATE: Hearing my plight here, the rockstars at Ayoka Systems bought me a TextMate license to help out Adhearsion development! Ayoka is the onshore alternative to offshore software development. Knowing them somewhat, I enormously enjoy my visits down to their office to discuss technology and where it’s going. If anyone stays on top of things, it’s Ayoka. Check out their website at http://ayokasystems.com.
Enjoy Creative Destruction! 1
Here’s a great Ruby snippet I’d like to share with you. Working on Adhearsion’s phone-based weather forecast feature, I needed to reorder an array containing the days of the week such that the current day was first and the other six days followed it.
For example, if the current day were Wednesday, then I’d need the array [‘wednesday’, ‘thursday’, ‘friday’, ‘saturday’, ‘sunday’, ‘monday’, ‘tuesday’]. With the days variable containing the days of the week (starting with Sunday), I managed to accomplish this rearranging with one beautiful line of Ruby:
days += days.slice! 0, Time.now.wday
The magic here is in the += operator combined with the destructive slicing. Calling days.slice! actually modifies the days variable directly, but returns what was sliced off. Because slice!()’s second argument is exclusive, the return value can be safely appended to the end.
Oh, the simple things in life!
Older posts: 1 2
