Categories
Programming

Something About Refs

React’s Virtual DOM arguably revolutionized web development. In short: React will keep a copy of the DOM in its own memory space. When you make updates, for example, several updates to component state, the React will manipulate the Virtual DOM first, performing all of the mutations on it in succession. Once all of your logic has run, React knows how to compare the Virtual DOM to the real DOM, and then it makes small, isolated updates one-by-one, only changing the least amount necessary.

Why does it do this? Well, for one thing, when the browser performs DOM operations it is famously slow at doing so, that is non-performant when many updates are happening. If each mutation of the DOM was done in the browser, you couldn’t achieve the fast effects you can with React.

You’ll note then that the objects you code in React, then, don’t expose direct access to the DOM elements. This is a good thing, because it means that to change the DOM you must always go through the React re-render cycle when you want to change your DOM.

Most of the time, this can get you most of what you need doing. But occasionally, if you need to access DOM elements to inspect them, you’ll want to use a feature of React called React Refs.

Other cases of using Refs is to manage text highlighting, managing focus, and media playback. Refs are also used for some advanced purposes too, like managing interactions with 3rd parties and multistep form state.

Today I will explore three patterns for using Refs in React: 1) A basic Ref implementation, 2) A forwarded Ref, that is a ref that has been sent to another component, and 3) A forwarded Ref used within a Styled Components setup.

Remember, your Ref will simply point to the DOM elements. What’s important here to keep in mind is that you 1) first need to create your ref, 2) then assign it to a component using ref= , and 3) let React maintain the Ref for you during the rendering.

Example #1 — Basic Usage

First, you need to create a Ref object. You do this before your component is rendered using React.createRef()

First let’s start with the most basic React component. (To see this, edit your App.js file and remove the default content and add <ThingOne />)

// src/thing_one.js

import React from 'react'

class ThingOne extends React.Component{
  constructor(props) {
    super(props)
    this.ref1 = React.createRef()
  }
  
  render() {
    return (
      <div>
        
      </div>
    )
  }
}

export default ThingOne

Notice that in the constructor, we create the Ref using this.ref1 = React.createRef(). At this point, if you examine your object, you will see something interestingly empty:

Notice that your variable now holds an object with a single key, current, that points to nothing (null).

Now, let’s add an input checkbox and also tell React to use this ref (ref1) for that input checkbox.

import React from 'react'

class ThingOne extends React.Component{
  constructor(props) {
    super(props)
    this.ref1 = React.createRef()
  }
  render() {
    return (
      <div>
        this is an experiment into forwarded refs
        <br />
        Please check this box:  
        <input type={"checkbox"} ref={this.ref1} />
      </div>
    )
  }
}

export default ThingOne

We use this Ref (ref1) in the render method, when we call

<input type={"checkbox"} ref={this.ref1} />

Here, we’re telling React when it renders the dom, a reference will be stored back onto the value in the current slot in our Ref.

If you examine the Ref after React has rendered, you get something different:

Now, the Ref’s current value is a reference to the DOM element. That means that it can be treated like a “native DOM element” because it is one.

Finally, in our little baby example, we’ll attach an onClick handler to the boxChecked handler.

import React from 'react'

class ThingOne extends React.Component{
  constructor(props) {
    super(props)
    this.ref1 = React.createRef()

    // if you don't bind your method then boxChecked will be called
    // without `this` in scope
    this.boxChecked = this.boxChecked.bind(this)
  }
  boxChecked(event) {
    const dom_elem = this.ref1.current
    const is_checked = dom_elem.checked
    alert("This box is now " + (is_checked ? 'CHECKED' : 'UNCHECKED'))
  }

  render() {
    return (
      <div>
        this is an experiment into forwarded refs
        <br />
        Please check this box:  
        <input type={"checkbox"} ref={this.ref1} onClick={this.boxChecked}  />
      </div>
    )
  }
}

export default ThingOne

Be sure to bind it to the this object (because, err.. javascript) in the constructor, and Bob’s your uncle… once clicked, this.ref1.current now returns {current: input} as you see above. As you can see from the code in boxChecked, you can pull the DOM element out from this.ref1.current and then examine it using native HTML properties (.clicked is implemented in the browser and is a native DOM element property.)

You can see the full code for this example here.

Example 2 — With Ref Forwarding

Now it’s time to go down the rabbit hole a little deeper. And with ref forwarding, we really are traveling down a rabbit hole.
Let’s stay we want to nest ThingTwo inside of ThingOne, but be able to look at the ref for ThingTwo from code inside of ThingOne.

Let’s say we try something like this

// src/thing_one.js

import React from 'react'
import ThingTwo from './thing_two'

class ThingOne extends React.Component{
constructor(props) {
super(props)
this.ref1 = React.createRef()

// if you don't bind your method then boxChecked will be called
// without `this` in scope
this.boxChecked = this.boxChecked.bind(this)
}
boxChecked(event) {
const dom_elem = this.ref1.current
alert("ThingTwo is " + dom_elem.getBoundingClientRect())
}

render() {
return (
<div style={{position: 'relative', border: 'solid 1px green'}}>
this is an experiment into forwarded refs
<br />
Please <button onClick={this.boxChecked} type="button" > click here </button>

<ThingTwo ref={this.ref1}/>
</div>
)
}
}

export default ThingOne

// src/thing_two.js

import React from 'react'

class ThingTwo extends React.Component{

render() {
return (
<div style={{position: 'relative', top: 0, left: 0, border: 'solid 1px red'}}>
This is thing Two
</div>
)
}
}

export default ThingTwo

Warning: The above code doesn’t actually work!

It makes sense that we might think we can pass a ref as a prop from one component to another. However, because of how React passes props around, this doesn’t actually work. Moreso, it actually produces no error message or indication to the developer that this is wrong. But here’s how you know it’s wrong: If you examine the ref once the UI is rendered, you get this wrong result:

If you see the name of the Component, something is wrong. it won’t work and your ref will not be usable. What’s wrong here is that you need to forward your ref from one component to another.

Interestingly, the code in thing_one.js doesn’t change — you’re still going to pass the ref down to ThingTwo via the props.

However, for ThingTwo, you need to wrap ThingTwo’s entire implementation in React.forwardRef. This utility method will take a function and will call that function with two arguments: the props passed and the ref passed, but it will allow you to pipe the ref into ThingTwo like so:

import React from 'react'

class ThingTwo extends React.Component{
  render() {
    const {selfRef} = this.props

    return (
      <div ref={selfRef} style={{position: 'relative', top: 0, left: 0, border: 'solid 1px red'}}>
         This is thing Two
      </div>
    )
  }
}

export default React.forwardRef((props, ref) => <ThingTwo {...props} selfRef={ref}  />)

Many examples online use a pattern like ref={ref} but I personally find this confusing for demonstration. What is happening is that one variable name exists in the ForwadedRef constructor, and a distinct variable also named ref then also exists inside your component, they just happen to both be called ‘ref.’ To eliminate the confusion, I named the ref that ThingTwo receives selfRef, indicating that this variable is only ever used as the reference to DOM element that maps to the component (to ‘itself’). You can pick any variable names you want, but this example demonstrates that the variable occupies a distinct namespace in ThingTwo.

Now, if you examine your ref after rendering, it looks like so:

Note that in some cases your DOM element object looks slightly different. For example, if React renders multiple of the same component, it will keep letter-based class names on your objects (it does this as its internal mapping to the DOM).

Here’s an example from a different app (you aren’t seeing the code for this). In this case, my component has a built-in class for logo-container and the strange-looking characters that make up the other classes are correct.

The example code for example #2 can be found here.

Example 3 — With Ref Forwarding in a Styled Component

Forwarding refs is slightly tricky. Once you get the hang of it, it makes sense. Always remember that the receiving component must be wrapped in the forwarder. The final pattern to show you here is how a ForwardedRef can be used with Styled Components.

This example is just like #2, except that ThingTwo uses a StyledThingTwo to display itself

import React from 'react'
import styled from 'styled-components'


const StyledThingTwo = styled.div`
  position: relative;
  top: 0;
  left: 0; 
  border: solid 1px red;
`

class ThingTwo extends React.Component{
  render() {
    const {selfRef} = this.props

    return (
      <StyledThingTwo ref={selfRef} >
        This is thing Two
      </StyledThingTwo>
    )
  }
}

export default React.forwardRef((props, ref) => <ThingTwo {...props} selfRef={ref}  />)

You will note that because StyledThingTwo is a functional styled component, it doesn’t need its own forwarded ref wrapper. Only the ThingTwo needs to be wrapped in the forwardRef call.

Apple Airport Express Base Station models A1088, A1264, and A1392

If you own an Apple Airport Express Base station model number A1088 (sold 2004-2008), it will no longer update with Apple Airport Utility 5.7.

If you have a later version A1264 (sold 2008 to 2012) or (sold 2012 to 2018) it will continue to work with the modern Airport Utility.

To update Airport A1088, you need to use an old version of Apple Airport Utility (5.6.1), which can only run on very old operating systems.

see this link for reference.

Categories
Programming

Halfway to One Point Oh: UTM Version 0.5

Today I’ve finished version 0.5 of my new Gem, Universal Track Manager.

It’s a plug-and-play Rails engine that you install into your Ruby on Rails application with just three simple steps (see the README). You can then immediately pick up your visitors’:

IP address
Ad campaign where they came from
the browser they are using

In my next version, I’ll add support for http referrer and more too. Give it a try today.

If you like the Gem, please ‘star’ it on Github or download it from RubyGems (you do that just by running bundle install). Also, consider supporting it today with a small contribution today through the Github sponsors program. Sponsors levels start at just $1/month.

Categories
Programming

Universal Track Manager Version 0.4

Today I’m announcing Version 0.4 of my new Gem: Universal Track Manager.

It’s an great little utility project that will surely have appeal to many websites and developers.

Visitors come to your site every day. Along with their visits, four key pieces of information come along for the ride:

— IP address
— browser name (which lets you infer operating system and sometimes device)
— UTM parameters (if they clicked from another site or an ad campaign)
— HTTP referrer, (which shows if they clicked directly from another site to your site, even when no UTMs are set)

Universal Track Manager, a play-on-words that shares an acronym with “UTM Parameters,” is a plug & play gem to automatically scoop up this information and stash it into your database. You can think of it like a built-in Google Analytics (without the fancy dashboard).

With a tiny bit of trickery, support for Viewport size too is possible (width X height of the users’s window), which can let you determine if the user is on a desktop or mobile browser.

Today I’ve bumped the version up to 0.4. (I realize I made a 10x version change but this Gem is nearing its ‘version 1.0’ release so I am anticipating that when it is feature complete.)

This is the second version I’m dubbing as ‘public beta.’ Although this is production-quality code, it should be used with caution until it is no longer in BETA status. Please give it a try on your Rails projects today. With an easy 3-step installation into any Rails 4+ app and you can sit back and sweep up tracking info on your visitors.

*MOST* of the core functionality now works! This version 0.4 implements fully support for timestamping your visits, the user’s IP address, browser, and UTMs.

Support for HTTP referrer and more coming soon! Kindly submit feedback via Github.

Links:

Github Repo

Rubygems page

Categories
Programming

A First Look : Universal Track Manager

Today I’m announcing ‘a first look’ at my new Gem: Universal Track Manager. It’s an ambitious project that’s going to have nearly universal appeal and utility.

Visitors come to your site every day. Along with their visits, 4 key pieces of information come along for the ride:

— IP address
— browser name (which lets you infer operating system)
— UTMs showing if they clicked from another site, or if they came from online advertising (typically you can “auto-tag” your ad campaigns and your UTMs will be magically populated)
— Http referrer, which shows if they clicked directly from another site to your site (Even when no UTMs are set)

Universal Track Manager, a play-on-words that shares an acronym with “UTM Parameters,” is your one-stop shop to automatically pick up this information and stash it into your database. You can think of it like a built-in Google Analytics (without the fancy dashboard).

As if that weren’t ambitious enough, with a tiny bit of trickery I’m planning support for optional Viewport size (width X height), which can let you determine if the user is on a desktop or mobile browser. (coming soon)

I’m pleased to announce Version 0.0.3, the first version I’m dubbing as ‘public beta.’ Although this is production-quality code, it should be used with caution until it is no longer in BETA status. You are welcome to give it a whirl on your Rails projects today. With an easy 3-step installation into any Rails 4+ app and you can sit back and sweep up tracking info on your visitors.

*MOST* of the core functionality now works! This version 0.0.3 implements fully support for timestamping your visits, the user’s IP address and browser. Support for UTMs & HTTP referrer and more coming soon! If you are curious now’s a great time to try it out, please submit feedback via Github.

Links:

Github Repo

Rubygems page

Categories
Programming

Announcing Nonschema Migrations — NOW FOR RAILS 6!

Nonschema migrations version 5.0.0: RubyGems Page, GitHub page

Now compatible with Rails 6, nonschema_migrations is the best way to separate your schema changes from your data changes.

Want to run no-downtime deploys with data-only migrations? No problem.

Install it in your Rails app today to see what a difference data migrations can make.

Shout out to Mikls Fazekas who hails all the way from Gyenesdis, Hungary for the pull request for this release!

Categories
Programming

Jason FB’s 10 Magical Ruby Developer Tools

1. deivid-rodriguez/byebug
Byebug is a fantastic debugger available for Ruby 2 (and presumably above). Drop

gem ‘byebug’

into your Rails app Gemfile and bundle install. In either your test run or your development run, write

byebug

on a single line of your app and voila. When you hit that line, you will drop into the debugger.

If you’re not developing a Rails app, you can include ‘byebug’ at the top of your Ruby file.

Full docs here.

2. pretty print (pp)

Pretty print is one of my favorite introspection weapons to help see variables more clearly.

pretty print, which you write as pp, prints out your object with each attribute on its own line. Take for example this Spree::Country object, shown here on the Rails console without pretty print

2.4.6 :010 > x
=> #<Spree::Country id: 232, iso_name: “UNITED STATES”, iso: “US”, iso3: “USA”, name: “United States”, numcode: 840, states_required: true, updated_at: “2019-05-19 17:16:07”, zipcode_required: true>

Now, with pretty print, the same object is conveniently displayed with each attribute as its own line. This is invaluably helpful when you have deep nesting of objects.

2.4.6 :009 > pp x
#<Spree::Country:0x00007fd8507ea358
id: 232,
iso_name: “UNITED STATES”,
iso: “US”,
iso3: “USA”,
name: “United States”,
numcode: 840,
states_required: true,
updated_at: Sun, 19 May 2019 17:16:07 UTC +00:00,
zipcode_required: true>

3. puts, .to_s, and inspect

OK, so we get a 3-in-1 here: When you call puts on an object, .to_s will be called and then output to your screen. So you should make your objects have a .to_s that is human readable, possibly even for use in, say, a drop-down menu or label. 

def class Person
 attr_accessor :first_name, :last_name

 def to_s
   “#{first_name} #{last_name}”
 end
end

inspect, on the other hand, is specifically for developers. In this method, you would write out as much information as you the developer (or next developer) want to see, including the keys (ids) of your objects if those will be helpful:

def class Person
 attr_accessor :first_name, :last_name

 def inspect
   “Person id: #{id} – first: #{first_name}; last: #{last_name}”
 end
end

Your objects should have both .to_s and .inspect on them, and you can try these universally named Ruby methods on other people’s objects to examine them. A well-formed codebase implements them or has helpful output for both of these.

4. .to_yaml
Pretty print’s cousin is the .to_yaml method, which will take your object and convert it into yaml. Take for example this arbitrary object, which you will notice contains a :ghi key that has a nested object as its value:

2.4.6 :023 > x= {abc: 1, def: 4, ghi: {ye: 6, nm: 3}}
=> {:abc=>1, :def=>4, :ghi=>{:ye=>6, :nm=>3}}
2.4.6 :024 > x
=> {:abc=>1, :def=>4, :ghi=>{:ye=>6, :nm=>3}}

.to_yaml on its own will produce a string that will output with newline characters, like so:

2.4.6 :025 > x.to_yaml
=> “-\n:abc: 1\n:def: 4\n:ghi:\n :ye: 6\n :nm: 3\n”

To make this more useful, try puts along with .to_yaml

2.4.6 :026 > puts x.to_yaml

:abc: 1
:def: 4
:ghi:
 :ye: 6
 :nm: 3

5. x.method(:_____).source_location

(where :_____ is name of the method — as a symbol — you are trying to search for)

OK, so the ultimate secret weapon of Ruby debugging is this little-known method that will magically — and I mean magically — tell you where a method was defined. That’s right, I mean the actual line number itself.

2.2.5 :002 > a.method(:hello)
=> #<Method: Apple(Thingy)#hello>
2.2.5 :003 > a.method(:hello).source_location
=> [“/Users/jason/Projects/nokogiri-playground/app/models/thingy.rb”, 2]

Look, ma, take a peek into my hard drive and you would find that the hello method is actually defined on the file at the full path /Users/jason/Projects/nokogiri-playground/app/models/thingy.rb on line 2.

Like magic it works for Rails and Gem code too, and is invaluable when you are ready to dive into the APIs you are working with.

6. x.methods
By default this method will return a list of all of the methods on an object. Watch out because you’ll get all the methods on the ancestor chain too.

In older versions of Ruby, you could use this method to examine the instance methods that were defined on this class only (excluding the ancestors), but unfortunately this no longer works.

If you pass this method false, like so:

x.methods(false)

…things get more interesting: then you get only the class methods defined on this object’s class itself. (Remember in Ruby class methods are defined with self.)

7. brunofacca/active-record-query-trace

An excellent gem that’s still a non-optional workhorse in my development practice – especially when debugging a legacy codebase. This gem will display for ALL of your SQL queries where in your Ruby or Gem code the active record update commands are coming from.

Follow the instructions in the Gem to create an initialize file and set it up. My only tip here that adds to the docs is that you’ll want to set the number of lines:

ActiveRecordQueryTrace.lines = 10

I find that when debugging a problem in my own Rails app I want this set to a lower number (like 5 or 10) and when debugging a problem in Gem code or in Rails I need this at a much higher number (like 50 or 100).

8. flyerhzm/bullet

Understanding N+1 queries is a significant litmus test that sets amateurs from the professionals. Bullet is like a magic bullet – literally named so – for finding your N+1 queries.

Bullet is a great gem that you should install in either development or test, not in production. Often because it does add overhead to your speed, I install it but leave it configured so that it is turned off by default and any developer on the team who needs it can turn it on.

You CAN and SHOULD turn it on periodically too, to examine where your app is producing N+1 queries.

Here’s the catch with Bullet: Remember that Active Relation objects are created as chains of conditions before they get translated and executed as SQL. That’s why when you do this you must carefully consider

query = Country.where(name: “United States”)

When you do this in your Rails console, you will see it run the SQL right away.

2.4.6 :039 > Spree::Country.where(name: “United States”)
 Spree::Country Load (0.7ms) SELECT `spree_countries`.* FROM `spree_countries` WHERE `spree_countries`.`name` = ‘United States’ LIMIT 11

It only does this because of the ‘print’ effect the Rails console has on your objects. If you string another .where onto this object, when translated into SQL, ActiveRecord will combine the queries:

query = Spree::Country.where(name: “United States”); query.where(iso: “US”);
 Spree::Country Load (1.0ms) SELECT `spree_countries`.* FROM `spree_countries` WHERE `spree_countries`.`name` = ‘United States’ AND `spree_countries`.`iso` = ‘US’ LIMIT 11

The reason this is important is that to understand where your N+1 queries are coming from you need to understand when you are creating your Active Relation objects and when they are invoked. They are not the same place, although on the Rails console it makes you think it is one and the same. When you grok this, you will see why Active Record’s side loading (which loads a related set of objects in a single optimized query, taking the number of queries from N+1 to 1+1=2) is both efficient and can be tricky to work with, especially with objects that have many relationships.

Don’t be fooled: Side-loading is nearly always more efficient than N+1 queries. 

Bullet tells you where those pesky N+1 queries are invoked, but not where you are creating them. What you then need to do is trace your code (manually) to figure out where the queries are being created, which hopefully should be near in the code to where they are being invoked ( but in the case of complex filtering logic might not be).

Here you need to add the appropriate .joins(:____) to your code anywhere between when the objects are set up and when they are invoked by Active Record. Note that you’ll only want to join in those additional tables if they are actually used. If not, you don’t need the over head.

You’ll know you’ve solved your N+1 queries because you won’t see them output in your Rails log, and they’ll disappear from the Bullet code.

9. better_errors

Since Rails 4 adopted a near identical default, this used to be more interesting. For a Rails 3 app it can bring your error crash console up to Rails 4 standards.

10. Introspect, Introspect, Introspect but remember Ruby’s last-line quirk

Always look at what you’re doing. Drop into your debugger, look at your variables, clone & freeze them, look for race conditions, look for flip-floppers, watch out for your own confirmation bias. Remember that when in the debugger or on the Rails console and you type a SINGLE VARIABLE and HIT RETURN, the console will interpret that action as-if you had called .inspect

2.2.5 :007 > a
=> #<Apple id: nil, created_at: nil, updated_at: nil>
2.2.5 :008 > a.inspect
=> “#<Apple id: nil, created_at: nil, updated_at: nil>”

In some cases, the act of inspection actually changes the object (like in the case of an Active Relation, in which case it invokes the query), so keep that in mind (we might call this the “observer effect” in software development.)

Categories
Programming

Disable Same Origin Policy in Chrome

For macOS

open -a Google\ Chrome -args -disable-web-security -user-data-dir

Linux

chromium-browser -disable-web-security -user-data-dir=”[some directory here]”

For Windows

chrome.exe -disable-web-security

See this SO post

Categories
Programming

Announcing Nonschema Migrations

After many years, I decided that my gem nondestructive migrations needed a facelift. It had some cruft I didn’t want, was packaged in the wrong way, and Alex Chaffee brought up a legitimate objection to the nuance of its name: the discriminating factor that differentiates these migrations is not destruction, he argued, and so the gem is likewise misnamed.

For all of these reasons, and to fix a problem with bundler’s ability to smoothly upgrade, I am renaming and replacing nondestructive migrations with nonschema migrations.

As well, this approach implements different versions of this gem for each different version of Rails, which became necessary when

ActiveRecord::Migration

was renamed to

ActiveRecord::Migration[X.X]

where X.X is the Rails version number. This strategy will allow bundler to easily pick up the new version of this gem when you upgrade Rails, and in the future I will release this along with Rails’ own release schedule.

https://github.com/jasonfb/nonschema_migrations

Categories
Programming

Heroku with a SSL/TLS purchased from SSLRenewals – BYO Instructions

Buy yourself a “RapidSSL Certificate” at SSL Renewals. After you place your order, they may not send you an email, so log in and go to “Orders” and look for the “Generate” button

You must have access to admin@ your domain to proceed. They will send an email to verify your domain.

Generate a private key and CSR on your computer. (see instructions for mac OS or Windows)

Submit the .crt file, or certificate signing request, to SSL Nenewals. select for Web Server “Apache + MOD SSL”. Copy & paste the crt file into text box.

Use DNS authentication. It is easiest. You will need to set a TXT record on your domain name.

For “Please select the Secure Hashing Algorithm (SHA) you would like to use.” choose “SHA2-FULL-CHAIN”

Follow the instructions to create a TXT file. For the apex (root) domain, it should have no subdomain (leave blank). For a subdomain, it will instruct you to create a “domain” for a special content string.

The string is provided in what SSLRenewals calls “Alias Name”. Copy & paste this into into the “content” setting of your new TXT record (do this in your DNS manager)

At the end of the process, go to the SSL Renewals tab, find your order, and find the “Download Certificates” button. You will receive a folder called Certs-12345678

In it there will be several files:

CACertificate-INTERMEDIATE.cer
CACertificate-ROOT.cer
PKCS7.p7b
ServerCertificate.cer

You want to open in a text editor these three files: CACertificate-INTERMEDIATE.cer, CACertificate-ROOT.cer, ServerCertificate.cer

create a new file that contains the concatenated version of these three files, in this order:

ServerCertificate.cer
CACertificate-INTERMEDIATE.cer
CACertificate-ROOT.cer

Name your new file “-CHAINED” to distinguish it from the others.

Log into the Heroku web interface. Make sure you have deployed at least once.

On the command line, remove the automatically added Heroku SSL using

heroku certs:remove -a your-app-name

Verify with
heroku certs -a your-app-name

Back in the Heroku web interface, go to Settings > Configure SSL.

On the first screen, the “public certificate” is the new concatenated file you created. On the second screen the “private key” is the key you generated when you created the key & CSR.

(Reminder: never share your private key except with your web server provider.)