Some posts

Adding Disqus to My Jekyll Blog

Feb 25, 2016 • how-to • code, blog, javascript, comments

This is probably already on the internet, but I’ll just go over how to add Disqus comments to a Jekyll blog.

First step… Sign up for Disqus! You can sign in with Facebook, Twitter, or Google if you so desire, so that’s pretty cool.

Next thing to do is to Register your site with Disqus, so click on the settings cog, “Add Disqus To Site.” Start using Engage or whatever, go through the registration steps, and select Universal Code whenever you get to that step.

Settings Cog dropdown

Universal Code

Now for the fun part! Grab the code Disqus gives you and throw that in _includes/disqus-comments.html. Then just use a Liquid include tag.

[sapslaj@sapslaj-desktop sapslaj.github.io (master)]$ touch _includes/disqus-comments.html
[sapslaj@sapslaj-desktop sapslaj.github.io (master)]$ out _includes/disqus-comments.html
<div id="disqus_thread"></div>
<script>
(function() { // DON'T EDIT BELOW THIS LINE
var d = document, s = d.createElement('script');

s.src = '//sapslaj.disqus.com/embed.js';

s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript" rel="nofollow">comments powered by Disqus.</a></noscript>
[sapslaj@sapslaj-desktop sapslaj.github.io (master)]$ tail _layouts/post.html
    <div class="meta">
      {% include post-meta.html post=page %}
    </div>
  </header>
  <section>
    {{ content }}
  </section>
</artcle>

{% include disqus-comments.html %}

That’s pretty much it. Disqus makes it really easy to integrate their platform with your site, even without any sort of backend CMS. You can leave off the Disqus configuration code. It’s dead simple.

Testing Libraries Suck

Nov 16, 2015 • rants • ruby, testing, code, opinion

Ooh man. Ruby testing. Most projects I see today are using RSpec, while DHH is so offended by RSpec he uses Test::Unit. Ever since MiniTest replaced Test::Unit as the default testing library for Ruby, I can agree with him now. What happened? MiniTest::Spec happened!

For those who are unaware, MiniTest::Spec is a spec framework that intends to compete somewhat with RSpec. It’s main benefit is that it’s very simply implemented and doesn’t require the same kinds of complexity to achieve a similar result. That still doesn’t mean you should just carry on doing it the RSpec way.

What’s wrong with the RSpec way?

I’ll admit I haven’t read through The RSpec Book, but I have researched enough about testing to know that I believe the RSpec way is flawed.

The issue is that RSpec is trying way too hard to be plain English

Correct use of describe and context blocks as well as meaningful spec descriptions are fantastic and I completely agree with using them. But RSpec tried too hard to be plain English that it ultimately makes tests less maintainable.

Let’s take a look at some examples from Better Specs:

context 'when not valid' do
  it { is_expected.to respond_with 422 }
end

This example pretty much sums up what I’m saying. I should note that this code is verbatim but the real-world implementation would actually require a let or before to set up the context. Here’s how I would implement the same thing:

it 'responds with 422 when not valid' do
  assert_response(422)
end

It probably seems similar to what Better Specs is saying not to do, but their example is very biased:

it 'has 422 status code if an unexpected params will be added' do

By combining the context and spec descriptions into one block, it saves one level and makes maintaining that test easier. Secondly, instead of trying to process the DSL and wondering if you need to use is_expected, expect, or should, simply use an assert. asserts are very simple. If whatever you pass to them evaluates to true, they pass. Else, they fail. You can even use MiniTest::Spec’s matchers for a more DSL-ish without going too crazy:

it 'responds with 422 when not valid' do
  must_respond_with 422
end

You might go crazy saying there’s duplication or something there. But the thing is, you are providing a plain English description of what it should be doing, then testing that with plain, little magic, Ruby.

But wait, Test::Unit, you aren’t off the hook yet

The plain English thing goes both ways. Test::Unit doesn’t try hard enough. Having everything as plain Ruby classes and methods is fine and dandy until you get shit like this:

class DatabaseTasksCreateCurrentTest < Test::Unit::TestCase
  def test_creates_test_and_development_databases_when_env_was_not_specified
  ...

Yes, I pulled that from a very popular library using Test::Unit.

Really the only pro to this approach is that I find it easier to translate a programming language to a thought when using simple constructs and not some complicated DSL with so much magic it belongs at Hogwarts.

subject.should_receive(:post).with(subject::PATH, :body => hash_including(key => value)).and_return double(:parsed_response => {})

Bottom line

Using strings to define the test gives you freedom to use plain English, punctuation and all. It separates logic from metadata. It’s a good thing.

Using simple constructs like assertions and expectations make it easier to write as well as read tests.

In a future post, I’ll go through how I test.

How I Implemented lunr.js In My Blog

Nov 6, 2015 • how-to • code, blog, tutorial, javascript, search

As you probably are aware, this blog is hosted on GitHub pages and is powered by Jekyll. It provides an interesting challenge when dealing with dynamic content, such as search. Luckily, there is lunr.js, a client-side full text search engine. Sadly there isn’t much good documentation on how to implement it, so I’ll just go over it quickly.

First go grab the JS or Minified JS from the GitHub project or use a CDN and include it in your HTML page. While you’re at it, go ahead and make a search.js file

<script src="//cdnjs.cloudflare.com/ajax/libs/lunr.js/0.6.0/lunr.min.js" charset="utf-8"></script>
<script src="/js/search.js" charset="utf-8"></script>

Now we need to create the lunr.js index.

var index = lunr(function () {
  this.field('title', { boost: 10 });
  this.field('category', { boost: 5 });
  this.field('tags', { boost: 5 });
  this.field('body');
  this.ref('id');
});

Of course your setup will be different. As you can see, you can apply boosts to certain fields. Pay attention to the this.ref('id') bit.

Now since I’m deploying to GitHub Pages, I can’t just add in plugins. Therefore I have to do indexing client side, which is fine as long as your blog isn’t Coding Horror. Jekyll has a nifty Liquid filter called jsonify to turn anything into valid JSON. So let’s create a posts.json and utilize that as well as some looping.


---
layout: null
---

[
  {% for post in site.posts %}
    {
      "id": {{ post.id | jsonify }},
      "title": {{ post.title | jsonify }},
      "category": {{ post.category | jsonify}},
      "tags": {{ post.tags | jsonify }},
      "url": {{ post.url | jsonify }},
      "date": {{ post.date | jsonify }},
      "path": {{ post.path | jsonify }},
      "excerpt": {{ post.excerpt | strip_html | strip_newlines | jsonify }},
      "body": {{ post.content | strip_html | jsonify }},
      "content": {{ post.content | jsonify }}
    }{% unless forloop.last %},{% endunless %}
  {% endfor %}
]

Now we can simply get them with a jQuery.get call.

var posts = [];

$.get('/posts.json', function (data) {
  data.forEach(function (post, id) {
    posts.push(post);
    index.add(post);
  });
});

Remember how I said to pay attention to the this.ref('id') bit? Well, Jekyll’s idea of an id is something like /2008/12/14/my-post, and since posts are being stored in an array, it makes finding them a little tricky. Simple fix: use a post factory.

function post(id) {
  var return_post;
  posts.forEach(function (post, index) {
    if (post.id == id) {
      return_post = post;
      return;
    };
  });
  return return_post;
};

Now you have the basics for client-side search! Still need to work on the view part. For my site, I used Handlebars, but you can use whatever floats your boat.

<div class="search">
  <span class="fa fa-search icon"></span>
  <input type="search" class="search-query" data-bind="value: query" placeholder="Search" autocomplete="off">
</div>

<div class="search-results">
  <h1>Search Results</h1>
  <div class="search-results-list">

  </div>
</div>

<script id="search-result-template" type="text/x-handlebars-template">
  <article>
    <header>
  		<h2>
        <a href="{{url}}">
          {{{title}}}
        </a>
      </h2>
    </header>
    <section>
      {{{excerpt}}}
    </section>
  </artcle>
</script>

If you chose to embed the template inside the search page, be sure to wrap it in a {% raw %} block so Jekyll doesn’t evaluate the brackets.

From here, it’s just wiring up the template to an event handler and you are good to go!

var template = Handlebars.compile($('#search-result-template').html());

$('.search-query').on('keyup', function (event) {
  $('.search-results-list').html('');

  index.search(query).forEach(function (result, index) {
    $('.search-results-list').append(template(post(result.ref)));
  });
});

Congrats, you now have client side search on your Jekyll blog!

EDIT: (later that very same day):

I forgot to add in the comma in JSON. ,

Welcome to Jekyll!

Jan 20, 2015 •

Welp, I did what all of the new kids are doing and switched to Jekyll for my “professional” blog. Still calling it a blag, because edginess. Oh by the way, how do you like the style? I made it myself. :O

And yes, I can do syntax highlighting…

def print_hi(name)
  puts "Hi, #{name}"
end
print_hi('Tom')
#=> prints 'Hi, Tom' to STDOUT.

Check out the Jekyll docs for more info on how to get the most out of Jekyll. File all bugs/feature requests at Jekyll’s GitHub repo. If you have questions, you can ask them on Jekyll’s dedicated Help repository.