Today I Learned

A Hashrocket project

12 posts by jonathanjackson

Highlight code without transient file using pbcopy

I’ve been creating a LOT of code slides in keynote recently. I’d like to have it highlight and also show up as text rather than a screenshot. And I want it to be EASY!

Look no further. Copy the code snippet you’d like to highlight then run:

pbpaste | highlight -O rtf  --src-lang js --style solarized-dark --font Monaco | pbcopy

This will pass your current paste buffer to highlight, format it, then put it back into your paste buffer for immediate paste into Keynote (or where ever).

Too easy!

Check highlight --help for more options and languages.

highlight brew formula

Use suffixadd to save yourself some life

I’ve been wasting a lot of my time trying to find certain backbone files lately (yes I know, coffeescript blehg).

define [
  'hbs!templates/my_template'
  'views/my_view'
], (
  Template
  MyView
) ->

I’d like to just go to the template line and type gf

So vfnegrisolo helped me out and added the following to my .vimrc.local:

autocmd BufRead,BufNewFile *.coffee set path+=app/assets/javascripts/app/

Which in coffeescript files adds the location of my backbone app. Which is great, but for some reason it wasn’t working on one of our dev machines. Luckily, with some quick googling, we were able to get to the bottom of it with suffixadd!

autocmd BufRead,BufNewFile *.coffee set suffixesadd+=.coffee,.hbs

Which searches the path with the suffix added to the search criteria as well. Which has already saved me soooo much time! Yay!!!

[Ember Integration tests] `this.inject` rocks!

When I first saw the inject helper in Ember Integration tests I had assumed that I would use these to stub services for testing purposes.

@rwjblue quickly pointed out to me that this is/was not their intent. And that for that I should use register for that purpose.

Instead what they are useful for is to utilize functions (helpers) found on services. Something like i18n.t. For our example I’ll just assume we have a service named foo with a function upcase. And our component takes a string and presents it upcased in a span.

With that in mind we can do something like this in our integration test:

moduleForComponent('some-thing', {
  integration: true
});

test('does a thing', function(assert) {
  this.inject.service('foo');
  this.render(hbs`{{some-thing textToRender='foo' }}`);
  let result = this.foo.upcase('foo'); // 'FOO'
  
  assert.equal(this.$('span').text(), result, 'should upcase textToRender');
});

Alright, I know what you are thinking. This is a little contrived. And it is, but let’s examine what this is doing a little more closely.

We injected foo to make it available in the testing context with this.foo or this.get('foo'). That’s super sweet!

Need a service helper function you can do it with this.inject!

Learn more here

Cheers

[Ember Integration tests] `this.register` rocks!

In Ember Integration tests it sometimes becomes necessary to stub / mock services. Luckily, we have a few options open to us.

Let’s assume that we have a service called foo that implements an API method called bar. We’ll also assume that when you click on our components’ a tag you trigger an action that calls the foo service’s API.

Whoa, still with me?

keanu

Alright. Let’s dive in!

import FooService from '<app-name>/services/foo';

moduleForComponent('some-thing',  {
  integration: true,
  beforeEach(){ 
    // extending in case the foo service has other responsibilities
    this.register('foo', FooService.extend({
      bar() { assert.ok(true); } 
    }));
  }
});

test('blah', function(assert) {
  assert.expect(1);
  this.render(hbs`{{some-thing}}`);
  this.$('a').click();
});

That wasn’t so bad. We’re simply ensuring that the FooService’s bar API function gets called. I think this is a wonderful way to handle this.

You can find more information about this.register (and how to stub/mock services) here:

Stubbing Services Ember.js Guides

Fastboot proofing your Ember addons...

I’ve been working a bit on trying to get Ember Weekend working with fastboot (again). The process was halted when I ran into complications around Liquid Fire and its animation dependency lib Velocity.js, which requires that a document be present.

Fastboot uses Simple DOM as its DOM and does not call it document on self (or window). Server side rendering with Fastboot has some limitations around what you are able to do as a result.

In most cases your addons should guard against any document usage with the following guard:

if (typeof document !== 'undefined') {
  // something with document here
}

Yesterday, I put a PR in (which is very much still a WIP) to help make this easier for addon authors who use EmberApp#import to get their dependencies into vendor.js. The idea is to automatically wrap all dependencies imported this way with the guard above. And allow opting-out by specifying preventDOMGuard in your app.import

app.import(this.bowerDirector + '/foo.js', { preventDOMGuard: true });

We’ll see how it goes.

Module imports in EmberCLI

If you’ve worked with EmberCLI a bit, you’ve probably run across a few import lines that look like:

import Ember from 'ember';

This actually gives you the Ember global (eventually the Ember module), but silences your jshinter which is warning you that you shouldn’t really use globals. This prepares you for some long term changes to EmberCLI.

Sometimes, however, you might want to be more specific.

You can do this in a couple of ways, the last of which is what I’d recommend.

First, utilizing ember-cli-shims:

import computed from 'ember-computed';
// or 
import { alias }  from 'ember-computed';

This is great. You can look at the ember-cli-shims repo to see what shims have been made available. However, I’d caution you here, it is likely that there will be changes to these shims. For example, ember-computed could change to @ember/computed. So, I’d actually reccomend…

Second, import and immediate destructure:

import Ember from 'ember';

const { computed } = Ember;

This leverages es6 style destructuring. This way your code doesn’t have to change when the module import changes are complete, you’ll just have to remove the destructuring assignment and update your import statements.

Cheers

Using the `wait` helper in Ember integration tests

Component integration tests are a powerful way to test your Ember components in relative isolation. They look something like this:

test('it renders', function(assert) {
  assert.expect(2);

  this.render(hbs`{{x-foo}}`);

  assert.equal(this.$().text().trim(), '');
});

Sometimes, however, you’ll want to handle a bit of asynchrony. Thanks to rwjblue that is now not too big of a deal with the wait helper:

import { moduleForComponent, test } from 'ember-test-helpers';
import wait from 'ember-test-helpers/wait';

test('it works when async exists in an event/action', function(assert) {
  this.render(hbs`{{my-foo}}`);

  this.$('button').click();

  return wait()
    .then(() => {
      // assertions for after async behavior
    });
});

And that’s about it! You’ll need to update ember-qunit to at least: v0.4.15

Cheers!

Inheriting from LinkComponent in Ember is amazing!

LinkComponent is the module backing the famous Ember {{ link-to }} helper. The LinkComponent will automatically add an active class to components that inherit from it as well as override their click handler to direct to a specified route.

Until quite recently in (Ember 2.1) it wasn’t really possible to utilize this module without {{ link-to }}.

No longer!

My use case was simple, I wanted to have a {{ link-to tagName="li" }} with some draggable behavior. This proved to be quite difficult. Once I got our app up to 2.1 I decided to use LinkComponent

To do so is quite simple:

// app/components/x-foo.js
export default Ember.LinkComponent.extend({
  tagName: 'li'
  // your handlers here
});

Then you invoke it just as you would with a {{ link-to }}

{{# x-foo 
    pathToRoute
    model 
    myComponentAttribute1='foo' 
}}
{{/ x-foo }}

And that is it. You get for free the active class behavior and your component’s click handler will have knowledge of Ember’s router to send you to the route you specified at invocation.

I had a great experience pulling this in (got to remove 20 or so LoC), have fun!

Cheers,

Jonathan

Ember Truth Helpers and HTMLBars Sub Expressions

Sub expressions. Sounds kinda ominous right? Well, let me show you a few ways you can leverage ember-truth-helpers to clean up your HTMLBars templates.

Given something like:

{{# if hasComments }}
  Yay comments!
{{/ if }}

You need to have a CP to handle this:

hasComments: Ember.computed.gt('comments', 0)

Which is fine, but this is such a simple operation isn’t there an easier way?

Sub Expressions to the rescue!

{{# if (gt comments.length 0) }}
  Yay comments!
{{/ if }}

Here we are using the truth helper gt and a subexpression so we don’t have to use our context at all.

This reads easily and won’t be subject error when some poor soul chooses a confusing variable name (as would be the case in the former example).

But that isn’t all, Sub Expressions are composable.

Imagine that we need to also ensure that there is an sandBox is not specified. We could simply leverage SE’s again:

{{# if (and (gt comments.length 0) (not sandBox) ) }}
  Yay comments!
{{/ if }}

Okay, so sandBox is a little bit contrived, but you see the power (I hope).

Cheers,

Jonathan

Let's talk about Ember's {{ mut }} HTMLBars helper

You’ve likely seen code that looks like the below since Ember 1.13 was released:

{{ my-component updateAction=(action (mut model.value)) }}

And been confused as to what this means. Luckily, @rwjblue explained in the EmberJS Community slack that:

Which kinda clears things up. It’d be a little easier if we could correlate the mut helper with something a bit more familiar. The above my-component snippet could be rewritten like so:

export default Ember.Controller.extend({
  actions: {
    updateValue(newValue) {
      this.set('model.value', newValue);
    }
  }
});

and

{{my-component updateAction=(action 'updateValue')}}

To restate the exposition from @rwjblue above… The mut helper returns a mutable object which is an object that responds to update. The action helper knows about these objects and knows to call update (passing in the new value) when given a mutable object .

This is a great shorthand that enables us to write a LOT less boilerplate code, but does require a little bit of understanding so that we don’t confuse each other.


The above information was shamelessly stolen from the EmberJS Community Slack. If you’d like to participate join by going here: Ember Community Slack Invite Page to get your invite.

Cheers!

Yielded closure actions as an API for a Component

From within x-parent component that has an action update that (for example) returns a promise:

{{ yield (action 'update') }}

You can then tap into that update action from within the block section like so:

{{ x-parent as |parentUpdateAction| }}
  {{ x-child update=parentUpdateAction }}
{{/ x-parent }}

Then from within the click handler on x-child you could utilize the promise returned from the closure action:

click() {
  this.attrs.update().then(function(){
    // do something like transition away
  }).catch(function(){
    // update ui to handle error case
  });
}

Yielding closure actions like this is powerful. Being able to utilize the return value from a closure action is great for ensuring that the right section of your application is responsible for the things that it cares about.

I’ve recently talked about this on Ember Weekend.

Specifically I think that you can utilize this feature to create Ember components that yield their API. Treating these yielded actions as the component’s API can allow you to create template DSL’s that are really something special.

Cheers, Jonathan