Today I Learned

Tue, 30 of May 2017

Ruby’s defined? method is useful, but the syntax is a little surprising at first glance!

# These two are similar, but you call them different
defined? @whatever # call with the actual identifier
instance_variable_defined? :@whatever # call with a symbol of the identifier

defined? returns a string of what identifier is. In this case, nil or "instance-variable".

instance_variable_defined? returns a bool.

When nil is an acceptable memoized value, I often reach for a pattern of.

def whatever
  return @whatever if instance_variable_defined? :@whatever
  @whatever = some_expensive_computation
end

For tersness that communicates just as much, this could become

def whatever
  return @whatever if defined? @whatever
  @whatever = some_expensive_computation
end

Wed, 31 of Aug 2016

Today I needed to re-raise an error in ruby, but change the error message slightly. It turns out this is baked right in to the use of raise!

do
  # something that raises
rescue => e
  raise e, "This is my modified message"
end

The docs!

Tue, 03 of May 2016

import statements can be picky When using ES2015. With the variety of Babel plugins and configurations it’s easy to have some technically invalid syntax that compiles just fine in that configuration.

// family.js
export default {
  george: "Grandpa",
  michael: "Dad",
  maeby: "Cousin",
}

// uses_family.js
import { maeby } from "./family.js"

I don’t know what plugin I was relying on but previously this import statement worked. It turns out that destructuring off a default export is not actually a thing.

Option 1:

// family.js
export const george = "Grandpa"
export const michael = "Dad"
export const maeby = "Cousin"
export default { george, michael, maeby }

// uses_family.js
import { maeby } from "./family.js"

Option 2:

// family.js
export default {
  george: "Grandpa",
  michael: "Dad",
  maeby: "Cousin",
}

// uses_family.js
import Family from "./family.js"
const { maeby } = Family

Wed, 09 of Mar 2016

Rails will save associations by default. If you build an in-memory representation of a record that’s not intended to be saved with a call to update you need to do one of two things.

  1. Set autosave to false. Example: has_one :other_thing autosave: false.
  2. Don’t associate the built record with the object you’re saving

This default behavior manifested itself because I was doing something of the form:

class Thing
  has_one :other_thing # 1. Use autosave: false

  def optimistic_version_of_other_thing
    OtherThing.new(thing: self) # 2. don't associate the record with self
  end
end

thing = Thing.last
thing.optimistic_version_of_other # I don't want this persisted
thing.update(anything: "else")

Wed, 27 of Jan 2016

I’m almost always wanting to add configuration hooks to Rails engines when I build them. Up to this point I’ve never taken the time to figure out the most succinct way to provide configuration hooks. It turns out that it’s much simpler than I even imagined.

module MyGem
  class Engine < ::Rails::Engine
    isolate_namespace MyGem

    config.my_gem = ActiveSupport::OrderedOptions.new
    config.my_gem.some_setting = true
  end
end

That’s it! Setting config directly in the class definition will expose the configuration in the consuming Rails application.

Thu, 07 of Jan 2016

Today I re-learned about ActionController::TestCase. It’s pretty common to send the request parameters in as the second argument. What I always forget is that the third and fourth parameters represent the session and the flash respectively.

test "something that depends on the session and the flash" do
  post :create, { always: "money" }, { in: "the" }, { banana: "stand" }
  assert_equal params[:always], "money"
  assert_equal session[:in], "the"
  refute_equal flash[:banana], "stand" # because the flash will have been flushed!
end

Mon, 07 of Dec 2015

Multiple calls to ReactDOM.render can be a super powerful tool. Given a state-ful component Counter

// Initial render into document.body
React.render(<Counter count=0 />, document.body)
// => { state: { count: 0 }, props: { count: 0 } }

// Something internal happens that changes state to 50
// => { state: { count: 50 }, props: { count: 0 } }

// Re-render without unmounting into document.body
React.render(<Counter count=100 />, document.body)
// => { state: { count: 50 }, props: { count: 100 } }

In many use-cases, flux is introduced to distinguish between props and state. If props are changing on the server, this is a nice light-weight way re-render everything, while maintaining some client-side state. (Super helpful in rails in my usage)

Fri, 27 of Nov 2015

While playing with webpack in a Rails environment, there are still some variables I want to expose to the window. I came up with this 2-liner to treat exports from the top most bundle as global variables!

export { Whatever, You, Want }
Object.assign(window, exports)

Sat, 14 of Nov 2015

When using elm make, the output is determined by the extension.

elm make Main.elm --output main.html # generates html
elm make Main.elm --output main.js # generates js

Mon, 09 of Nov 2015

Put it in a Rakefile. Why incur the overhead of ruby my_script, when you can just type rake? It takes a little more time to write, but being able to return to a small folder and type rake -T by convention makes you faster in the long run.

Tue, 29 of Sep 2015

You are not allowed to complain about what you are not willing to confront. I saw that in a tweet a while ago, and it is a good word.

Prefixing methods that will change what is on output to the screen with render_ sounds verbose, but it has been helpful as I’ve started to use it more. Another React convention that is informing other areas of development.

Wed, 12 of Aug 2015

CORS is real. The part that really tripped me up, is the preflight OPTIONS request.

You can handle this options request in Rails with a nice routing constraint.

match '*', to: 'cors#handle', via: %i(options)

Then set your Access-Control-[Whatever] headers accordingly, and you’re in business.

Wed, 22 of Jul 2015

There are a lot of ways that payment can fail. Thankfully, Stripe provides ways to trigger almost every conceivable failure. And they put the credit card values that will trigger these failures into a handy doc.

It’s important to remember, some of these failures will occur when attempting to get a Stripe token. Others will fail when attempting to use the Stripe token.

Mon, 20 of Jul 2015

When using Bugsnag within a Rails app, you must use the before_bugsnag_notify macro within your ApplicationController (or similar) to add custom info. I tried to be clever, using the Bugsnag.before_notify_callbacks manually in an initializer. This didn’t work. My assumption is that Bugsnag.before_notify_callbacks.clear is called somewhere internally in the Railtie.

It pays to read the Bugsnag ruby docs.

Mon, 22 of Jun 2015

In Rails’ Mailer Previews, you can append .text to the URL to view the text version by default. Way better than reloading, and having to select text from the dropdown!

Mon, 15 of Jun 2015

Rails.application.routes.url_helpers can be used to access your URL helpers from anywhere.

Wed, 20 of May 2015

In JavaScript, document.activeElement gives you the active element. How did I never know this?

Tue, 21 of Apr 2015

<<-SOMETHING.strip_heredoc in Ruby, to strip the heredoc, and align to the current level of indentation. Doc

Tue, 03 of Mar 2015

When working in Ruby, JSON.parse(payload, symbolize_names: true) will automaticaly symbolize the names.

Mon, 02 of Feb 2015

There is no magic for Rails’ enum in fixtures. If you want to use the string value (which is the entire point of using the enum), you need to ERB it up. Something like

michael:
  name: Michael Bluth
  occupation: <%= Person.occupations[:actor] %> # because 'actor' won't do it

Fri, 09 of Jan 2015

You can use %i[some symbols] in ruby to generate [:some, :symbols]

Tue, 25 of Nov 2014

You can use reorder on an ActiveRecordRelation to replace all existing order methods. It’s super useful when merging scopes that may have imported their own ordering that is no longer applicable.

Mon, 24 of Nov 2014

Study the docs. As an example, there are so many methods on Enumerable that you can leverage to eliminate temporary variables. Don’t spend all your time reading the docs, but every once and a while it’s good to review what’s already built in the standard library that you don’t need to re-invent.

If you’re looking up a record by anything other than the primary_key, don’t accept arbitrary arguments. Lazily looking up a record is great, but if you’re using something like

def destroy_do_dad(expecting_an_id_but_an_object_was_passed_in)
  DoDad.where(foreign_system_id: expecting_an_id_but_an_object_was_passed_in).destroy
end

you have a huge vulnerability. #to_param, will come into play, and you’re now potentially finding a completely arbitrary record and destroying it.

Fri, 21 of Nov 2014

Let the database do all of the heavy lifting for counting your ActiveRecord objects.

Record.pluck(:owner_id).each_with_object(Hash.new(0)) { |id, counts|
  counts[id] += 1
}

Sums up the number of records for a owner in Ruby. The same can be achieved via ActiveRecord.

Record.group(:owner_id).count

Mon, 10 of Nov 2014

When accessing the Rails flash messages, use strings instead of symbols. I thought it was a HashWithIndifferentAccess…but it doesn’t appear to be.

Sat, 08 of Nov 2014

Responding to http in Go on Dreamhost is pretty easy. The trick is to use FactCGI to serve it up.

I did this via a trivial conditional for my setup of developing on OSX, and deploying to Linux.

if runtime.GOOS == "linux" {
  fcgi.Serve(nil, nil)
} else {
  http.ListenAndServe(":2112", nil)
}

To cross-compile to Linux, you use the Go runtime flags.

GOOS=linux GOARCH=386 go build

Fri, 07 of Nov 2014

I was reminded how evil DST is. It’s just the worst. Writing tests around it is the best. Just a reminder that 2am-3am on March 8, 2015 DOES NOT EXIST.

Thu, 06 of Nov 2014

Some random commands from tinkering with Vagrant today:

JavaScript Array’s map function takes a optional second argument, of what to bind to this.

Wed, 05 of Nov 2014

Gulpfiles. I don’t know what I learned about them, but I helped a friend troubleshoot why gulp.watch() and gulp-sass combined to produce a Segmentation Fault 11. Something with libsass, and rolling back the node-sass version fixed it.

Computers.

Tue, 04 of Nov 2014

Gourmet Service Objects is a post worth returning to from time to time. After slogging through some code to understand what it did, I wrote it into a service. The code wasn’t substantially different, but the fact that it had a name as first-class citizen instantly made it easier to understand.

Because my dudepal @jabronus gave me an SVG of my avatar, I started learning how to use SVG in the browser. I even made my avatar blink using CSS animations. Supes cool.

Mon, 03 of Nov 2014

git log --pretty=oneline gives you the one-line per a commit output.

git log --pretty=format:"%an" gives you formatting on commits. All the interpolations available are listed in the man git-log under “PRETTY FORMATS”.

attr_readonly exists in Rails for making fields immutable. But we’re in Rails, so we don’t use big words like immutable, we use readonly. Caveat: you can still change the values in memory, which has other consequences around validations and any derived values.

Wed, 29 of Oct 2014

Having opinions is more fun that trying to please everyone. Engage in helpful debate with reasonable people. Change your mind when presented with new data that should change your mind. Attack the problems together. Defend your teammates, not your opinions.

Tue, 28 of Oct 2014

Don’t use Ruby’s or, and, or not keywords. Just don’t. It’s not worth the hassle of slightly different behavior. Refer yourself to the Community driven ruby style guide often.

Thu, 23 of Oct 2014

You can be incredibly productive, but feel unproductive. Fixing lots of small bugs leads to this. Keeping a list of everything completed such as Trello helps you remember that you’re making a lot of small progress when it feels like you’re not making any large progress.

There are many ways to write even the simplest statement.

# Whitelisted arguments.  # Which is most readable while being concise?

# 1
trusted = %w[approve reject].find { |i| i == untrusted }

# 2
trusted = (%w[approve reject] & [untrusted]).first

# 3
trusted = %w[approve reject].include?(untrusted) ? untrusted : nil

# 4
trusted = case untrusted; when *%w[approve reject]; untrusted; end

Wed, 22 of Oct 2014

Aggressively eliminate state. After working with ReactJS for a bit, I am starting to see the merits of eliminating state. I’m even beginning to like methods prefixed with get and set. Eliminating state means eliminating side-effects.

Writing adolescent JS code seems to lead to better JS code. What I mean by adolescent code, is that it refuses to take responsibility. It lets somebody else own the state of the world. All it does is ask for values, and do something with them.

If you want to launch Vim from a Ruby script, use system 'vim'. Backticks won’t work, because they want to consume STDOUT. exec takes over the process, so you couldn’t do work afterwords. system works.

Tue, 21 of Oct 2014

Take breaks.

Lately, I’ve been taking breaks. Today I didn’t. And at end-of-day, the difference in energy level left for friends & family is substantially depleted.

Mon, 20 of Oct 2014

Small changes are easier than big changes. Renaming things seems like a huge win, but when you’re renaming big things, small subtleties will emerge. These pitfalls are easier to see in others’ proposed changes than your own.

If you’re going to rename something, have a good purpose for it.

Look for the dumb solution. Sometimes refactoring isn’t needed yet. You don’t know enough about the problem to find the better solution, yet.

Thu, 16 of Oct 2014

It’s important to know how to revert a commit, because sometimes you accidentally commit strait to master.

If you caught yourself before pushing upstream, you’re good. Just

git checkout -b temporary
git branch -D master
git checkout master

This assuming it automatically pulls master back down from upstream, which is my default setup.

If you did push upstream, you’ll basically want to create a commit that reverts the latest commit. Hopefully it’s only one commit.

git format-patch -1 HEAD
git apply [newly_created_patch_name] -R

Wed, 15 of Oct 2014

You have to mull through a lot of terrible names, and iterate on terrible code to arrive at a consistent, reasonable API. Today I was building an ActiveSupport::Concern whose purpose will be to cache attributes that are expensive to compute. The names of the methods changed a handful of times. And even now they may not be finalized.

I left the code for a few hours, and returned to it with a fresh set of eyes. The names were terrible. Their implied meaning was confusing. But because of this gap, I was able to see some of of the consistent shortcomings. I also saw patterns emerging, that lead to a more consistent API for the final iteration (of the day).

Tue, 14 of Oct 2014

I started making a before_filter that would redirect a request from a bot. After returning to the code, I decided it would be better to rescue_from SomeCustomError, with: :what_was_previously_a_before_filter so that the code did not have to run on every single request. This probably amounts to minimal performance gains in terms of actual execution time, but I think it brought clarity to the code by having the happy path occur first.

Taking the time to organize your folders/files into something predictable needs to be done quickly when you’re working with branches of code. Every divergent branch means a delay in making it happen.

Mon, 13 of Oct 2014

Reminded of a proposal I made long ago. For responsive design, start at one size, and head in one direction, using either min-width or max-width, but not both.

I spent time today moving some behavior of a model into a concern, specific to that model. Rather than putting it into app/models/concerns/person_pending_request_count I put it into app/models/person/pending_request_count. I liked this change, because it communicated that only Person should be using this. It’s not a general mixin, though it could easily become one. Then in the person class, I just included it with include Person::PendingRequestCount.

Tue, 30 of Sep 2014

Rails UJS’ ajax:success and ajax:error only apply to XHRs originating from a data-remote="true" source. If you’d like them to apply to all XHRs in your page or application, you’re gonna have to wire that up.

In slim, you can use <, > or both after your tag to add leading or trailing whitespace, respectively.