Picture of Michael Lee
:wave: Hey hey, I'm Michael Lee and this is my site about being a developer, being a dad and making side projects.

Multiple user management on iOS probably ain't happening

Written on November 20, 2018

I’ve been a fan of the iPad. I believe one of the pros with the iPad is iOS. Let’s be honest, most folks probably use the iPad mostly for browsing the Internet and binging on YouTube videos and Netflix. But I truly believe the iPad can be utilized to do some productive work.

In the past, I’ve used an iPad to write long form for this site, I’ve even done some light dev work. And it has been a delight because one of iOS’ main features is focused application use. Well, I guess, if you don’t use split view or slide over.

One thought I’ve had about the iPad and I suppose more specifically about iOS, is if it would ever get the ability to manage multiple users. The scenario would go like this, like a family iMac, you could get an iPad Pro to share with your entire family. Depending on when the device sees downtime, different members can pick it up and use it. In doing so, you’d have the ability to have different apps set up each tied to different iTunes accounts.

If iOS could handle multiple users each tied to their own iTunes account, I wouldn’t have run into the sad reality that iOS’ Family Sharing doesn’t support In-App purchases.

I think this could be pretty powerful, but I don’t think Apple is going to create such a feature. With the iPhone and iPad being such a personal device, I’m guessing that they imagine every member of the family having their own (i)device instead of sharing one. But for once, it’d be sweet to be able to hand off my iPhone to my toddlers and not worry about a 300+ burst shot of them running around the house taking up my camera roll. Or guessing which app my kid deleted or rearranged when I get my device back from them.

Think about the possibilities if you could quickly swap users and then hand off a device to your kid and their account is almost sandboxed, tailored to their usage. Or being able to share a single iPad Pro with your spouse, with different apps for each of your own needs. While I still hope one day that Apple will build such a feature, I wouldn’t hold my breath. They’re probably betting on each member of a family just purchasing their own devices.

In-App purchases are not shareable with Family Sharing in iOS

Written on November 20, 2018

In-App purchases not shareable photo

Well, that stinks. Tonight I found out that In-App purchases are not shareable in iOS’ Family Sharing feature.

My wife has a last generation iPad Pro that she uses to make paper goods and catch up on shows and movies on Netflix. When she isn’t using it, I thought I could set up some apps to do some focused writing.

One app that I’ve recently started using more of is Working Copy, which lets me work with various projects that are versioned with Git. Working Copy is free to download but to unlock the ability to push, requires a $15.99 in-app purchase, which I gladly paid on my personal iTunes account.

On my wife’s iPad, she’s got her own iTunes account which is linked to my account via the Family Sharing feature. We’ve used this feature before to download apps that I purchased with my account to her iOS devices. But according to Apple, in-app purchases aren’t one of the things that gets shared.

Prior to Working Copy, if I was on an iPad, I’d just set up SSH access to my desktop on my local wi-fi. But being able to have a working copy of my site’s source that I can tweak and change offline has been nice for mobility purposes and not having to set up so many things to get this setup working.

Guess I’ll just have to pair my bluetooth keyboard to my iPhone and do some writing there for now.

Google Forms is neat

Written on November 18, 2018

Google Forms is a neat service provided by Google, where you can quickly set up forms and all your form submissions will collect into Google Sheet document. I’ve used the service before to set up forms for various this and tonight I spent some time setting one up for taking new conference submissions.

I’m not quite sure when this feature was implemented, but Google Forms allows you to set up multiple sections and based on certain answers to your form, you can guide the user to the various sections. I thought this was really neat because essentially, you can have some logic set up into your form which you can then use to guide the user based on their answers.

I’ve often found this as a pro feature in other form SaaSes, so when I saw that Google Forms provides this, I thought it was really nice.

Google forms sections logic

The form I had set up tonight for ConfsList, first asks for details of a conference. If there is an upcoming event for the conference, then the user will be asked to fill out additional information about the event. If there is no upcoming event, then the user will be directed to the form’s submit button. Being able to guide the user journey is powerful stuff.

Google Analytics gtag setup for Rails 5.2

Written on November 17, 2018

Google has made grabbing traffic data from your site super simple. Most of the time you can just copy and paste the tracking code from the Google Analytics site to your web property’s <head> tag and start receiving data about traffic to your site.

In a Rails application, the set up is a little more involved.

Grab gtag Google Analytics code

Before we get started, we’ll want to grab the Google Analytics tracking code which can be found on the Google Analytics site under Admin > Property > Tracking Info > Tracking Code.

The code should look something like this:

<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXXX-X"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'UA-XXXXXXXX-X');
</script>

You’ll also need your tracking ID, which should be on the same page. It should look like UA-XXXXXXXX-X where X are numbers.

Store tracking ID in your app’s encrypted credentials file

Starting from Rails 5.2, instead of using a file that isn’t tracked in your version control system, Rails provides an encryted credentials file that you can commit into source and make available to all instances where your application is running.

Since the analytics code is JavaScript code, the tracking ID will be exposed in a browser’s source, but it’s still good to store the tracking ID along with your app’s other credentials. As you can see in the Google Analytics code above, there are two instances of the tracking ID. You can have both instances make reference to the stored credential and then if you ever need to change the ID, you’ll only have to do it in one place and not worry about changing multiple sections of your code.

To add the tracking ID to your credentials file, you’ll first open up the credential file by running:

EDITOR="nvim" bin/rails credentials:edit

Where nvim is your text editor of choice. NeoVim is my editor of choice so that’s why I have EDITOR="nvim"

If your editor is a GUI-based editor such as Code or Atom, you’ll also want to pass --wait.

EDITOR="atom --wait" bin/rails credentials:edit

Passing --wait will cause Rails to wait until the editor closes the credential file before accepting the changes and saving the latest credentials.

Once the credentials file is open, you’ll want to add in an entry like:

google_analytics: UA-XXXXXXXX-X

Again where XXXXXXXX-X is your unique tracking ID. Then save and close the file.

In your command line you should see a confirmation message like this:

New credentials encrypted and saved.

Another indicator that new credentials have been added to your application is that Git will indicate changes in the encrypted file config/credentials.yml.enc.

Create a Google Analytics view partial

Next we’ll want to add the Google Analytics code snippet to the <head> script found in the application.html.erb file, but before we do, it’s good to create a partial and add the partial to the application file. In creating a partial, the analytics code is in a single file and is quicker to access if you ever want to reference it in your project.

For this example, I’ll place this partial into my layouts folder in a file name _google_analytics.html.erb.

.                              
└── app   
    └── views
        └── layouts
            └── _google_analytics.html.erb

Within the new partial we’ll want to paste this code:

<% if Rails.env.production? %>
<script async src="https://www.googletagmanager.com/gtag/js?id=<%= Rails.application.credentials.dig(:google_analytics) %>"></script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());

    gtag('config', '<%= Rails.application.credentials.dig(:google_analytics) %>');
  </script>
<% end %>

There are two things to point out in the code snippet above. First it’s <% if Rails.env.production? %> which tells Rails to only render this block in production environments and not when you’re running on your machine in development mode. The second is <%= Rails.application.credentials.dig(:google_analytics) %> which is how you get the tracking ID rendered from your application’s credentials to the Google Analytics code.

If you’ve got your Rails application set up to use Turbolinks, you’ll also need to set up an event listener to send the gtag API the page’s URL when Turbolinks loads a new page.

First create a file in your javascripts file, I’ll being using a file called google_analytics.js.erb.

.                               
└── app               
    └── assets            
        └── javascripts 
            └── google_analytics.js.erb

The reason for the .js.erb extension is that, we’ll be passing the Google Analytics tracking ID using Ruby syntax. If you leave the extension as just .js then you can’t pass the tracking ID from the application’s credentials.

The event listener looks like this:

document.addEventListener('turbolinks:load', function(event) {
  if (typeof gtag === 'function') {
    gtag('config', '<%= Rails.application.credentials.dig(:google_analytics) %>', {
      'page_location': event.data.url
    })
  }
})

What the event listener above does is, first to check if the turbolinks:load event is triggered. If so, then an if statement checks to see if a function of gtag is available by checking typeof gtag === 'function'. If a gtag function is available, then it calls the function and sends a pageview.

If we’re running our application in a development environment, the gtag code defined in our _google_analytics.html.erb partial won’t render, which means that the gtag function won’t be available when this snippet of JavaScript is reached. This ensures that pageviews won’t be sent in a development environment.

Add the partial

Now that we’ve got the Google Analytics code snippet in a partial and have an event listener set up in our JavaScript, all that’s left is to add the partial in our layout file.

# app/views/layouts/application.html.erb 
...
  <head>
    <title>Awesome application</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= render 'layouts/google_analytics' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>
...

As you can see, I’ve placed the partial to render above the javascript_include_tag helper. This is so that if the application is being run on a production server, the Google Analytics code will be made available before the application’s compiled JavaScript is run.

Toggle word wrap in Vim

Written on November 15, 2018

By default, I’ve got Vim set up to not word wrap. While this is useful for writing code, it sometimes is a nuisance when writing notes or posts for my site as the sentences are cut off past the current view.

Toggling is pretty straightforward in Vim, so in instances in when I do need the copy in front of me to be word wrapped I could turn it off and then quickly turn it off again.

Command to turn on word wrap in Vim

To turn on word wrap in Vim, you’ll want to enter this sequence of characters in normal (command) mode:

:set wrap

This will immediately word wrap all the sentences in the current document that is open in the buffer.

Command to turn off word wrap in Vim

To turn off word wrap in Vim in the current document that is open, you’ll want to enter this sequence of characters in normal (command) mode:

:set nowrap

Command to toggle word wrap in Vim

While :set wrap will turn on word wrap in Vim and :set nowrap will turn off word wrapping, you can also use both commands with the ! (bang) symbol to toggle word wrap.

So using either:

:set wrap!

or

:set nowrap!

Will both toggle word wrap in the current document in the buffer.

Weniger aber besser (Less but better) - Dieter Rams

Written on November 7, 2018

I’m really digging this German quote by designer Dieter Rams. It’s a quote that’s in the book I’m currently reading, Essentialism. What the quote embodies is the pursuit to get to the essence of something by filtering through the noise.

I admire this focus to hone in on what’s needed and then keeping the urge to add more just for the sake of it at bay. I think it’s easy to over complicate something because we often look at simple and think something is wrong or missing from it. I definitely feel like I could embody more of this quote in my life.