A reintroduction to TDD

So I’ve been writing a forest.

And I’ve been writing tests for it.

It’s been a lot of fun, and I’ve gotten a second wind on the project in the past couple weeks. I’ve written a bunch of code!

However, a lot of features have yet to be implemented. The code I’ve been writing has largely been RSpec, which you can see in this PR. As of right now, most of those tests fail, which isn’t a mistake.

I’ve been TDDing the forest a lot. Not everything, but a lot of things. Professionally, I’ve always regarded TDD like veganism: yes, you can make a lot of great arguments in its favor that I cannot honestly counter, but I just can’t imagine myself actually following through with it. So while I’ve historically written tests, they usually don’t come first.

Good arguments against TDD exist, and I certainly don’t think it’s the be-all and end-all. Some people are really off-puttingly dogmatic about it. But I’ve discovered, personally and for the first time, reasons to do it.

  1. It’s meditative. I’m not going to substantiate this because it’s very subjective, but there. It feels good.
  2. Non-passing tests act as a very difficult-to-ignore to-do list. I have a bunch of to-do lists devoted to the forest, including Trello, post-it notes, and #TODO and #FIXME comments scattered throughout my code (which is great for indelibly affixing a task to a particular line), but nothing encourages me to act more than a yellow or red dot in a sea of green.
  3. I’m not on a timeline. TDD does take longer up front, at least in my experience. Maybe one day I’ll get good enough at it that that won’t take any longer than writing the other way around. Of course, professional projects usually are on a timeline, so this reason might not convince your boss.
  4. It makes my coding intentional. Every time I write a method, it is to get a particular behavior. If I start building a workaround that goes off into some space not covered by the spec, I feel it immediately.
  5. It makes my code prettier. This is also subjective, but I think it does.

I’ve definitely complained about TDD before, because if you are in a time crunch it can feel very, very slow. “What do you mean I have to write code before I can write my code? This is bull!”. But this forest is a nice place. There’s time to do things right here.

Advertisements

Leave a comment

Filed under code, Uncategorized

Layouts with JBuilder and rails-api

Rails-api has been merged into normal rails, but this is what I’m working with. I’m fairly certain the process will be identical for someone using the new setup!

I wanted to build an API whose responses had a reusable wrapper, just like an HTML response can be wrapped in a reusable header and footer. The process to do this is easy, but not totally neat, for reasons I’ll get into.

Anyways, here’s what you need.

# app/controllers/application_controller.rb
class ApplicationController < ActionController::API
  include ActionController::ImplicitRender
  include ActionView::Layouts
end
# app/views/application.json.jbuilder
json.head("This will appear in every response")
json.body(JSON.parse(yield))

JSON.parse(yield) stands in for the normal yield you are used to when rendering HTML with erb or what have you.

This code is not ideal because the use of JSON.parse(yield) means that the body of your JSON response is parsed twice. It is hella inefficient.

I’ve done a fair amount of research, and it seems this is simply a limitation of JBuilder. This Github conversation confirms this. If anyone hears of a good solution or workaround, please let me know! And I think ActiveModel::Serializer is not the way for me, but I would love to be convinced!

I suppose you don’t even need to include ActionController::ImplicitRender but it has made my life a whole lot easier! It means you don’t have to specify which jbuilder file to load at the end of a controller; Rails will try to figure out which one based on naming conventions as it does with normal erb views. If your goal is to try and get rails-api to behave like Rails but with JSON instead of HTML, then you need ImplicitRender.

Leave a comment

Filed under Uncategorized

The forest is better!

Thanks to an unexpected PR from a friend, the forest is in good health. The polymorphism issues I was having in the last blog post are all but solved, and all tests are passing. There need to be *more* tests, for sure, but things are looking much better now.

The Location#objects helper hack method still exists, but that’s okay because all the other ActiveRecord helpers I’m used to are back. Wolf#location and Location#wolves both work out of the box. Trogidu, the writer of the PR, saw to that. He also found a couple pluralization issues! I suspected those would turn up, but I was missing the extra pair of eyes!

I’m not working on this project as frequently as I ought to, but every time I put an hour into it I’m astounded by the amount I learn. Trogidu’s PR introduced me to inverse_of, which I somehow had never heard of before. Plus, it made me feel all warm inside that someone I haven’t spoken to in a while took enough interest to help me write code!

Also, the dev blog seems to be following a pattern of humanistic status update post followed by a more specific post on a particular technical thing. I think it’s a good pattern. I’ll follow this one by a quick post on JBuilder layouts.

Leave a comment

Filed under code, Uncategorized

Reverse polymorphism, aka polymorphic join.

I’ve built and implemented a bunch of stuff I’m excited about with the forest, but this post will focus on one aspect: reverse polymorphism. I don’t have it working perfectly yet (EVEN THOUGH IT SHOULD BE WORKING WHAT THE HECK) but I think it is the solution to the craziness I had been encountering with the ActiveRecord associations I need. The best part about it is that it’s not Single Table Inheritance (STI), another potential “solution”.

I’ll describe the problem that needed solving, and how this solves it, and why it’s awesome. Then I’ll describe what’s not quite working yet, the workarounds I’m using, and plea for help from those more knowledgeable.

First, though, here is the gist which introduced me to RP in Rails. I’ll explain how it works in a bit.

The forest’s fundamental blocks are Location objects. They’re normal AR objects. Locations have_many objects, and objects can be multiple kinds of things. The toy examples in the app right now are Wolves and Trees. Wolves can move around, and Trees can’t, but both have_one location.

Ideally, I’d like to be able to call Location#objects and receive a list (an ActiveRecord::Relation) that looks like [wolf1, wolf2, tree1]. I’d like this to work at the ORM level (i.e. I want ActiveRecord to do it for me) and not have to write that scope or method myself.

Polymorphism to the rescue

This sounds like a job for polymorphism, but it’s not a classic case. The normal case is an object being able to belong_to one of multiple kinds of things. I need an object to be able to have_many of many types of things.

It took me a day to grok this, but the solution is a join table. In my case, a LocationObject.

  • Location has_many LocationObjects
  • LocationObjects (the join table) have a polymorphic have_one association with Wolves, Trees, etc.
  • Wolves and Trees have_one LocationObject as object
  • Location has_many Wolves and Trees through LocationObjects.

So the associations are all set up. Location#location_object AND Wolf#location_object work.

Someone might say “well Vincent, this is totally more complicated than Single Table Inheritance!” and I would say “ugh come on”. Classical inheritance sounds like a great solution until you see what it does to your database. Even though Wolves and Dogs intuitively could both inherit from a hypothetical Canid class, which inherits from a Mammal class, and so on, this means that everything that inherits from the base class shares the same table. Every time a single child needs a new attribute, it gets added as a column to the ancestor table.

Because the forest will hopefully have a widely-branching tree of life, this is not the proper solution for this project. That single table would probably get huge, and track information for everything from number of leaves to most recent meal. Or whatever. It would be painful.

To keep shared behavior manageable, I’m going to be relying on composing with modules. To continue the previous example, I’d have a Mammal module, and a Canid module, both of which would get mixed in to the lowest-level Wolf and Dog classes. I’m keeping these modules in lib/.

Hell yeah. This seems like the perfect solution.

The Problem

The problem I’m having is the join. Location#objects and Wolf#location do not work. I’ve created the following fix, which I really don’t want to be permanent:

# app/models/location.rb
... 
# FIXME
def objects
   self.location_objects.includes(:object).map do |location_object|
     location_object.object
   end
 end
...

While it DOES avoid a potential N+1 issue, I’m pretty sure ActiveRecord is capable of doing this for me. And as long as this is a pet project, I want the code to be beautiful. I’ve even got failing tests demonstrating this behavior.

Another symptom of this is being unable to create the objects as I’d like. Wolf.create(name: "joe", location: some_location) just doesn’t work!

The plea

WHYYYYY?

It may be the ActiveRecord just doesn’t handle those helper methods over polymorphic join tables. But the writing I’ve seen online doesn’t suggest that.

I have a terrible fear that this is a naming or pluralization issue. ActiveRecord’s errors hint at that: Could not find the association :location_objects in model Wolf.

Anyways, here’s the relevant code. I invite feedback!

location.rb
location_object.rb
wolf.rb

1 Comment

Filed under code, Uncategorized

It’s just an API for now.

Alright, episode two in the development blog of my little forest project.

Here’s the forest code.

If you look at my Github contribution tracker, you’ll notice a month gap there. There’s a couple reasons for that, but the relevant one is that I was trying to work on the front end. I was learning how to get React + Redux running with Webpack and Babel and all that fun stuff. I was learning about modern JavaScript development and deployment.

I spent a couple weeks following Survive.js’s awesome Webpack and React tutorial. I don’t think I will continue down that road for right now. I’m just doing Ruby for now. I am capable of learning the modern front-end, but it will probably have to be with more time or mentorship. The complex mixture of compilers and languages and package managers is too much for me to handle at the moment.

So that’s that. I’m building an API for now. With Ruby on Rails. Once it’s fleshed out I’ll start looking at a front-end. I’d love for it to imitate the style of text adventures like Zork, except the world is dynamic and alive. Every movement (e.g. north, south) would constitute an API call. Clearly, web technologies are not the best way to build this. I think Z-machine is the way to go for that.

So that’s a status update. I’ll write a follow-up post real soon re: technical issues on the back-end.

Leave a comment

Filed under code, Uncategorized

File Upload Regression in Safari for iOS

Hi readers! Please let me know if I’ve made any mistaken assertions in this post, or if I have missed any key points! The tone of this post is fairly combative due to my frustration, but I’m eager to continue this discussion in a civil way.

Anyways.

It’s currently in style for developers to complain about the direction of Apple’s design. From my perspective, the magnum opus of this growing body of work is How Apple is Giving Design A Bad Name, by former Apple designers Don Norman and Bruce Tognazzi. A quick Google (or DuckDuckGo, really) search will show you that they’re not the only ones with this opinion. There is so much to write about: Apple’s narrowminded focus on aesthetic over function; the staunch refusal to include a hardware back button; the frustration that Google seems all too eager to follow their lead.

A caveat, though: I really like Safari for OSX. The Webkit team does a great job of implementing and supporting modern web standards. I don’t buy into the Safari is the new IE thing. Also, a friend of mine works on that team and I don’t want to malign him.

So I’ll just focus on one personal story / rant on a particular subject which I don’t think has been covered: Apple kneecapping file upload in Safari for iOS in what I’m pretty sure is an attempt to make money selling storage space on iCloud.

I’m currently on the job market as a full-stack web developer (WINK WINK), so I went to a coffee shop with the intention of applying to a couple jobs, maybe send off some emails and resumes. I didn’t have my laptop with me, but I figured that the iPhone is a reasonably powerful computer and can certainly handle browser form submissions. The small screen compared to a laptop would be frustrating, but something I could deal with for a couple hours.

Fundamentally, I needed to go to a website, fill out a form, upload a resume, and submit that form.

This is not a weird use case. This has been a feature of web browsers since, I don’t know, probably 1996 or something. Here’s the IETF “experimental” specification for HTML file upload in browsers, published in 1995.

So here’s what happens when you try to upload a file:

IMG_1045

The menu that appears when I tapped “upload a file”.

And here’s what happened when I tapped the “iCloud Drive” option:

IMG_1046

What is allegedly in my iCloud drive.

 

Mind you, I have the relevant PDF stored on my phone locally, but I couldn’t upload it unless it was a photo. It’s living in a Notes document, which is the only way I could figure out to download it. I briefly considered taking a screenshot of the PDF so that it would be uploadable as a JPEG. Also, all my Notes are backed up to iCloud automatically, but it’s clearly not in a form that I’m able to access.

I spent an hour trying to figure out how to get the PDF (first) ONTO iCloud from my iPhone, and (second) down FROM iCloud into the browser. The first thing seems impossible. Apple support directed me a useless iCloud help page. In the end, I gave up and found a desktop computer, which enabled me to complete the task in a few seconds.

Apple. My phone is a computer. It has 30 or so gigabytes of local storage space that I already paid extra for, and you’re now scheming to get me to use up my limited cloud storage so that I can pay you for more. In doing so, you have regressed a 20 year old feature of browsers.

And I still don’t have a hardware back button. I would be surprised if I ever buy an iPhone again.

Leave a comment

Filed under Uncategorized

Gratitude

I write this kind of post every year or two. I write this kind of post every time I feel the need to.

I’m having a hard time right now. I am unemployed, and I had an exciting romantic relationship end before it could really begin. I feel, generally, down. Bummed. Sad, and a bit hopeless.

Mind you, I don’t think I am hopeless, but that’s really how I feel.

While I respect my struggles, I also want to take the time to respect the positive things I do have. I can’t list everything, but these are some pretty major ones.

  1. Family. I am so, so, so lucky to have the family I have. Describing them fairly would take a novel. I am grateful for them.
  2. Friends. The long distance friends I left behind physically when I moved here, and those that I have found since moving here. So many people have shown me kindness. I’m floored and grateful.
  3. My self. I’m a good person. Sometimes I have trouble believing that I’m deserving of love and success, but I really am. I’m worth the effort. I’m also cute.
  4. Portland. I have never felt more at home than here. I am so happy to have found it.
  5. My physical health. I’m working good, physically, and that’s not a given.
  6. My mental health. I have the gumption to get up and work, train, job hunt, write music, whatever. I am emotionally intelligent. I am not the perfect picture of mental health; my anxiety can be quite controlling at its worst, and I don’t *always* make it out of bed before noon. But I’m more than okay.
  7. My savings. They won’t last forever, but I have the money I need for rent and food.
  8. Unemployment insurance.
  9. My house. I rent it, but it’s my place.
  10. My privilege. I am granted many systemic advantages because of my age, gender, and race, among other things. “Grateful” is the wrong word to describe how I feel about it, but I note its large and usually positive effects on my life.
  11. My things. I have some possessions that really help me, e.g. my bike, my guitar, my computer, my bed, my clothing. I’m glad about those.

The first three are, like, paramount. For them I am not only grateful, but joyful.

Having written this, I feel better. I don’t feel not sad, but my emotions will always be complex. That won’t end. I feel better having some positive perspective.

Leave a comment

Filed under Uncategorized