Gtdjedi Podcast - Ep015 - Notes On Notes

Note Management & Organization

What kind of notes go where: images, text, bookmarks, photos?

Will we see services eventually go away as native solutions become more complete?

The importance of syncing and sharing

Note Widgets: Do you use them? Which ones & how?

Presenting Unanticipated Errors To Users

This is the start of a really great series. It uses Swift for the examples but everything in the articles holds true for any language/platform

First, some quick terminology:

  1. an error condition is a failed conditional check that results in a function skipping its usual functionality and instead returning an nominated error value.

  2. an error is a value used to report that an error condition occurred and normal functionality was skipped

  3. error handling is code that looks for errors and performs different actions based on the presence of those errors

  4. error reporting communicates an error result from a user task to the user

Trying to Mock a Self Booting Laravel Model Trait

Bootable Model traits are pretty nifty. I'm using them to register certain events for the models using my Trait. However, I've run into an issue trying to mock models that are using the trait. Specifically, when a Mockery version of the model is instantiated, it's boot code agrees that it should have a bootMyTrait method, but can't find it when it tries to call it.

Sample Repository for the below, with commands to reproduce.

As an example, here is a trait:

namespace App;
trait MyTrait
{
    public static function bootMyTrait()
    {
        print("Booting MyTrait\n");
    }
}

And a model using it:

namespace App;
use Illuminate\Database\Eloquent\Model;
class MyModel extends Model
{
    use MyTrait;
}

Instantiating the model regularly works fine. This shows the desired output:

$model = new MyModel();

However, trying to mock this model does not cooperate. This:

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;


class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testTraitBooting()
    {
        $model = $this->getMock('App\MyModel');
    }
}

Fails. Adding some debugging to Eloquent:

    /**
     * Boot all of the bootable traits on the model.
     *
     * @return void
     */
    protected static function bootTraits()
    {
        $class = static::class;

        foreach (class_uses_recursive($class) as $trait) {
            print("\nTesting that class: $class has method: " . $method = 'boot'.class_basename($trait) . " because of Trait: $trait\n");
            if (method_exists($class, $method = 'boot'.class_basename($trait))) {
                print("Class: $class has method: $method \n");
                try {
                    forward_static_call([$class, $method]);
                } catch (\PHPUnit_Framework_MockObject_BadMethodCallException $e) {
                    print("Class: $class failed calling $method\n");
                    throw $e;
                }
            }
        }
    }

Gives us this failure:

PHPUnit 5.1.0 by Sebastian Bergmann and contributors.

E                                                                   1 / 1 (100%)
Testing that class: Mock_MyModel_9ee820db has method: bootMyTrait because of Trait: App\MyTrait
Class: Mock_MyModel_9ee820db has method: bootMyTrait
Class: Mock_MyModel_9ee820db failed calling bootMyTrait


Time: 129 ms, Memory: 18.00Mb

There was 1 error:

1) ExampleTest::testTraitBooting
PHPUnit_Framework_MockObject_BadMethodCallException:

mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:326
mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:309
mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:296
mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:277
mock-bootable-laravel-model-trait/tests/ExampleTest.php:16

I've also tried creating the mock a few different ways. Using DatabaseSoftDeletingTraitTest as an example:

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Mockery as m;

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testTraitBooting()
    {
        $mock = m::mock('App\MyModel');
        $mock->shouldReceive('bootMyTrait')->once();
    }
}

But here, bootMyTrait is never called:

PHPUnit 5.1.0 by Sebastian Bergmann and contributors.

E                                                                   1 / 1 (100%)

Time: 149 ms, Memory: 19.25Mb

There was 1 error:

1) ExampleTest::testTraitBooting
Mockery\Exception\InvalidCountException: Method bootMyTrait() from Mockery_0_App_MyModel should be called
 exactly 1 times but called 0 times.

mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/CountValidator/Exact.php:37
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/Expectation.php:271
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/ExpectationDirector.php:120
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/Container.php:297
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery/Container.php:282
mock-bootable-laravel-model-trait/vendor/mockery/mockery/library/Mockery.php:142
mock-bootable-laravel-model-trait/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:122

So, I can move the code I'm doing in the boot method to a ServiceProvider, but then I'll need to register each Model that uses the trait. This feels dirty, and using the boot method seems appropriate. So I think I've either hit a bug, or am Mocking the trait-using-model incorrectly. I've looked at getMockForTrait but I also need the mocked instance to extend Eloquent (a few of the trait's methods call eloquent methods)

If anyone sees something I missed, much appreciated

Update Apr, 22 (Friday) 2016-04-22 03:28 PM

Thanks to Marcin, we have a solution!

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Mockery as m;

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testTraitBooting()
    {
        $mock = m::mock('App\MyModel')->makePartial();
        $mock->shouldReceive('bootMyTrait')->once();
        $mock->__construct();
    }
}

Everything Is Possible But Nothing Is Free

What those asking really want to know, though, is one of two things:

Can you just build this thing I want, in addition to all the other things already on your plate, without moving any of your estimates?

Is this “easy” to do?

Here’s a simpler approach: I would like to have this and I’m willing to pay up to that.

Gtdjedi Podcast - Ep014 - Getting Social

The Big Discussion

Social Networking

Which services we use

Which services manage which relationships

Which services we stay away from

What routines are in place that help keep our circles and feeds streamlined

What does it take for a social network to have staying power on your devices?

Jedi Weapons of Choice

Clay - Tweetbot

Jerry - Facebook Paper

Tim - Cluster

Jumping Ship on Basecamp 3

I love Basecamp. I've used it in some shape or form for almost 7 years. I was super excited for Basecamp 3. I wish I could say "It's not you, it's me" but that would be a lie.

Basecamp 3 is not ready

Does it have bugs? No, none that I've seen. Does it have downtime? No, it's been rock solid. What v3 is missing are some key features found in v2. Ones I didn't realize were missing until I went to use them. I've tried to live without them, or work around them best I can, but I'm done.

I started at a new company in January and choosing our tools is my responsibility. Slack and Google Apps were first on the list. Next came something to handle tracking long form conversations and company/project todos. I love basecamp. A new version just came out. Easy decision. One that I now regret.

What I miss from Basecamp 2:

  1. Email In
  2. An API (specifically Zapier integration)
  3. Sorting posts by most recently commented

(The third one pushed me over the edge)

Email-in

There are a lot of people in this world that don't like tools like Basecamp. "Why can't I just use email", "the search sucks", "It's just another thing I have to check" can be heard with regularity. Part of my job involved parading around the office championing Basecamp (or forcing people to use it). Email-in made part of these complaints bearable. It made it "just as easy" as email for starting, or replying to, threads. Basecamp 3 was the promise land that addressed a lot of this with better search and better notifications.

Email in isn’t on the roadmap nor is it listed on the “should we switch" page.

This functionality is partially there, hidden away in the "forward from client" section. When I found out it was missing I almost left, but I figured I could cobble something together with the API and Zapier...

API

I have a few main use cases for an API. The primary one being a hacked together Email-in. The second is replicating Basecamp tasks in my todo app. (I happen to use Omnifocus.)

Lacking an API, or a roadmap for one, I grumbled. But, I figured I could wait and make my tasks by hand. After all, that's me wanting to work the way I like to. Manually entering emails into Basecamp, littering messages with "as communicated by," seemed a small price to pay.

The missing API is listed on the should we switch page, after a long discussion on Github

The good news on the API front is that there has been GREAT progress. I got excited. Soon everything would be as it should

Post Sorting

This hurdle just dawned on me this morning while I was scrolling down looking for something. Basecamp 3 only sorts posts by their created date. Which meant that our most frequently updated post, with dozens of comments, is all the way at the bottom, with a bunch of fluff between me and it. It seemed like there had to be a way to change the sort, but I confirmed with Basecamp this is not available.

Use search! Ok, but now an app is asking me to take on cognitive load of something it should handle

You are using it wrong! Don't even go there, I spent years at my last job working with some of the best UX and Creative Designers I've ever seen. If "the customer just isn't using it right" was used as an argument, we hadn't solved the problem

Use notifications! I do, they go away

One could argue that I'm just annoyed that "things have changed and I just want things to go back to the way they were in 2". I thought about that. Is this just me? Am I just whining? Email in and an API are missing, not changed.

Using "Email In" isn't the way the product was meant to be used! Tough, it was there for years.

Even if I could suck it up and trudge through lacking email and API, It is beyond me why you would want older content above newer content

So, I'm leaving. We are moving too fast for this to slow us down. I can't wait for "someday/maybe" (Basecamp does not release timelines; I respect that but it doesn't help me here)

Tim, if you love v2 so much, just use it. I might! But:

  • I'm not sure how long v2 will be around
  • When it does get decommissioned, will my above issues still exist?
  • Will a v2 to v3 migratory exist? (I would hope so)

The barrier to switching will be much higher if/when v2 dies than it is now. Should I switch to v2? Probably. Should I take some time and look at something like http://asana.com? Yep, I have. Now if I could just get over how they format the emails...

How To Set Up An Ios And Android Smart App Banner

Leveraging their link redirect and deep linking expertise, Branch just released a fully customizable, cross-platform, deep linking and tracking smart app banner. It works on all browsers: Safari, Chrome, Firefox, stock browsers and even desktop versions.

​This looks pretty good. Curious how well it will play with JLRoutes

Tektok Podcast - Ep025 - Ocd & The Se

TEK Topics

Patrick: iPhone SE

What are your thoughts on the iPhone SE, was Apple smart to hold this device out for Spring announcement?

Jerry: Smartphone as a primary (and only) computing device?

Can your smartphone be your primary (and only) computing device?

Tim: Mobile Money

How comfortable are you sending money with your phone? (venmo, square cash, FBM, snapchat)

How comfortable are you giving these apps your CC or checking account info?

Snuck in some discussion about Kidfund ;)

Disclosed of course

Justin: RSS and news apps

What is your routine for saving news/blog posts? By the time you get to them are they already old news?

Clay: Homescreens on iOS

How would you like to see the home screen changed in iOS?