Drupal on Rails - Part 2
So it's Friday and the University is closed due to all the flooding that is happening. Time to work on my apps and see if I can complete the circle. In part one I had had Drupal working as a consumer of data from a Rails app. I had speculated on a way to get the data from Drupal to Rails but hadn't implemented anything yet. Today I set out to accomplish that part.
My first idea was basically to reverse the process I had setup for the Rails to Drupal, that is to have Drupal provide the full data as a JSON feed, and have Rails read it in. To do this in Drupal I needed to install one more module.
With Views Datasource I was able to build a View that output all of the data as JSON. So if you hit the site at a specific URL you would get the JSON.
Next I set to work in Ruby to read the JSON. I installed the HTTParty Gem and then this code did the trick:
url = 'http://192.168.1.109/ride-log/json'
response = HTTParty.get(url)
data = ActiveSupport::JSON.decode(response.body)
data['ridelog'].reverse.each do |node|
ride = node['ride']
I had all the data but needed to decide what to do with it. I needed to be able to determine which were new rides, or if there were any updates. At this point I had no way of knowing because I had lost the ID. So I went back to Drupal and added a field to store the Rails ID, and then ran an update on the data. This worked an now I had the ID of exiting rides, or if the ID was null it meant it was a new ride entered in Drupal.
While I was working on the above I decided maybe it would be easier to have Drupal POST updates to Rails, rather then have Rails go out and fetch the data, The app Controller was already setup to accept JSON posts for both new rides and updates, so all I would need was a module to do the POSTs.
So I switched my coding hat back to PHP mode and got to work on a new module. The first hurdle was finding out that the hook I was trying to use was no longer supported in Drupal 7. Once I found the right hooks for node updates and inserts in Drupal 7 I was off and running. The logic is simply to create a new object with all of the right fields, which I could read from the node object, pass that to json_encode, and then POST it to the appropriate Rails URL. There are a couple of important steps in putting together the POST request, mainly in getting the headers right.
Content-Type: application/json Accepts: application/json
I must say I was blown away the first time it worked! It was totally transparent to Drupal, other than a status message I posted from the module. You create a new node in Drupal and boom, there it is in the Rails app. Very cool, but what about updates?
The Rails docs, and the controller, say you do an update through a PUT. Come on, there is no such thing as an HTTP PUT, only GET and POST. It turns out the magic is in adding one more header.
X-Http-Method-Override: put
With that in place the rest of it was the same, and now I can do updates and inserts. I did not implement delete because I never delete my rides, but it would work the same way.
So now I have a Rails app that functions as a web service with Drupal as the front end. Data can flow in both directions. I can see many uses for something like this. Normal interaction like data entry, updates, and viewing can all happen in Drupal. Administrative functions that require more complex data manipulation can still be built on a Rails UI. Or maybe you set it up where external users only see the Drupal side, while internal users have access to the Rails app. The possibilities really are endless.
