< Return to Blog

Let's Disqus!

Update: Interestingly, the first comment I've received via Disqus was from Tomash and he correctly pointed out while this was a nice 'exercise' in the use of concerns, as far as the model is concerned, this HTML-and-javascript monster has no place in there at all! Ah yes, pun intended as well :)

So, how do we go about this the correct way? How about a PORO presenter?

class PostPresenter < Struct.new(:component)
  def post
    component
  end

  def disqus_id
    "post-#{post.id}"
  end

  def disqus_thread
    if self.respond_to?(:disqus_id)
      return <<-CODE
        <div id="disqus_thread"></div>
        <script type="text/javascript">
            /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
            var disqus_shortname = 'mwdesilva'; // required: replace example with your forum shortname
            var disqus_identifier = "#{self.disqus_id}";
            /* var disqus_developer = 1; */

            /* * * DON'T EDIT BELOW THIS LINE * * */
            (function() {
                var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
                dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
                (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
            })();
        </script>
        <noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
        <a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>
      CODE
    end
  end

end

...and the beautiful part is that in my view it simply changes to <%= raw PostPresenter.new(@post).disqus_thread %>.

Do share your thoughts, oh, and Tomash, let me know what you think as well please!


I've just upgraded the comments system to use Disqus instead of my hand-baked comments system that used the Ancestry gem inspired from RailsCasts.

Much of the hard work in this simple change is tackled via a concern that I only need to include within my Post model

require 'active_support/concern'

module Disqusable
  extend ActiveSupport::Concern

  # NOTE Also need to implement disqus_id in the including class.

  def disqus_thread
    if self.respond_to?(:disqus_id)
      return <<-CODE
        <div id="disqus_thread"></div>
        <script type="text/javascript">
            /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
            var disqus_shortname = 'mwdesilva'; // required: replace example with your forum shortname
            var disqus_identifier = "#{self.disqus_id}";
            /* var disqus_developer = 1; */

            /* * * DON'T EDIT BELOW THIS LINE * * */
            (function() {
                var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
                dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
                (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
            })();
        </script>
        <noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
        <a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>
      CODE
    end
  end

end

Similar to to_param I'm also adding a method disqus_id to my Post model and this simply defines a unique id for each post for Disqus. In the view for posts#show I'm simply calling (and this is erb) <%= raw @post.disqus_thread %>.

A potential downside to this approach is that I'm escaping the javascript that I'm fetching from Disqus as 'raw' and this could potentially be a malicious script. I'm giving them the benefit of the doubt in this case of course.