Benson, Discourse, and WordPress

It sounds like an exciting new buddy movie . . . but it’s an attempt to better integrate elements of our Discourse install in WordPress using Benson (a neat plugin Mark made that lets you use Angular w/in WordPress). I decided to look into this after seeing this example using Twig. Ordinarily, I’d do something like this using Discourse’s RSS feeds and probably manipulating it with FacetWP. I’m opting to look at these other options for a few reasons. One, with WordPress expanding JSON I want a better idea of how all that works in comparison to RSS. Two, I don’t really like duplicating all this content through the syndication option if I can achieve the same effect in other ways. I’m not so worried about space (although I don’t like to waste it) but there are occasionally issues with updates and duplications using RSS the way we do. I wonder if JSON will straighten some of that out. Angular also opens up a realm of options as you get closer to writing code rather than relying on plugins. And finally, I want to knit Discourse more tightly to WordPress. That’ll matter because of the strong resistance to “another site?” responses.

What can you get out of Discourse via JSON?

Short answer- lots of stuff. Much like WordPress you can tack on RSS or JSON to most Discourse URLs and get a feed of activity. The Twig example referenced above also gets into some less standard ways to find JSON feeds. For this example I’ll just use the most recent activity feed – http://talk.rampages.us/c/5/l/latest.json That’s all fairly straightforward and was enough for me to get started playing around.

Benson & Angular

Mark came over and gave me a quick demo of how Benson worked. I had neglected to activate Advanced Custom Fields when I’d briefly looked at it before. We used it initially to play with some of the data from Flickr. That gave me enough to get started and I was confident that things would work. It’s always nice to get something basic working before wandering into other places where you’re less sure. Think of it as isolating variables. I’ve spent too many hours trying to fix the wrong thing when I haven’t followed this path.

The basic Benson set up is detailed below. You have a basic wrapper with the ng attributes on the first two lines and you set the source for your JSON in the custom fields element.
Benson basics

<div ng-app="benson">
<div ng-controller="MainController">
<div ng-repeat="talk in data.topic_list.topics">

<a href=http://talk.rampages.us/t/{{talk.slug}}/{{talk.id}}>{{talk.title}}</a> last commented on by
<img src=http://talk.rampages.us/user_avatar/talk.rampages.us/{{talk.last_poster_username}}/50/1.png />

</div>
</div>

Anyway, I set things up and figured I’d be good to go but instead I got nothing. I messed with different permutations for a bit and then looked at the console (in Chrome- right click “Inspect Element” and got to the Console tab. (If you look too closely at the screenshot below you’ll see it’s using an Instagram feed to generate the error. I cheated because resetting things to fail in Discourse takes too long.)
XMLHttpRequest Error

I got the following error.

No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://rampages.us’ is therefore not allowed access.

That gave me something concrete to chase down.

Discourse Sharing or Make the Error Go Away

I started Googling and thought that this advice on cross-origin resource sharing would get me what I needed. It did not. I tried it many different ways. Many, many different ways.

The slightly irritating thing about Discourse that made that super slow is that every time you change the app.yml file, you have to rebuild the whole install. That doesn’t take forever but it’s not fast either. Every different attempt would go as follows . . . 1

cd /var/discourse
nano containers/app.yml
>>>change attempts>>>save>>>exit
/var/discourse/launcher rebuild app

I found quite a bit on how to make this work with NGIX. We’re running on Linode and that led me down some other paths but got me no place I was happy. I was seriously considering setting up NGIX just to get to the solution. In the end, I sent an email to Tim Owens who thought this Discourse plugin might help. It allows you to iframe Discourse into other sites which is something I’ll likely do at some point. It didn’t quite get me where I wanted but it gave me the structure I needed to add a few pieces that solved the problem. It’s now up here although you’ll want to change rampages.us to your domain of choice.

Benson example screenshot

Back to Benson

Now that I had access to the data things were simple. You can see a working example here.

Tip: Make sure you have a JSON viewer installed. It’ll help quite a bit as you make sense of the structure.

Benson details - getting the right JSON element

<!-- First two lines are standard. -->
<div ng-app="benson">
<div ng-controller="MainController">
<!-- The "talk" portion below can be anything. Just pick a name. You'll use it in the patterns below. You also select the specific element of the JSON you want based on the structure of the data. data will start off all of them (I think) and then you're working through the hierarchy to the repeated element you want.  -->
<div ng-repeat="talk in data.topic_list.topics">

<!-- Now that we've gotten to the specific JSON element we want, it's a matter of building the URL from the pieces. I find a URL that goes where I want and cut/paste it below to help model what I'm building. It's mostly moving between this and the JSON to see what lives where. -->
<a href=http://talk.rampages.us/t/{{talk.slug}}/{{talk.id}}>{{talk.title}}</a> last commented on by

<!-- I thought I had this working but the URL fails sometimes and works other times. The difficulty is the avatar element isn't in the topics data. -->
<img src=http://talk.rampages.us/user_avatar/talk.rampages.us/{{talk.last_poster_username}}/50/{{talk.uploaded_avatar_id}}.png />

</div>
</div>

So nothing magical quite yet but a step towards something down the road and a chunk of troubleshooting done that I hope saves someone else a good deal of time.


1 Included for documentation