<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Preston St. Pierre</title>
    <description>Preston St. Pierre&#39;s website and blog. Now powered by Jekyll!
</description>
    <link>http://tarential.com/</link>
    <atom:link href="http://tarential.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Thu, 02 Feb 2017 13:56:07 -0800</pubDate>
    <lastBuildDate>Thu, 02 Feb 2017 13:56:07 -0800</lastBuildDate>
    <generator>Jekyll v3.0.1</generator>
    
      <item>
        <title>Getting Things Done Stress-Free Style</title>
        <description>&lt;p&gt;Do you know what you should be working on right now? Are you sure? One hundred
percent absolutely sure? So certain that your mind doesn’t even plague you with
the thought that maybe there could be something more important for you to be
doing right now?&lt;/p&gt;

&lt;p&gt;If so, you don’t need to read this blog post. I’m speaking to the many people
out there who, like my past self, have so much they need or want to get done
that they suffer from the stress of not &lt;strong&gt;really knowing&lt;/strong&gt; what to work on. I
compensated for this problem by simply choosing what I thought was the most
obvious task and sticking to it, but that was effective neither at relieving the
stress nor at getting the right work completed.&lt;/p&gt;

&lt;p&gt;It took a while to realize. I was struggling at the edges of the problem. In my
conscious mind, I simply had too much to do. I didn’t have time to do it all.
This was causing me stress. It seemed simple enough, and that viewpoint sufficed
to motivate me to work harder in at attempt to complete all the tasks. That
solution was obvious, of course.&lt;/p&gt;

&lt;p&gt;It worked for a while. Unfortunately, it’s a sad fact of reality that we have
limited time and there are virtually unlimited things we could be doing. The
harder I worked, the more behind I was getting. My to do lists were a joke since
they kept getting longer. I was so overworked and stressed out that I started to
miss deadlines, snap at coworkers and be uncommunicative.&lt;/p&gt;

&lt;p&gt;This is unacceptable behaviour at
&lt;a href=&quot;http://predictablerevenue.com&quot;&gt;our workplace&lt;/a&gt;, even from a cofounder. My team
voted to send me on vacation for a month to get my shit together. They locked me
out of GitHub and off the production servers and told me to come back when I
could play nicely with others.&lt;/p&gt;

&lt;h4 id=&quot;the-temper-tantrum&quot;&gt;The Temper Tantrum&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/images/crying-baby.jpg&quot; class=&quot;inline-right&quot; /&gt; I was devastated.
&lt;strong&gt;How could they do that to me?&lt;/strong&gt; I was regularly putting in over 80 hours a
week!  I’d committed more code than any other developer! I was always the guy
who picked up the slack when there was nobody else to do it! After I stopped
ranting and raving to my girlfriend about how unfair life is, I took a moment to
think about what I was doing wrong instead of what I was doing right.&lt;/p&gt;

&lt;p&gt;Nobody was mad at me because I wasn’t working hard enough. Nobody thought I
didn’t spend enough time programming. Nobody thought I left them with the hard
tasks and picked up the fun ones for myself. Those were all important, but not
the area where I was lacking.&lt;/p&gt;

&lt;p&gt;Despite working so hard, I had been taking on too much. People had expectations
of me and I would let them down. I would give estimates that didn’t come to
fruition. I’d promise to check on things and then forget about them. I would
refuse to consider people’s ideas about the future because I was too busy with
the day to day.&lt;/p&gt;

&lt;p&gt;I was concentrating on how much effort I’d been putting in. I should have been
concentrating on what I’d been putting effort into.&lt;/p&gt;

&lt;h4 id=&quot;all-about-priorities&quot;&gt;All About Priorities&lt;/h4&gt;

&lt;p&gt;It was the start of an important shift in thinking for me. I’d hit the limits of
what I could accomplish by sheer force of effort. I simply wasn’t able to get it
all done anymore. This lead directly to the very relevant question posed at the
start of this post: Do you know what you should be working on right now?&lt;/p&gt;

&lt;p&gt;It had new implications. Before, it was obvious. Pick something that needed to
get done on the project, anything, and just start work. After all, that is the
secret to hard work… working. However, realizing that not everything was
going to get done in time meant keeping a prioritized to do list. I’d tried this
in the past and never had much success, because “priority” always seemed to be a
complicated topic.&lt;/p&gt;

&lt;p&gt;For example, what if the business is about to go bankrupt and I need to get
funding to save it? That’s naturally the first priority. On the other hand, I
might have a task requiring me to prepare for a doctor’s appointment for
surgery without which I could die. Obviously my health comes first!&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Except, what if the first available appointment for surgery isn’t for 3 months
and the business won’t be able to make payroll in a single month?&lt;/li&gt;
  &lt;li&gt;What if it’ll take you two weeks in order to find funding to cover payroll?&lt;/li&gt;
  &lt;li&gt;What if you can’t start talking to your friends at the financing agency until
the end of the quarter next week?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As each variable comes to light we see that the priorities change. Furthermore,
they cannot be assigned just once as they change over time relative to each
other. Things get even fuzzier with items that have no due date, or items for
which the due date is artificial instead of externally imposed. What about
partially completed items? What about recurring tasks?&lt;/p&gt;

&lt;h4 id=&quot;the-checklist-manifesto&quot;&gt;The Checklist Manifesto&lt;/h4&gt;

&lt;p&gt;While I pondered this organizational puzzle, I was busy taking part in one of my
new self improvement priorities: Reading a new book each week (or listening to
one on audible). No, not novels; self help books in various flavors. I’d just
finished reading the &lt;a href=&quot;https://www.amazon.com/Checklist-Manifesto-How-Things-Right/dp/0312430000&quot;&gt;Checklist Manifesto&lt;/a&gt;
and was inspired by it.&lt;/p&gt;

&lt;p&gt;Accordingly, I started by making a checklist for all my household chores. I
quickly noticed that while “Wash Dishes” and “Wash Floors” both needed to get
done, the frequency wasn’t the same. I converted the checklist into a
spreadsheet that allowed me to log an entry every time I completed a task and
which showed me, based on a specified interval for each item on the list,
exactly when the tasks were next required.&lt;/p&gt;

&lt;p&gt;My apartment got cleaner and cleaner as I started to see the effects of regular
reminders of when tasks needed to get done. I began adding items that were not,
strictly speaking, chores. Practice guitar. Practice piano. Learn Cantonese.
Lift weights. Do cardio. Time and time again I noticed something… items on
that list got done regularly. I talked to my partner, Collin, about how awesome
this new idea was.&lt;/p&gt;

&lt;p&gt;Collin very politely refrained from laughing in my face as he told me I’d just
described part of what David Allen writes about in his book &lt;a href=&quot;https://www.amazon.com/Getting-Things-Done-Stress-Free-Productivity/dp/0349408947&quot;&gt;Getting Things Done: The Art Of Stress-Free Productivity&lt;/a&gt;.
When I read it for myself, I was amazed. Shocked. I couldn’t get through the
whole book without running off to start implementing it. I felt like a had been
converted. I wanted to shout from the rooftops how awesome this new idea was.&lt;/p&gt;

&lt;h4 id=&quot;getting-things-done&quot;&gt;Getting Things Done&lt;/h4&gt;

&lt;p&gt;What was it that had me so over the top excited? The simple idea that the thing
causing me the most stress in life was not that I had too much to do, but that I
wasn’t ever &lt;strong&gt;sure&lt;/strong&gt; I was working on the right thing at any given time. I had a
million different priorities pulling me in various directions at work, not to
mention personal goals and responsibilities. Keeping them all inside and relying
on my subconscious mind or requests from coworkers to keep me on track was
causing me stress.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/light-bulb.jpg&quot; class=&quot;inline-right&quot; /&gt; Here’s an example:
Two of the four light bulbs in our main fixture had burned out. There was enough
light to see by, but there might not be if another went out. Should I go down to
the store and get new light bulbs? Almost certainly not, there are more
important things to do. Perhaps sometime in the future when I’m already going to
the store. So I don’t do it now, and I hope that when I’m at the store I’ll
remember.&lt;/p&gt;

&lt;p&gt;A lot of people have a list for things like this. It’s a common enough scenario.
Once you’ve written it down, it’s no longer a worry. You know that next time
you’re at the store you’ll get more light bulbs. That’s not a stressful task, it
just requires walking a few steps to the rack and putting them in your basket.
What’s stressful is keeping the thought in your mind: “I need to get more light
bulbs next time I’m out.” It’s even more stressful when you return from the
store without light bulbs, remember, and then kick yourself for forgetting.&lt;/p&gt;

&lt;p&gt;Many of the responsibilities in life are like this, it turns out. They’re not
particularly that stressful to do, and not getting them done is far less
stressful if it’s planned ahead instead of by surprise. If you “have to get some
light bulbs”, and your mind knows it is responsible for this, it will
continually nag at you that you “should be getting light bulbs”. Furthermore,
the longer you don’t, the more stressed out about it you will get. The opposite
is true if you write it down on that shopping list. You know that you always
take that list. You know that anything on that list gets purchased. Once you
write down “light bulbs”, it’s as good as done. You can forget about it.&lt;/p&gt;

&lt;p&gt;What’s happened here is simple: You’ve determined how important the task is (not
as important as your other work), when it needs to get done (next time you go to
the store), what action needs to be taken (purchase new bulbs), and what happens
in the event the task is not completed (the lights go out). Once you have that
all down in a trusted organizational system (ie the shopping list), it’s off
your mind.&lt;/p&gt;

&lt;p&gt;The aforementioned book, &lt;a href=&quot;https://www.amazon.com/Getting-Things-Done-Stress-Free-Productivity/dp/0349408947&quot;&gt;Getting Things Done: The Art Of Stress-Free Productivity&lt;/a&gt;,
is largely about getting to the state where every single one of your
responsibilities is written down in a trusted organizational system. At its
heart, the idea is that if you trust the system you don’t have to worry about
working on the wrong task. It sounds simple. It is. It works.&lt;/p&gt;

&lt;h4 id=&quot;organizing-your-life&quot;&gt;Organizing Your Life&lt;/h4&gt;

&lt;p&gt;The book goes into more details about how to make such a system work. Find that
some “to do” items are too long and keep getting pushed back? Replace all to do
items with single actions and group them together by project. Keep forgetting to
tell your coworker about the change you made? Group your to do actions by
context, be it a person or a place. Have trouble finding time to add items
properly throughout the day? Create an “inbox” system of items to add based on
rough form voice notes, texts or emails which you’ll transpose later.&lt;/p&gt;

&lt;p&gt;It should have been obvious, in hindsight. We’ve built many of these into our
own product. For example, &lt;a href=&quot;http://predictablerevenue.com&quot;&gt;Carburetor&lt;/a&gt; presents you with a
prioritized list of tasks, one at a time, organized by the type of work you’ll
be doing. If only I’d thought to apply something similar to my own life!&lt;/p&gt;

&lt;p&gt;I’ve added a bit of a personal touch to my version. Prioritization of tasks is
handled automatically via three fields: Impact, Urgency, and Due Date. Impact
indicates how much of a difference doing / not doing the task will make, urgency
indicates how much of a difference having it done on time / not on time will
make, and the due date reflects the day on which it should be completed. The
exact formula has been evolving over time, but in general a higher impact item,
more urgent, due sooner, will be higher priority.&lt;/p&gt;

&lt;h4 id=&quot;reviewing-open-tasks&quot;&gt;Reviewing Open Tasks&lt;/h4&gt;

&lt;p&gt;Now for the final, all-important step: Review! If you write your tasks down once
and then forget about them, you’ll know what you did. Your brain isn’t stupid.
It knows there are things you once wanted to do and haven’t thought about in a
long time. It can’t really remember what they all are, but it nags you about
them. In the inner recesses of your mind you feel it saying “what are you
forgetting?”.&lt;/p&gt;

&lt;p&gt;Your to do list can’t be the place tasks go to die. A to do list is for things
you intend to complete. Regular review, reprioritization, and pruning of the
list is the only way to ensure that you don’t have any nagging feelings that
maybe there’s something else out there more important than what you’re currently
doing.&lt;/p&gt;

&lt;p&gt;Yes, writing this blog post is exactly what I should be doing right now. Do you
know what you should be doing?&lt;/p&gt;

</description>
        <pubDate>Sun, 29 Jan 2017 19:55:00 -0800</pubDate>
        <link>http://tarential.com/organization/self-management/gtd/2017/01/29/getting-things-done-stress-free-style.html</link>
        <guid isPermaLink="true">http://tarential.com/organization/self-management/gtd/2017/01/29/getting-things-done-stress-free-style.html</guid>
        
        
        <category>organization</category>
        
        <category>self-management</category>
        
        <category>gtd</category>
        
      </item>
    
      <item>
        <title>The Importance of 15 Minutes: Bootstrapping with Idle Villagers</title>
        <description>&lt;p&gt;Check in the startup world today and you’ll inevitably find two groups of people
who have polar opposite viewpoints when it comes to work hours.&lt;/p&gt;

&lt;p&gt;One group feels that working over a certain number of hours is not more
productive in the long term. Another group feels that more hours is better even
to the point of getting less than the recommended amount sleep. I happen to know
that for my own body the former is true, but I can’t speak for anyone else.&lt;/p&gt;

&lt;p&gt;What I can say with complete certainty is this: Whatever your optimum number of
hours is for working each day, it is limited. If you’re trying to start a
business, and why else would you be reading this article, then you by definition
have more work than you can handle. Since you can’t bargain for any more time,
you have to manage what you do have effectively.&lt;/p&gt;

&lt;h4 id=&quot;youre-stating-the-obvious-get-to-the-part-about-villagers&quot;&gt;You’re stating the obvious. Get to the part about villagers.&lt;/h4&gt;

&lt;p&gt;Ok, I get it. You’re here for the good stuff. Maybe you’re an old-school Age of
Empires player like I was. If so, you might remember that in the game there are
two basic ways to go about winning. The first is to slow your opponent’s economy
by military force, and the second is to expand your own economy faster than they
can.&lt;/p&gt;

&lt;p&gt;Theoretically, the way to become the most powerful civilization is to put all
your resources into economic growth. You can think of this economic growth as
analogous to development of your product or in-house processes. It is
cumulative in nature and the benefits are felt by all.&lt;/p&gt;

&lt;p&gt;However, you can’t spend all the resources on your economy. Your opponent is
busy killing off all your villagers faster than you can produce them. Game over.
You have to start fresh, only this time you’ll make some military units to
defend yourself.&lt;/p&gt;

&lt;p&gt;Think of this military protection as the immediate jobs you need to keep the
wolf from the door. That contract work you took to pay bills? Protection. That
feature you pretend to have even though you’re doing it manually just to make
an important customer happy? Protection. If you don’t do these things you don’t
make rent/payroll and you can no longer work on your product.&lt;/p&gt;

&lt;p&gt;Armed with this additional knowledge you start a new game. You won’t be caught
undefended this time! You divert your precious resources to military power and
find you can easily fend off your opponent’s early raids. Soon, they aren’t even
a problem anymore.&lt;/p&gt;

&lt;p&gt;Except, you notice something: Despite beating him on the field your opponent’s
score continues to rise above yours. Every time you try to expand to new
resources you find the other player is already set up. Also, his units are
getting stronger and coming more frequently.&lt;/p&gt;

&lt;p&gt;Before you know it, you’re completely overwhelmed by an army you couldn’t
possibly hope to throw back. Hold on, what happened? How did you lose this game?&lt;/p&gt;

&lt;p&gt;This time you lost because your opponent grew their economy faster than you grew
yours. In effect, you lost because you diverted too much of your resources into
combat (and didn’t cripple their economy in the process). What have we learned
here?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There is a delicate balance that you must preserve in order to compete.&lt;/strong&gt; If
you spend all your time building your military, someone with a better economy
will overtake you later. If you don’t build enough military, someone who did
will use it to stop you.&lt;/p&gt;

&lt;p&gt;Similarly, while bootstrapping your business if you spend too much time on
immediate-return projects, such as consulting, your competitors will make a
better product and win the market. On the other hand, if you spend all your time
on product development it won’t matter that after a year your product will be
the best on market; you only have enough cash on hand for three months worth of
expenses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“So?!”&lt;/strong&gt; I can hear you asking again, possibly a bit more vehemently now. This
is a fairly basic concept. Why am I bothering with the game analogy, and why
haven’t I even mentioned villagers yet? Ok, here they are.&lt;/p&gt;

&lt;p&gt;In this game, the villager is the basic unit of your economy. They gather
resources and construct buildings. You can create more of them at a cost, but
only if you have enough resources and the proper buildings. Ergo, villagers are
in limited supply, just as your time is.&lt;/p&gt;

&lt;p&gt;When you first play the game, you tend to be careless with your villagers. “Go
create this building,” you’ll say. Then you forget about it and do something
else. Later on you find the villager, waiting patiently by the completed
building. This is an idle villager, and he’s hurting your economy more than you
know.&lt;/p&gt;

&lt;p&gt;When an expert plays the game, villagers never remain idle for long. There are
two reasons an idle villager is toxic:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Economic improvements are cumulative.&lt;/strong&gt; If that idle villager had been
gathering food he might have produced enough to build &lt;em&gt;another&lt;/em&gt; villager. Even
small periods of time add up over the length of the game. That extra villager
might have been just enough to get a new economic improvement faster, which in
turn boosts your whole economy further.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Military costs are fixed.&lt;/strong&gt; You have to spend enough on military to defend
yourself, end of story. There is no way around it. If you don’t, it will cost
you even more as they kill your units. This means that any idle villager time
is a direct cost to your cumulative economy, not to your immediate military.&lt;/p&gt;

&lt;p&gt;This is the same as our analogous parts of your bootstrapped business. When the
bills come in, they need to be paid. If it takes half of your time to cover the
maintenance tasks, then you need to dedicate that half to maintenance. By
process of elimination, this means that any time you spend being idle is
deducted directly from your product development.&lt;/p&gt;

&lt;p&gt;Do you spend 15 minutes after each meal relaxing and reading the news? Maybe
not, but it used to be a habit of mine. At four meals per day, that was about an
hour of relaxing time. A single hour out of twenty-four is only 4.2% of my time,
and keeping up in the tech field is worthwhile, right?&lt;/p&gt;

&lt;p&gt;Although, come to think of it, I actually do try to sleep for eight hours each
night. I guess that makes it one out of sixteen hours. I also need to spend time
preparing and actually eating the meals, so that’s probably about another two
hours. There are other daily chores to take care of, too. Personal hygiene,
laundry, pets, dishes, and other cleaning. That takes up at &lt;em&gt;least&lt;/em&gt; another hour
each day.&lt;/p&gt;

&lt;p&gt;Finally, I lift weights every other day and ride a stationary bike for cardio.
This takes about an hour / day average, though to be fair I think this time is
worthwhile due to the increased energy it gives me.&lt;/p&gt;

&lt;p&gt;Ok, so one hour out of twelve. We’re up to 8.4% of my time taken up by my
after-meal relaxations now, and we haven’t even covered the business related
maintenance tasks.&lt;/p&gt;

&lt;p&gt;I spend about an hour each day reading and replying to emails. Some of these are
small tasks, others inquiries, others just updates. None of it gets any software
development done, though. I spend about another hour on top of that setting up
and importing new data for use with our campaigns, inputting criteria for new
matches, arranging for any further scraping required, and sometimes just
manually doing things for customers that the system won’t do automatically yet.&lt;/p&gt;

&lt;p&gt;In addition, there is approximately another hour on top of this lost to context
switching between tasks, chatting with co-workers on HipChat, and the odd voice
or video conference meeting.&lt;/p&gt;

&lt;p&gt;This brings my remaining hours down to nine, which puts my leisurely after-meal
relaxation at a whopping 11.1% of my available development time. That’s almost
three times as much as at the start. Bad enough as is, but it goes on.&lt;/p&gt;

&lt;p&gt;As in the game, much of the product development that I do is cumulative. When I
improve our software it often saves me time, which I can then use to do more
development. That hour worth of setting up campaigns and importing data I
previously mentioned? It used to take a full four hours of my day. Back then, a
15-minute after meal break would be 16.7% of my available development time!&lt;/p&gt;

&lt;p&gt;All this is assuming I have absolutely no life outside of the company. Any of
that time comes directly out of development. Want to see your family? That comes
out of development time. An old friend is in town for the day and wants to hang
out? Now you’re two days behind schedule and playing catch-up on the maintenance
tasks. Have a significant other? Deduct some more time. Have a commute? Deduct
some more time.&lt;/p&gt;

&lt;p&gt;In the end, that 15 minute after-meal break can very easily be a full quarter of
your free development time. Seen in that light, it’s much easier to convince
myself that yes, it really is important to start &lt;strong&gt;right now&lt;/strong&gt;.&lt;/p&gt;

</description>
        <pubDate>Fri, 04 Jul 2014 13:52:00 -0700</pubDate>
        <link>http://tarential.com/startups/bootstrapping/aoe/rts/2014/07/04/idle-villagers.html</link>
        <guid isPermaLink="true">http://tarential.com/startups/bootstrapping/aoe/rts/2014/07/04/idle-villagers.html</guid>
        
        
        <category>startups</category>
        
        <category>bootstrapping</category>
        
        <category>aoe</category>
        
        <category>rts</category>
        
      </item>
    
      <item>
        <title>How to Fail Via Perfectionism</title>
        <description>&lt;p&gt;Pretend you’re starting a blog. Which of the following methods is more likely to
gain significant readership:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Spend a year writing one perfect article.&lt;/li&gt;
  &lt;li&gt;Write a series of 52 articles, one each week.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ok, it’s a trick question. I haven’t actually tested it. Anecdotal stories
online would suggest that one can attain quality through quantity (aka
practice), but that’s not what I’m here to write about.&lt;/p&gt;

&lt;p&gt;I’m here to complain about the perfect part.&lt;/p&gt;

&lt;p&gt;You see, I have a problem publishing my blog posts. I know my writing is far
from perfect, and at times despite my best intentions I even get facts or code
wrong too. My ideas are just “things I made up” in this crazy head of mine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I’ve had my “next post” written since the very day it was due and haven’t
been able to convince myself that it is good enough to publish&lt;/strong&gt;. I have similar
thoughts about all my posts, and this one is no exception.&lt;/p&gt;

&lt;p&gt;You see, &lt;strong&gt;I’m terribly afraid that people will think my writing is bad&lt;/strong&gt;. More
than that, I’m afraid they’ll be right. Yet, is that any reason to not write?&lt;/p&gt;

&lt;p&gt;All my life I’ve had different opinions than most of my peers and my teachers
about what constitutes “good” when it comes to art. Since I didn’t really
understand art in the same way I could understand physics or computers, I just
assumed that I must be wrong.&lt;/p&gt;

&lt;p&gt;An interesting thing happened then. I stopped taking art courses because they
were “hard”. I even stopped practicing any sort of art. It became a
self-fulfilling prophecy. I’ve heard about this happening to other kids, but
usually in the math/science classes instead of art.&lt;/p&gt;

&lt;p&gt;In elementary school my books were filled with doodles. Now I’m ashamed if I
have to draw anything.&lt;/p&gt;

&lt;p&gt;A few years ago during university I wrote a number of articles for high profile
websites, mostly reviews of Linux distributions or other free software. It
started out as an idea for a way to get my name “out there” and turned into a
fairly well paying job. The problem is that when I look back now I see a
different person writing those articles.&lt;/p&gt;

&lt;p&gt;Could those opinions really all have been mine? Could I really have been so
arrogant in my responses to commenters? It would seem so. Now that writing is
memorialized until the end of days. It represents me in many ways. When you
search for me online now you still find them, a decade after they were written.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Suddenly I find myself hesitant to post my writing in the open. It, too,
becomes an everlasting part of me.&lt;/strong&gt; I look to my words and wonder if they will
age gracefully.&lt;/p&gt;

&lt;p&gt;What will I think of my writing, now, in another decade? Will I be happy I wrote
this blog post, or will I feel embarrassed for my former naiveté? Will I have
conquered my fear that others might judge my writing poorly, or will this post
only add to the anxiety?&lt;/p&gt;

&lt;p&gt;I don’t know the answers, but I do know that I’d rather be the guy who tries
than the guy who lets his fear hold him back. That’s why I’m posting this. Not
for the readers this time, but for myself.&lt;/p&gt;

&lt;p&gt;Nevertheless, I hope someone, somewhere enjoys this post and perhaps finds their
own will to push forward. It shall be my constant reminder to step into the
unknown, make mistakes, and learn from them.&lt;/p&gt;

</description>
        <pubDate>Sun, 25 May 2014 17:05:00 -0700</pubDate>
        <link>http://tarential.com/personal/writing/blog/2014/05/25/how.to.fail.via.perfectionism.html</link>
        <guid isPermaLink="true">http://tarential.com/personal/writing/blog/2014/05/25/how.to.fail.via.perfectionism.html</guid>
        
        
        <category>personal</category>
        
        <category>writing</category>
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Reach High, Get Paid</title>
        <description>&lt;p&gt;In the past two years of my life I’ve learned a lot about getting paid. It’s
completely changed my perspective on marketing and sales, both in a freelance
and corporate capacity.&lt;/p&gt;

&lt;h4 id=&quot;reaching-high&quot;&gt;Reaching High&lt;/h4&gt;

&lt;p&gt;The first time I sold a website my fee was $10 / hour. I remember it well,
despite it being over fifteen years ago. The client was a local corn farmer and
reseller. I built a very simple site in less than five hours, but that didn’t
satisfy.&lt;/p&gt;

&lt;p&gt;At first, it just wasn’t enough. It wasn’t exactly what he wanted. One little
change here, another little change there. Then the big question came.&lt;/p&gt;

&lt;p&gt;“How much to get an editable photo gallery with a slideshow and comments?”&lt;/p&gt;

&lt;p&gt;I quoted him 20 hours @ $10 / hour. A mere $200 for what was, at the time, a
relatively complex job. He refused, saying he knew someone else who could do it
cheaper. I got paid for my first five hours and no more.&lt;/p&gt;

&lt;p&gt;Two months ago when I was doing my last contract job (I’ve been working on
&lt;a href=&quot;http://carb.io/&quot;&gt;Carburetor&lt;/a&gt; full time recently), I quoted $220 for 2 hours of work
customizing a client’s Magento plugin. The reply?&lt;/p&gt;

&lt;p&gt;“No problem. Can you get it done by next week?”&lt;/p&gt;

&lt;p&gt;The work took me closer to four hours, if you include communication and setup
time. That didn’t matter. I thought it might take longer. My 2 hour estimate was
used to bump up the hourly rate without raising the price. Why would I do that?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;People tend to treat me better with high rate, low hour estimates.&lt;/strong&gt; Perhaps
it gives the impression that I’m much better at my job, but it’s actually my
marketing skills have which have improved. I think there’s another reason, too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I’m no longer concerned with charging for every fifteen minutes of ancillary
time spent on calls or emails.&lt;/strong&gt; This pays off for both client and freelancer.
The very act of recording such small intervals of time adds overhead. When I was
charging the bare minimum per hour I couldn’t afford to give away “free time”
like that. Now it’s easier to include as part of the main estimate.&lt;/p&gt;

&lt;p&gt;Here’s the most interesting part I’ve discovered so far: &lt;strong&gt;When you are cheap,
clients will argue with you about the price. When you are expensive, clients
will argue with you about the features.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Trying to compete on price will only send you in one direction: Down. That’s a
depressing direction to go. So depressing it actually made me quit professional
programming during university to take up technical writing instead.&lt;/p&gt;

&lt;h4 id=&quot;getting-paid&quot;&gt;Getting Paid&lt;/h4&gt;

&lt;p&gt;Our CRM &lt;a href=&quot;http://voltagecrm.com&quot;&gt;voltageCRM&lt;/a&gt; has never felt the pressure of a
thousand registered users. I don’t think we’ve passed 100 users logged in at a
time. Most start-ups would fall down laughing at our pitiful “traction”.  Yet
I’ll let you in on a little secret: &lt;strong&gt;voltageCRM has been profitable since
day one.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ok, that doesn’t count our time at even minimum wage near the start. We have
always had enough to cover company expenses, contribute to our personal
expenses, and still bank a little for a rainy day. It was enough, combined with
a little outside work, to keep us going until we found some real traction with
our lead generation service (&lt;a href=&quot;http://carb.io&quot;&gt;Carburetor&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Surely that was just luck, though, right? Everyone would be profitable from the
start if they could.&lt;/p&gt;

&lt;p&gt;Luck is great, and we take it where we can get it, but this profit was due to
the careful planning of my partner Collin. He &lt;strong&gt;first found a client willing to
pay&lt;/strong&gt; for a custom CRM, then found open source software (Fat Free CRM) close
enough to act as a “MVP”.&lt;/p&gt;

&lt;p&gt;We started by customizing Fat Free CRM to meet their requirements.  The next
step was to recreate everything from scratch, aka “version 2.0” of our software.
All the while, we were charging $50 per user per month to run modified open
source software.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customers care neither how the system works nor how much work it took you.&lt;/strong&gt;
It works. It fits their requirements. It is within their budget. That is enough.
As a programmer, this lesson was shocking. I used to associate value directly
with the technical challenge involved. Sorry younger me, but that point of view
is &lt;em&gt;wrong&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;When we set out to build &lt;a href=&quot;http://carb.io/&quot;&gt;Carburetor&lt;/a&gt;, the first step was similar.
Collin found five prospective customers willing to put down $500 each on a trial
of the new service. He ran that trial manually while I worked on our CRM
software. The trial was a success. We’ve continued down that road. So?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Carburetor has been profitable since day one.&lt;/strong&gt; Even if the trial had been a
failure we could have walked away slightly better off than we’d been before.&lt;/p&gt;

&lt;p&gt;How does this help you? It won’t, unless you take action! Do you want to build
something? Find your target customers. Hear their complaints. Find out what they
want. Tell them how you’ll accomplish what they need. &lt;strong&gt;Then, ask for a
cheque.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At my last “start-up”, I built CMS software based on what I thought small web
design shops needed. I didn’t partner up with a business/sales guy because &lt;strong&gt;who
wants to give away half their company&lt;/strong&gt;, right? Besides, there was no business
work to do yet. I wasn’t &lt;em&gt;done&lt;/em&gt; the software, so we had nothing to sell.&lt;/p&gt;

&lt;p&gt;If you found yourself nodding along at all to that last paragraph, &lt;strong&gt;find a cold
glass of water and toss it in your face&lt;/strong&gt;. Good. Now, rethink that situation.
The reality is that &lt;strong&gt;there was no development work to do because I didn’t have
any customers&lt;/strong&gt;. That’s right, I said it. My precious work had no intrinsic
value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our salesman CEO has been worth his weight in gold.&lt;/strong&gt; I’m not a solo founder
anymore. I no longer own 100% of nothing. Instead, I own a split share of
something very significant. My own personal value is increased simply by
learning to market and sell properly. I don’t think it’s a stretch to say that
&lt;strong&gt;finding a non-technical partner was the best business decision I’ve ever
made&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This has been a long post, but let me try for a quick summary: &lt;strong&gt;Get paid up
front and don’t be afraid to charge a reasonable amount.&lt;/strong&gt; If you can do that
your chances of success are greatly increased. Plus, if you fail the landing is
cushioned.&lt;/p&gt;

</description>
        <pubDate>Sat, 01 Mar 2014 10:51:00 -0800</pubDate>
        <link>http://tarential.com/2014/03/01/reach-high-get-paid.html</link>
        <guid isPermaLink="true">http://tarential.com/2014/03/01/reach-high-get-paid.html</guid>
        
        
      </item>
    
      <item>
        <title>Medium Data Discoveries on PostgreSQL</title>
        <description>&lt;p&gt;Here at 27 Volt Labs we recently saw our database grow by several orders of magnitude after launching our new service, &lt;a href=&quot;http://carb.io/&quot;&gt;carb.io&lt;/a&gt;. While it may have been considered “Big Data” ten years ago, today it falls into the lesser known category of “Medium Data”.&lt;/p&gt;

&lt;h4 id=&quot;what-exactly-is-medium-data-anyway&quot;&gt;What exactly is &lt;strong&gt;Medium Data&lt;/strong&gt;, anyway?&lt;/h4&gt;

&lt;p&gt;Opinions vary, as they normally do. My favorite is &lt;a href=&quot;https://rgrossman.wordpress.com/tag/what-is-a-large-data-cloud/&quot;&gt;this dynamic definition&lt;/a&gt; [Link Updated] which states, in general terms, that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Small data fits in the memory of a single machine.&lt;/li&gt;
  &lt;li&gt;Medium data fits on the disk or disks of a single machine.&lt;/li&gt;
  &lt;li&gt;Big data requires a distributed storage/access system.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Obviously this isn’t an exact science. There is no one point where your data crosses the line; hardware capabilities are always changing. Still, we can say in general terms that our own database has stopped fitting in memory on most average machines today. This is a marked difference from the &amp;lt;256MB of data we had before launching &lt;a href=&quot;http://carb.io/&quot;&gt;carb.io&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;enough-with-the-backstory-what-did-you-learn&quot;&gt;Enough with the backstory. What did you learn?&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;If at all possible, use a subset of the database for testing.&lt;/strong&gt; Sometimes we have to test with the entire database, but usually either fake data or a subset of the real database will do the trick. It’s much faster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test your queries on the entire database.&lt;/strong&gt; Yes, I know what I just said. Most of the time you can test on a subset. But you absolutely must test your queries on realistic amounts of data to see how they perform. In the small data days a slow-running query would take a few seconds. Now the same problem query takes three hours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solid state drives are your friend.&lt;/strong&gt; Did you know that doing a simple alter table add column in PostgreSQL can take hours on a 7200RPM hard disk? It can, if your table is big enough. Restoring a copy of the production database is even worse. I’ve never found my big, slow hard disks lacking before. Now I run the dev database on a Samsung 840 Pro Series SSD.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check your indexes.&lt;/strong&gt; This should be obvious. Hey, I’ve always indexed my tables. Yes, by every column I want to query against on a regular basis. How could I forget any of them? The truth is, I did forget some, and we never noticed back when the entire database fit into memory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your backup strategy might have to change.&lt;/strong&gt; We used to dump our database and pull offsite backups hourly (in addition to the slave server running a continuous sync). Now it takes the better part of an hour just to dump the database and is a burden on the server to create. We’ve started dumping from the slave server instead, and only every six hours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Increase the Write-Ahead Log buffer size and/or number of files.&lt;/strong&gt; Large numbers of queries in a short period of time can push your slave server out of sync. Then it just sits there like a crying child, logging its woes pitifully until you rsync the database manually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tune your database/OS.&lt;/strong&gt; There is more to this than I have time for here, but suffice to say that the defaults are not your friend. We ended up increasing the Linux shmmax/shmall and the PostgreSQL effective_cache_size and shared_buffers settings. For help tuning your own OS install for PostgreSQL look to the &lt;a href=&quot;http://www.postgresql.org/docs/9.5/static/kernel-resources.html&quot;&gt;manual&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There you have it folks. You get the lessons learned from our recent increase in database size and I make my promised blog post for the month. I hope you found it useful!&lt;/p&gt;
</description>
        <pubDate>Fri, 31 Jan 2014 22:55:00 -0800</pubDate>
        <link>http://tarential.com/postgresql/medium-data/carburetor/2014/01/31/medium-data-discoveries-on-postgresql.html</link>
        <guid isPermaLink="true">http://tarential.com/postgresql/medium-data/carburetor/2014/01/31/medium-data-discoveries-on-postgresql.html</guid>
        
        
        <category>postgresql</category>
        
        <category>medium-data</category>
        
        <category>carburetor</category>
        
      </item>
    
      <item>
        <title>The Great Pivot of 27 Volt Labs</title>
        <description>&lt;p&gt;Here at 27 Volt Labs we’ve been working hard to create &lt;a href=&quot;http://voltagecrm.com&quot;&gt;CRM software for both users and managers&lt;/a&gt; (&lt;a href=&quot;http://en.wikipedia.org/wiki/Customer_relationship_management&quot;&gt;What is CRM?&lt;/a&gt;). We’ve had positive feedback; enough to think we’re doing a good thing. We’ve also had negative feedback, and we’ve used that to improve the product. Overall, things are looking good. So, what’s the problem?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It’s just not fast enough.&lt;/strong&gt; We found two main issues slowing adoption. To start, it turns out that CRM tools are often very highly integrated with other existing systems within the company. Prospective clients always come with a list of requirements as long as their arm. We have to support all of their current software and hardware, which is resource-intensive for a small bootstrapped company like ours. Secondly, we’ve discovered that large enterprises move even more slowly than expected. Clients come to us to discuss an integration that might happen two years down the road.&lt;/p&gt;

&lt;p&gt;So, &lt;strong&gt;what can we do about it?&lt;/strong&gt; The very question my partner and I asked ourselves. What can we provide that all companies need, that they’re willing to pay for, and that can be produced and consumed in the short term? Preferably something that utilizes our current technology and gives us incentive to improve upon it. Also, if you could have the answer to me before dinner that’d be great, mmmk?&lt;/p&gt;

&lt;p&gt;Improbable, right? Very much. Yet we found it. All companies need customers, and we’ve spent months practicing sales. We know how to get the right people to listen. We use our own CRM tool to hook you up with the people you want to meet. In doing so, we’ve now removed the integration requirements as barriers to entry and changed our offering from the “expense” of a CRM to the profit of additional customers.&lt;/p&gt;

&lt;p&gt;We call our new lead generation service &lt;a href=&quot;http://carb.io/&quot;&gt;“Carburetor”&lt;/a&gt; and it’s been an immediate success. What started as an experiment in &lt;a href=&quot;http://paulgraham.com/ds.html&quot;&gt;unscalability&lt;/a&gt; quickly reached the limits. It’s obvious that people are interested in lead generation, and we’ve seen results with our methods. Now it’s time to automate them.&lt;/p&gt;

&lt;p&gt;To that end, we’re happy to announce that we have a new developer joining our team. &lt;a href=&quot;https://github.com/Fire-Dragon-DoL&quot;&gt;Francesco Belladonna&lt;/a&gt; is our second dedicated developer and his addition brings our team up to five. Our CEO Collin Stewart, myself Preston St. Pierre as CTO, our designer Allegra Scrugham, and our salesperson Jerry Situ make up the other four. Can I have a moment to be a little proud of what we’ve accomplished? Hell, it’s my blog. I’m proud of what we’ve accomplished :)&lt;/p&gt;

&lt;p&gt;Now that I’ve fulfilled my promise about an update I’ll veer back to the original problem. I have this blog which I told myself I’d keep updated, yet I haven’t been. I think I bit off a bit more than I could chew with the plan to write one blog post every week. Either that or I need to lower my standards and make them shorter. I think I’ll do a combination of both. Once a month I shall write a “feature length” article on a particular topic designed to help inform readers. Other times, at my whim, I will write spontaneous blog posts of shorter duration with a bit less purpose to them. Hopefully this new schedule will be easier to meet with the ever-growing business demands.&lt;/p&gt;
</description>
        <pubDate>Mon, 23 Dec 2013 09:14:00 -0800</pubDate>
        <link>http://tarential.com/caburetor/pivot/lead-generation/2013/12/23/the-great-pivot-of-27-volt-labs.html</link>
        <guid isPermaLink="true">http://tarential.com/caburetor/pivot/lead-generation/2013/12/23/the-great-pivot-of-27-volt-labs.html</guid>
        
        
        <category>caburetor</category>
        
        <category>pivot</category>
        
        <category>lead-generation</category>
        
      </item>
    
      <item>
        <title>Testing AngularJS? A.K.A. Where is Tarential?</title>
        <description>&lt;p&gt;This is more of a meta-post, so I’ll try to keep it short.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First of all, what happened to the AngularJS testing post?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Three things, actually:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Business is going well. I’ll be writing a follow-up post about this, but for now suffice to say that I’ve been very busy with work problems.&lt;/li&gt;
  &lt;li&gt;My post on testing AngularJS got really long in the outline stage. Enough to be a series all by itself.&lt;/li&gt;
  &lt;li&gt;While I was researching, I found &lt;a href=&quot;http://www.yearofmoo.com/2013/01/full-spectrum-testing-with-angularjs-and-karma.html&quot;&gt;another tutorial that covers AngularJS testing in great detail&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I’ve been mulling these points over in my mind, trying to decide if I should write a separate testing series anyway. I’ve concluded that it would be wasted effort, since the &lt;a href=&quot;http://www.yearofmoo.com&quot;&gt;Year of Moo&lt;/a&gt; tutorial is so comprehensive (it’s a good site in general, check it out).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Secondly, what happened to Tarential?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Besides being busy as outlined above, I also felt obliged to write my next post on AngularJS testing. Since that was in question, I wound up writing no blog posts at all. This is a problem because I made a new year’s resolution to keep up the blog posts. Clearly I’ve been failing at it. So, starting next week, I shall continue posting with a follow-up on how our startup (&lt;a href=&quot;http://voltagecrm.com/&quot;&gt;27 Volt Labs&lt;/a&gt;) is doing.&lt;/p&gt;

&lt;p&gt;That about sums it up. I apologize to everyone for the prolonged break. Come back in a week for the next post.&lt;/p&gt;

&lt;p&gt;-Preston&lt;/p&gt;
</description>
        <pubDate>Mon, 16 Dec 2013 06:04:00 -0800</pubDate>
        <link>http://tarential.com/apologies/personal/2013/12/16/testing-angularjs-aka-where-is-tarential.html</link>
        <guid isPermaLink="true">http://tarential.com/apologies/personal/2013/12/16/testing-angularjs-aka-where-is-tarential.html</guid>
        
        
        <category>apologies</category>
        
        <category>personal</category>
        
      </item>
    
      <item>
        <title>Startup Means Busy</title>
        <description>&lt;p&gt;Hi folks. Perhaps some of you are wondering where the next part of your AngularJS on Rails tutorial is, and with good reason. I missed last week and I apologize but it won’t be out this week either. For the last six months I’ve been developing customer relationship management software for a startup I co-founded, 27 Volt Labs. This software, &lt;a href=&quot;http://voltagecrm.com&quot;&gt;voltageCRM&lt;/a&gt;, is entering the beta stage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For the first time we have people running real, production data on our software.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s exciting. It’s hectic. There are bugs, we fix them. There are new features people need, we implement them. There are blog posts that need to be written… but I fall behind. I must pick and choose my battles. I must needs choose my business over my blog. However, I will do my best to ensure that this state of chaos is short-lived and that the posts continue as scheduled.&lt;/p&gt;

&lt;p&gt;For the second day in a row I’m up past 4am preparing for the users to hit the server at 6am. Last time I went to bed only to receive a call at quarter past six saying something needed to be changed. I think this time I’ll just stay up and keep working.&lt;/p&gt;

&lt;p&gt;All this and I still earn far less than minimum wage. &lt;strong&gt;So this is what it’s like to be an entrepreneur.&lt;/strong&gt;&lt;/p&gt;
</description>
        <pubDate>Tue, 19 Mar 2013 08:46:00 -0700</pubDate>
        <link>http://tarential.com/carburetor/startup/busy/2013/03/19/startup-means-busy.html</link>
        <guid isPermaLink="true">http://tarential.com/carburetor/startup/busy/2013/03/19/startup-means-busy.html</guid>
        
        
        <category>carburetor</category>
        
        <category>startup</category>
        
        <category>busy</category>
        
      </item>
    
      <item>
        <title>Angularize Your Rails App Part Four: Sending Data</title>
        <description>&lt;p&gt;After last week’s post on &lt;a href=&quot;/angularjs/rails/services/2013/02/25/angularize-your-rails-app-part-three-getting-data.html&quot;&gt;retrieving data from your Rails API&lt;/a&gt; you should be able to view a list of tasks in your application. While an essential part of the client, seeing isn’t everything. We need a way to create, update and delete tasks. Let’s get started.&lt;/p&gt;

&lt;h4 id=&quot;services&quot;&gt;Services&lt;/h4&gt;

&lt;p&gt;We’ll be sending data using the same services we created last week for retrieving. Here they are in case you missed it:&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
exampleServices = angular.module(&#39;exampleServices&#39;, [&#39;ngResource&#39;]).
  factory(&#39;Tasks&#39;, [&#39;$resource&#39;, ($resource) -&amp;gt;
    $resource(&#39;/tasks.json&#39;, {}, {
      query: { method: &#39;GET&#39;, isArray: true }
      create: { method: &#39;POST&#39; }
    })
  ]).
  factory(&#39;Task&#39;, [&#39;$resource&#39;, ($resource) -&amp;gt;
    $resource(&#39;/tasks/:task_id.json&#39;, {}, {
      show: { method: &#39;GET&#39; }
      update: { method: &#39;PUT&#39; }
      destroy: { method: &#39;DELETE&#39; }
    })
  ]).
&lt;/div&gt;

&lt;h4 id=&quot;creating-the-templates&quot;&gt;Creating the Templates&lt;/h4&gt;

&lt;p&gt;To start with, create a form template containing fields for a task. In a slight deviation from traditional methods the name we give the input will not dictate which data is sent to the server by AngularJS. Instead, that association is made using the element’s model. You’re going to give each input field an attribute in the form of &lt;span class=&quot;code&quot;&gt;“data-ng-model” =&amp;gt; “task.field_name”&lt;/span&gt;. This binding works both ways; changing the input value will change &lt;span class=&quot;code&quot;&gt;task.field_name&lt;/span&gt; and changing &lt;span class=&quot;code&quot;&gt;task.field_name&lt;/span&gt; will change the input value.&lt;/p&gt;

&lt;p&gt;As an added bonus, this binding will affect all other elements in the scope containing the same variable &lt;span class=&quot;code&quot;&gt;task&lt;/span&gt;. For a live preview box all you have to do is include your task show template in the same scope as your edit form. No more hitting the “preview” button and waiting for the server to respond. Everything is automated and live. However, there is something to watch out for.&lt;/p&gt;

&lt;p&gt;Heads up: The DOM is not considered canon for data values. AngularJS stores values separately in memory.&lt;/p&gt;

&lt;p&gt;This may seem like an irrelevant distinction since in most cases they actually match up. Certain elements, like select options, do not match. Their values instead are the indices for the options array. Don’t be fooled when you inspect the DOM and don’t assume that altering the DOM will change the AngularJS values. In addition, it’s not necessary to create hidden input fields to pass variables along with the form. Simply set the value on the task object before you send it.&lt;/p&gt;

&lt;p&gt;Here is an example of a form for a task object found in &lt;span class=&quot;code&quot;&gt;/templates/tasks/edit.html&lt;/span&gt;:&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
.edit-task{ &quot;data-ng-model&quot; =&amp;gt; &quot;task&quot; }
  %form
    %label{ for: &quot;task_name&quot; } Task
    %input{ type: &quot;text&quot;, class: &quot;focus&quot;, id: &quot;task_name&quot;, name: &quot;task[name]&quot;,
      placeholder: &quot;Enter your task here.&quot;, &quot;data-ng-model&quot; =&amp;gt; &quot;task.name&quot; }
    %label{ for: &quot;task_due&quot; } Due
    %input{ type: &quot;text&quot;, class: &quot;date&quot;, id: &quot;task_due&quot;, name: &quot;task[due]&quot;,
      placeholder: &quot;Enter the due date here.&quot;, &quot;data-ng-model&quot; =&amp;gt; &quot;task.due&quot; }
    %button{ type: &quot;button&quot;, &quot;data-ng-click&quot; =&amp;gt; &quot;save(task)&quot;,
      name: &quot;commit&quot;, value: &quot;Save Task&quot; } Save Task
    or
    %button{ type: &quot;button&quot;, &quot;data-ng-click&quot; =&amp;gt; &quot;cancel()&quot; } Cancel
    %span{ &quot;data-ng-show&quot; =&amp;gt; &quot;task.id &amp;gt; 0&quot; }
      or
      %a{ rel: &quot;nofollow&quot;, class: &quot;delete&quot;, &quot;data-ng-click&quot; =&amp;gt; &quot;destroyTask(task)&quot; } Delete Task
&lt;/div&gt;

&lt;p&gt;Here we have a template containing the task name and due date along with options to save, cancel or delete the task. The option to delete appears only if the task has an ID, indicating it is saved. This allows us to re-use the form for both creating new and editing existing tasks. How do we do that? The buttons still aren’t functional! That’s true. This code doesn’t stand alone. We’re going to update the index page from the previous post in order to add new tasks.&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
.tasks{ &quot;data-ng-controller&quot; =&amp;gt; &quot;TaskController&quot; }
  .add-button{ &quot;data-ng-hide&quot; =&amp;gt; &quot;task.editing&quot;, &quot;data-ng-click&quot; =&amp;gt; &quot;newTask()&quot; } New Task
  .edit-task-form{ &quot;data-ng-show&quot; =&amp;gt; &quot;task.editing&quot;, &quot;data-ng-include&quot; =&amp;gt; &quot;&#39;/templates/tasks/edit.html&#39;&quot; }
  .index{ &quot;data-ng-repeat&quot; =&amp;gt; &quot;task in tasks&quot;, &quot;data-ng-include&quot; =&amp;gt; &quot;&#39;/templates/tasks/show.html&#39;&quot; }
&lt;/div&gt;

&lt;p&gt;The first element is the new task button, followed by the task edit form. You’ll only see one of the two at any given time since we hide/show them based on the same boolean flag.&lt;/p&gt;

&lt;p&gt;Since we’re planning to make changes to the existing tasks we’ll want a way to update the task index without reloading the page. Add this function to your task controller (&lt;span class=&quot;code&quot;&gt;TaskController&lt;/span&gt; if you followed the previous post):&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
$scope.reloadIndex = -&amp;gt;
  Tasks.query({}, (tasks) -&amp;gt;
    $scope.tasks = tasks
  )
&lt;/div&gt;

&lt;h4 id=&quot;adding-tasks&quot;&gt;Adding Tasks&lt;/h4&gt;

&lt;p&gt;These templates aren’t very useful by themselves. They require some controller updates to be made active. Start by adding the following functions to &lt;span class=&quot;code&quot;&gt;TaskController&lt;/span&gt;:&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
$scope.newTask = -&amp;gt;
  $scope.task = {}
  $scope.task.editing = true
$scope.cancel = -&amp;gt;
  $scope.task.editing = false
$scope.save = (task) -&amp;gt;
  Tasks.create({task_id: task.id, task: task}, (reply) -&amp;gt;
    task.editing = false
    task.id = reply.id
    $scope.reloadIndex()
  )
&lt;/div&gt;

&lt;p&gt;The new task function creates a new blank object and sets the editing flag to true while the cancel function simply sets the flag to false. The save function accepts the task model we’ve been editing and sends it to the server, whereupon the server replies with the generated ID. We add this ID to the task before inserting it into the top of the index.&lt;/p&gt;

&lt;p&gt;“Wait,” you say, “my server is throwing an error!” This is anticipated. We still need to set up the response format for the create method of our tasks controller on the Rails app:&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;format.json { render json: { id: @task.id }, status: :ok }&lt;/div&gt;

&lt;p&gt;Inserting this inside the &lt;span class=&quot;code&quot;&gt;respond_to do |format|&lt;/span&gt; block of your controller as outlined in the previous post will instruct the server to send the ID along with the success message. Now the client and server can speak to each other!&lt;/p&gt;

&lt;h4 id=&quot;editing-tasks&quot;&gt;Editing Tasks&lt;/h4&gt;

&lt;p&gt;Earlier on I promised you the ability to edit tasks. Here’s how. Add an edit button for each task on the show template (&lt;span class=&quot;code&quot;&gt;/templates/tasks/show.html&lt;/span&gt;):&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
.edit-button{ &quot;data-ng-hide&quot; =&amp;gt; &quot;task.editing&quot;, &quot;data-ng-click&quot; =&amp;gt; &quot;editTask(task)&quot; } Edit Task
&lt;/div&gt;

&lt;p&gt;Make it work by adding this function to your &lt;span class=&quot;code&quot;&gt;TaskController&lt;/span&gt;:&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
$scope.editTask = (task) -&amp;gt;
  $scope.task = task
  $scope.task.editing = true
&lt;/div&gt;

&lt;p&gt;Finally, we’ll need to add a destroyTask function and update the save function in the task controller as follows:&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
$scope.save = (task) -&amp;gt;
  if task.id
    task.$update({task_id: task.id}, -&amp;gt;
      $scope.reloadIndex()
    )
  else
    Tasks.create({task_id: task.id, task: task}, (reply) -&amp;gt;
      task.editing = false
      task.id = reply.id
      $scope.reloadIndex()
    )
$scope.destroyTask = (task) -&amp;gt;
  Task.destroy({task_id: task.id}, -&amp;gt;
    $scope.reloadIndex()
  )
&lt;/div&gt;

&lt;p&gt;The new destroy function will tell the server to delete the given object. The save function has been modified to send an update command if the task has an ID (thus is already saved) or a create command otherwise. Afterwards they reload the task index to update the display.&lt;/p&gt;

&lt;p&gt;There you have it folks! Some might consider this a complete client side web application, but there is still more left unwritten. Right now our app only responds to success. What happens when an API call fails or a requested update fails validation? We still need to handle error notification and fail gracefully. We also have to write our client side tests. Come back in two weeks to read more!&lt;/p&gt;
</description>
        <pubDate>Mon, 04 Mar 2013 13:42:00 -0800</pubDate>
        <link>http://tarential.com/angularjs/rails/services/2013/03/04/angularize-your-rails-app-part-four-sending-data.html</link>
        <guid isPermaLink="true">http://tarential.com/angularjs/rails/services/2013/03/04/angularize-your-rails-app-part-four-sending-data.html</guid>
        
        
        <category>angularjs</category>
        
        <category>rails</category>
        
        <category>services</category>
        
      </item>
    
      <item>
        <title>Angularize Your Rails App Part Three: Getting Data</title>
        <description>&lt;p&gt;In the &lt;a href=&quot;/angularjs/rails/services/2013/03/04/angularize-your-rails-app-part-four-sending-data.html&quot;&gt;previous post in this series&lt;/a&gt; I explained, with sample code, how to separate your &lt;a href=&quot;http://angularjs.org/&quot;&gt;AngularJS&lt;/a&gt; front end from your &lt;a href=&quot;http://rubyonrails.org/&quot;&gt;Ruby on Rails&lt;/a&gt; back end. In this post I will explain how to reconnect them for the purposes of getting data from the server.&lt;/p&gt;

&lt;p&gt;Sharing data in AngularJS is done via &lt;a href=&quot;https://docs.angularjs.org/guide/services&quot;&gt;services&lt;/a&gt;. You’re probably familiar with a few of the built in services provided by AngularJS, such as $locationProvider and $routeProvider, from the &lt;a href=&quot;/angularjs/rails/routing/2013/02/11/angularize-your-rails-app-part-one-routing.html&quot;&gt;AngularJS routing post&lt;/a&gt; I wrote a couple weeks ago. Well, you can create your own services for use in your application. Let’s look at an example:&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
exampleServices = angular.module(&#39;exampleServices&#39;, [&#39;ngResource&#39;]).
  factory(&#39;Tasks&#39;, [&#39;$resource&#39;, ($resource) -&amp;gt;
    $resource(&#39;/tasks.json&#39;, {}, {
      query: { method: &#39;GET&#39;, isArray: true }
      create: { method: &#39;POST&#39; }
    })
  ]).
  factory(&#39;Task&#39;, [&#39;$resource&#39;, ($resource) -&amp;gt;
    $resource(&#39;/tasks/:task_id.json&#39;, {}, {
      show: { method: &#39;GET&#39; }
      update: { method: &#39;PUT&#39; }
      destroy: { method: &#39;DELETE&#39; }
    })
  ]).
&lt;/div&gt;

&lt;p&gt;Here we have defined two new services, Task and Tasks. These use the AngularJS ngResource service, which must be declared as a dependency and included in your source files (&lt;a href=&quot;http://code.angularjs.org/&quot;&gt;downloadable here&lt;/a&gt; for your chosen release as angular-resource.js). The ngResource service provides us an easy way to send requests to our API and automatically load the data on receiving a reply.&lt;/p&gt;

&lt;p&gt;As you may have guessed, the singular service (Task) is responsible for interactions with single, specific task objects. The plural service (Tasks) is used for interactions with multiple or non-specific objects. The url passed as the first argument to the $resource function must match the routes on your Rails API. Note that we’ve added the JSON extension since that is the format of response we want. Each of these services has multiple functions associated with it; these functions each have their own HTTP method (and potentially other variables) which will be received by Rails and used to interpret the request.&lt;/p&gt;

&lt;p&gt;In order to use these services we must first declare the services module as a dependency for our main AngularJS module as follows:&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
@example = angular.module(&#39;example&#39;,[&#39;exampleServices&#39;,&#39;ngSanitize&#39;],
[&#39;$routeProvider&#39;, &#39;$locationProvider&#39;, ($routeProvider, $locationProvider) -&amp;gt;
&lt;/div&gt;

&lt;p&gt;From here we then declare the services themselves as a dependency anywhere we wish to use them, such as in a controller:&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
example.controller(&#39;TaskController&#39;, [&#39;$scope&#39;,&#39;$location&#39;,&#39;Task&#39;,&#39;Tasks&#39;,
TaskController = ($scope, $location, Task, Tasks) -&amp;gt;
&lt;/div&gt;

&lt;p&gt;Now let’s retrieve a list of tasks for the index:&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
$scope.tasks = Tasks.query()
&lt;/div&gt;

&lt;p&gt;Wait a minute. Where’s the callback function? Isn’t that how JS works? You send a request, then handle it with a callback function. Actually you can do that by passing in a function as the second argument (after the data as the first) to the service function. In this case, however, that would be overkill. AngularJS knows your intention here is to wait for the request to be complete then assign $scope.tasks to the return value of that call, so that’s exactly what it does for you. When the response is parsed the value will be updated and your views will be re-rendered accordingly. It’s that easy to make API calls.&lt;/p&gt;

&lt;h4 id=&quot;the-rails-side&quot;&gt;The Rails Side&lt;/h4&gt;

&lt;p&gt;There’s only one problem. Anyone following along and running this code is (likely) going to get an error response from their Rails application. Why? By default, Rails doesn’t respond to JSON format. We have to go into all our controllers and add that response type. Here’s an example from the tasks controller:&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
@tasks = Task.all
respond_to do |format|
  format.json { render json: @tasks }
end
&lt;/div&gt;

&lt;p&gt;This basically says “If you received this request with a JSON extension then respond with the contents of the @tasks variable rendered in JSON format”. You’ll add a similar line in every one of your controllers which responds with data. You might add another response format if, for example, you wished to support XML. What about a simple “destroy” command which doesn’t need to respond with data beyond a report of success? I’m glad you asked:&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
format.json { render nothing: true, status: :ok }
&lt;/div&gt;

&lt;p&gt;This little snippet will result in no content but only a successful response code which AngularJS interprets. You can switch this to any of the available Rails symbols which map to HTTP response codes (an unofficial list is available &lt;a href=&quot;http://billpatrianakos.me/blog/2013/10/13/list-of-rails-status-code-symbols/&quot;&gt;here&lt;/a&gt; or by installing the &lt;a href=&quot;http://cheat.errtheblog.com/&quot;&gt;cheat gem&lt;/a&gt; and running the command &lt;span class=&quot;code&quot;&gt;cheat status_codes&lt;/span&gt;). I’ve found these really handy in designing the API for our application.&lt;/p&gt;

&lt;p&gt;There’s another problem, though. Let’s assume that each of our tasks has comments associated with it which we’d like to display. In our Rails views we’d call &lt;span class=&quot;code&quot;&gt;task.comments&lt;/span&gt; and it would give us the list of comments. The same is true AngularJS. So what’s the problem? It turns out that Rails, in an attempt to be efficient, is lazy about loading those comments. It doesn’t do so until you actually request them.&lt;/p&gt;

&lt;p&gt;One solution would be to make another API call for each task, requesting the associated comments. You might choose this way if you only wanted to display the comments at user request (thus saving the transfer of those comments which are not to be displayed). If you intend to display all comments, a better way is to specify to Rails that you’d like to include them in the main tasks list. Here’s how:&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
@task = Task.includes(:comments).where(&quot;id=?&quot;,params[:id]).first
respond_to do |format|
  format.json { render json: @task.as_json(include: [:comments] }
end
&lt;/div&gt;

&lt;p&gt;In the first line we’re telling Rails that the query to load our requested task should include the associated comments. Rails might handle this with a single query or multiple queries depending on what it deems efficient. Then, in the third line, we’re telling Rails to include the associated comments when it renders the JSON response. Now let’s get back to displaying our content.&lt;/p&gt;

&lt;h4 id=&quot;the-angular-side&quot;&gt;The Angular Side&lt;/h4&gt;

&lt;p&gt;When last we left our client it had assigned $scope.tasks to the result of our API call. This should now give you a real list of tasks. You can inspect them in the console or you can display them using code like this:&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
.index{ &quot;data-ng-repeat&quot; =&amp;gt; &quot;task in tasks&quot;, &quot;data-ng-include&quot; =&amp;gt; &quot;&#39;/templates/tasks/show.html&#39;&quot; }
&lt;/div&gt;

&lt;p&gt;Then, in &lt;span class=&quot;code&quot;&gt;/templates/tasks/show.html&lt;/span&gt;:&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
.task{ &quot;data-ng-controller&quot; =&amp;gt; &quot;TaskController&quot; }
  .name 
  .description 
  .comments{ &quot;data-ng-repeat&quot; =&amp;gt; &quot;comment in task.comments&quot;, &quot;data-ng-include&quot; =&amp;gt; &quot;&#39;/templates/comments/show.html&#39;&quot; }
&lt;/div&gt;

&lt;p&gt;And finally, in &lt;span class=&quot;code&quot;&gt;/templates/comments/show.html&lt;/span&gt;:&lt;/p&gt;

&lt;div class=&quot;code&quot;&gt;
.comment{ &quot;data-ng-controller&quot; =&amp;gt; &quot;CommentController&quot; }
  .subject 
  .content 
&lt;/div&gt;

&lt;p&gt;There you have it! You’ve successfully loaded your data from the Rails API and displayed it in your AngularJS application. Congratulations! Join me next week when we’ll be going the other way and using services to send data back to the Rails server. &lt;span class=&quot;edit&quot;&gt;Update: The next post is now available &lt;a href=&quot;/angularjs/rails/services/2013/03/04/angularize-your-rails-app-part-four-sending-data.html&quot;&gt;here&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 25 Feb 2013 12:23:00 -0800</pubDate>
        <link>http://tarential.com/angularjs/rails/services/2013/02/25/angularize-your-rails-app-part-three-getting-data.html</link>
        <guid isPermaLink="true">http://tarential.com/angularjs/rails/services/2013/02/25/angularize-your-rails-app-part-three-getting-data.html</guid>
        
        
        <category>angularjs</category>
        
        <category>rails</category>
        
        <category>services</category>
        
      </item>
    
  </channel>
</rss>
