<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>sensible.io blog</title>
  <subtitle>Team sensible.io blog</subtitle>
  <id>http://blog.sensible.io/</id>
  <link href="http://blog.sensible.io/"/>
  <link href="http://blog.sensible.io/rss" rel="self"/>
  <updated>2014-05-17T17:57:00Z</updated>
  <author>
    <name>sensible.io team</name>
  </author>
  <entry>
    <title>SSH Tunnel - Local and Remote Port Forwarding Explained With Examples</title>
    <link rel="alternate" href="/2014/05/17/ssh-tunnel-local-and-remote-port-forwarding-explained-with-examples.html"/>
    <id>/2014/05/17/ssh-tunnel-local-and-remote-port-forwarding-explained-with-examples.html</id>
    <published>2014-05-17T17:57:00Z</published>
    <updated>2014-05-17T17:57:00Z</updated>
    <author>
      <name>sensible.io team</name>
    </author>
    <content type="html">&lt;p&gt;There are two ways to create an SSH tunnel, local and remote port
forwarding (there&amp;rsquo;s also dynamic forwarding, but we won&amp;rsquo;t cover that
here). The best way to understand these is by an example, let&amp;rsquo;s start
with local port forwarding.&lt;/p&gt;

&lt;p&gt;Imagine you&amp;rsquo;re on a private network which doesn&amp;rsquo;t allow connections to a
specific server. Let&amp;rsquo;s say you&amp;rsquo;re at work and imgur.com is being
blocked. To get around this we can create a tunnel through a server
which isn&amp;rsquo;t on our network and thus can access Imgur.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ssh -L 9000:imgur.com:80 user@example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The key here is &lt;code&gt;-L&lt;/code&gt; which says we&amp;rsquo;re doing local port forwarding. Then
it says we&amp;rsquo;re forwarding our local port &lt;code&gt;9000&lt;/code&gt; to &lt;code&gt;imgur.com:80&lt;/code&gt;,
which is the default port for HTTP. Now open your browser and go to
&lt;a href="http://localhost:9000"&gt;http://localhost:9000&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The awesome thing about SSH tunnels is that they are encrypted. Nobody
is going to see what sites you&amp;rsquo;re visiting, they&amp;rsquo;ll only see an SSH
connection to your server.&lt;/p&gt;

&lt;h2&gt;Connecting to a database behind a firewall&lt;/h2&gt;

&lt;p&gt;Another good example is if you need to access a port on your server
which can only be accessed from &lt;code&gt;localhost&lt;/code&gt; and not remotely.&lt;/p&gt;

&lt;p&gt;An example here is when you need to connect to a database console, which
only allows local connection for security reasons. Let&amp;rsquo;s say you&amp;rsquo;re
running PostgreSQL on your server, which by default listens on the port
&lt;code&gt;5432&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ssh -L 9000:localhost:5432 user@example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The part that changed here is the &lt;code&gt;localhost:5432&lt;/code&gt;, which says to
forward connections from your local port &lt;code&gt;9000&lt;/code&gt; to &lt;code&gt;localhost:5432&lt;/code&gt; on
your server. Now we can simply connect to our database.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ psql -h localhost -p 9000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now let&amp;rsquo;s stop here for a little bit an explain what is actually going
on. In the first example the &lt;code&gt;9000:imgur.com:80&lt;/code&gt; is actually saying
&lt;code&gt;forward my local port 9000 to imgur.com at port 80&lt;/code&gt;. You can imagine
SSH on your server actually making a connection (a tunnel) between those
two ports, one on your local machine, and one on the target destination.&lt;/p&gt;

&lt;p&gt;If we however say something like &lt;code&gt;9000:localhost:5432&lt;/code&gt;, it means
&lt;code&gt;localhost&lt;/code&gt; from the server&amp;rsquo;s perspective, not localhost on your
machine. This means &lt;code&gt;forward my local port 9000 to port 5432 on
the server&lt;/code&gt;, because when you&amp;rsquo;re on the server, &lt;code&gt;localhost&lt;/code&gt; means the
server itself.&lt;/p&gt;

&lt;p&gt;This might be a bit confusing, but it is important to understand what
the syntax actually means here.&lt;/p&gt;

&lt;h2&gt;Remote port forwarding&lt;/h2&gt;

&lt;p&gt;Now comes the second part of this tutorial, which is remote port
forwarding. This is again best to explain with an example.&lt;/p&gt;

&lt;p&gt;Say that you&amp;rsquo;re developing a Rails application on your local machine,
and you&amp;rsquo;d like to show it to a friend. Unfortunately your ISP didn&amp;rsquo;t
provide you with a public IP address, so it&amp;rsquo;s not possible to connect
to your machine directly via the internet.&lt;/p&gt;

&lt;p&gt;Sometimes this can be solved by configuring NAT (Network Address
Translation) on your router, but this doesn&amp;rsquo;t always work, and it
requires you to change the configuration on your router, which isn&amp;rsquo;t
always desirable. This solution also doesn&amp;rsquo;t work when you don&amp;rsquo;t have
admin access on your network.&lt;/p&gt;

&lt;p&gt;To fix this problem you need to have another computer, which is publicly
accessible and have SSH access to it. It can be any server on the
internet, as long as you can connect to it. We&amp;rsquo;ll tell SSH to make a
tunnel that opens up a new port on the server, and connects it to a
local port on your machine.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ssh -R 3000:localhost:9000 user@example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The syntax here is very similar to local port forwarding, with a
single change of &lt;code&gt;-L&lt;/code&gt; for &lt;code&gt;-R&lt;/code&gt;. But as with local port forwarding, the
syntax remains the same.&lt;/p&gt;

&lt;p&gt;First you need to specify a local port on your machine which you wish
to expose publicly, which in this case is &lt;code&gt;3000&lt;/code&gt;. Next there is the
address on which the server should listen to, and a port on which the
server should listen to, which in this case is &lt;code&gt;9000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There is one more thing you need to do to enable this. SSH doesn&amp;rsquo;t by
default allow remote hosts to forwarded ports. To enable this open
&lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; and add the following line somewhere in that
config file.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GatewayPorts yes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Make sure you add it only once!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo vim /etc/ssh/sshd_config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And restart SSH&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo service ssh restart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After this you should be able to connect to the server remotely, even
from your local machine. The way this would work is that you would
first create an SSH tunnel that forwards traffic from the server on
port &lt;code&gt;9000&lt;/code&gt; to your local machine on port &lt;code&gt;3000&lt;/code&gt;. This means that if
you connect to the server on port &lt;code&gt;9000&lt;/code&gt; from your local machine,
you&amp;rsquo;ll actually make a request to your machine through the SSH tunnel.&lt;/p&gt;

&lt;h2&gt;A few closing tips&lt;/h2&gt;

&lt;p&gt;You might have noticed that every time we create a tunnel you also SSH
into the server and get a shell. This isn&amp;rsquo;t usually necessary, as you&amp;rsquo;re
just trying to create a tunnel. To avoid this we can run SSH with the
&lt;code&gt;-nNT&lt;/code&gt; flags, such as the following, which will cause SSH to not
allocate a tty and only do the port forwarding.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ssh -nNT -L 9000:imgur.com:80 user@example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;SSH has a huge number of features, so I&amp;rsquo;d recommend you to checkout the
manual page at &lt;code&gt;man ssh&lt;/code&gt;, which contains even more tips.&lt;/p&gt;

&lt;p&gt;There&amp;rsquo;s also an amazing talk called &lt;a href="http://vimeo.com/54505525"&gt;The Black Magic of SSH / SSH Can Do
That?&lt;/a&gt;, which I really recommend you to
watch.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Supercharge your VIM into IDE with CTags</title>
    <link rel="alternate" href="/2014/05/09/supercharge-your-vim-into-ide-with-ctags.html"/>
    <id>/2014/05/09/supercharge-your-vim-into-ide-with-ctags.html</id>
    <published>2014-05-09T00:00:00Z</published>
    <updated>2014-05-09T00:00:00Z</updated>
    <author>
      <name>sensible.io team</name>
    </author>
    <content type="html">&lt;p&gt;CTags generates index file of all your classes, methods and all other identifiers.
You can use that index in your editor to jump straight to the methods you&amp;rsquo;re interested
in. In this article, I&amp;rsquo;ll show you how to use them with Vim and Rails.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;Installation&lt;/h2&gt;

&lt;p&gt;You need to install &lt;a href="http://ctags.sourceforge.net/"&gt;Exuberant CTags&lt;/a&gt;, on OSX just run&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ brew install ctags
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;or on Ubuntu/Debian&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo apt-get install exuberant-ctags
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Generating CTags manually&lt;/h2&gt;

&lt;p&gt;In your rails project you can generate CTags for you project with&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ctags -R --languages=ruby --exclude=.git --exclude=log .
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But what about generating CTags for our bundled libraries too? Easy task, let&amp;rsquo;s
add bundle paths&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ctags -R --languages=ruby --exclude=.git --exclude=log . $(bundle list --paths)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Usage&lt;/h2&gt;

&lt;p&gt;You can jump into the method with&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;ta&lt;/span&gt; attr_accessor
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;or using regular expressions like that&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;ta&lt;/span&gt; /^before_*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;If you position cursor over the method and hit &lt;code&gt;CTRL+]&lt;/code&gt; it will take you into the
method.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CTRL-T&lt;/code&gt; will take you back from that method.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CTRL-I&lt;/code&gt; and &lt;code&gt;CTRL-O&lt;/code&gt; will take you In and Out from the method.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;ts&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;expr&lt;span class="p"&gt;]&lt;/span&gt;  # Lists &lt;span class="k"&gt;tags&lt;/span&gt; matching expression
&lt;span class="p"&gt;:[&lt;/span&gt;count&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;tn&lt;/span&gt;  # Jumps &lt;span class="k"&gt;to&lt;/span&gt; the next matching tag
&lt;span class="p"&gt;:[&lt;/span&gt;count&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;tp&lt;/span&gt;  # Jumps &lt;span class="k"&gt;to&lt;/span&gt; the &lt;span class="k"&gt;previous&lt;/span&gt; matching tag
&lt;span class="p"&gt;:[&lt;/span&gt;count&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;tf&lt;/span&gt;  # Jumps &lt;span class="k"&gt;to&lt;/span&gt; the &lt;span class="k"&gt;first&lt;/span&gt; matching tag
&lt;span class="p"&gt;:[&lt;/span&gt;count&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;tl&lt;/span&gt;  # Jumps &lt;span class="k"&gt;to&lt;/span&gt; the last matching tag
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;CtrlP&lt;/h2&gt;

&lt;p&gt;If you&amp;rsquo;re using CtrlP, you can use &lt;code&gt;CtrlPTag&lt;/code&gt; to browser your tags. You can bind
that command to a key and add this line to your &lt;em&gt;.vimrc&lt;/em&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;leader&lt;span class="p"&gt;&amp;gt;.&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;CtrlPTag&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Getting Advanced&lt;/h2&gt;

&lt;p&gt;Since we want to DRY this workflow a little, we&amp;rsquo;ll install Ruby gem to auto-generate
those tags for us.&lt;/p&gt;

&lt;p&gt;We&amp;rsquo;ll be using &lt;a href="https://github.com/ivalkeen/guard-ctags-bundler"&gt;Guard-CTags-Bundler&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Install the gem:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ gem install guard-ctags-bundler
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Add it to your Gemfile (inside development group):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="ss"&gt;:development&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'guard-ctags-bundler'&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now add it to your &lt;em&gt;Guardfile&lt;/em&gt; with&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ guard init ctags-bundler
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now you can run &lt;code&gt;guard&lt;/code&gt; and it will start watching your files will generate &lt;em&gt;tags&lt;/em&gt;
and &lt;em&gt;gems.tags&lt;/em&gt; files. Since Vim is not looking for &lt;em&gt;gems.tags&lt;/em&gt; by default, you&amp;rsquo;ll
need to edit your &lt;em&gt;.vimrc&lt;/em&gt; and add &lt;code&gt;set tags+=gems.tags&lt;/code&gt; line, then restart Vim.&lt;/p&gt;

&lt;h2&gt;.gitignore&lt;/h2&gt;

&lt;p&gt;Since you don&amp;rsquo;t want to commit those files into the GIT index, add them to &lt;em&gt;.gitignore&lt;/em&gt;
or I like to add them to my global &lt;em&gt;~/.gitignore&lt;/em&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat &amp;lt;&amp;lt;EOT &amp;gt;&amp;gt; ~/.gitignore
tags
gems.tags
EOT
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Path depends on your configuration &lt;code&gt;git config --global core.excludesfile &amp;quot;~/.gitignore&amp;quot;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;Questions?&lt;/h2&gt;

&lt;p&gt;Vim has very nice build-in help that can be accessed by&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="p"&gt;:&lt;/span&gt;help &lt;span class="k"&gt;tags&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Bonus: Inspecting Gems&lt;/h2&gt;

&lt;p&gt;I like to inspect Gems a lot. Just set your &lt;code&gt;$EDITOR&lt;/code&gt; variable and then run command
&lt;code&gt;bundle open rails&lt;/code&gt; to open it in your favourite editor. I recommend you to try
Tim Pope&amp;rsquo;s automatic RubyGems CTags invoker &lt;a href="https://github.com/tpope/gem-ctags"&gt;gem-ctags&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Just install the gem&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ gem install gem-ctags
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and generate CTags for already installed Gems (needs to be run only first time).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ gem ctags
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title>Don't just dump code into your models</title>
    <link rel="alternate" href="/2014/04/19/don-t-just-dump-code-into-your-models.html"/>
    <id>/2014/04/19/don-t-just-dump-code-into-your-models.html</id>
    <published>2014-04-19T16:05:00Z</published>
    <updated>2014-04-19T16:05:00Z</updated>
    <author>
      <name>sensible.io team</name>
    </author>
    <content type="html">&lt;p&gt;A few years ago there used to be a motto saying &lt;em&gt;Skinny controllers, fat
models&lt;/em&gt;. It was good at the time, because people thought all of the
application code belonged into the controllers, and it helped them
realize that it&amp;rsquo;s good to have just a simple controller layer and push
things down. The problem with this motto is that it&amp;rsquo;s wrong. Just
because you should have skinny controllers it doesn&amp;rsquo;t mean you should
have fat models. In fact, none of your classes should be fat.&lt;/p&gt;

&lt;p&gt;The reason we have MVC is that it is a good starting point for
separating the concerns in your application. It makes it more obvious
where you should put your code when you&amp;rsquo;re starting out with your
application. But this doesn&amp;rsquo;t mean your application should be limited to
just these three layers, quite the opposite.&lt;/p&gt;

&lt;p&gt;Every time you need to add a new service to your application, you should
think about how you&amp;rsquo;re going to be using it, and then build a sufficient
abstraction on top of that.&lt;/p&gt;

&lt;p&gt;For example let&amp;rsquo;s say that your application needs to automatically sign
up newly registered users to a mailing list. You&amp;rsquo;ve even chosen a
provider, say AWeber or Mailchimp, as both of these have a nice Ruby gem
wrapping up their API, allowing you to subscribe the user with only a
few lines of code.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s how the naive solution might look like&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;
  &lt;span class="n"&gt;after_create&lt;/span&gt; &lt;span class="ss"&gt;:subscribe_to_mailchimp&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;subscribe_to_mailchimp&lt;/span&gt;
    &lt;span class="n"&gt;list_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"MAILCHIMP_LIST_ID"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="no"&gt;Mailchimp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"MAILCHIMP_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you happen to like YAML files more than environment variables, you
might write something like this instead&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;subscribe_to_mailchimp&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SomeGlobalYamlConfigReader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mailchimp&lt;/span&gt;
  &lt;span class="no"&gt;Mailchimp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"api_key"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"list_id"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While this might make sense the first time you try this, there are
actually many things wrong with this approach. Let&amp;rsquo;s list a few:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the Mailchimp API is unavailable during the time you decide to
create a new user, your &lt;code&gt;after_save&lt;/code&gt; callback will raise an exception.&lt;/li&gt;
&lt;li&gt;If an exception is raised, ActiveRecord will rollback the transaction
and your user won&amp;rsquo;t get created.&lt;/li&gt;
&lt;li&gt;Even if you choose to handle the exception in the callback, you&amp;rsquo;ll fail
to subscribe the user to the mailing list.&lt;/li&gt;
&lt;li&gt;Your User model becomes coupled with the Mailchimp gem. If for some
reason you later decide to switch to AWeber, you&amp;rsquo;ll have much harder
time doing so (probably because you have Mailchimp in more than one
place).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are just a few problems. There are many more, for example you
probably don&amp;rsquo;t even want to run this code in development/test
environment, which means the method should be changed to something like&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;subscribe_to_mailchimp&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;production?&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SomeGlobalYamlConfigReader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mailchimp&lt;/span&gt;
    &lt;span class="no"&gt;Mailchimp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"api_key"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"list_id"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;but this is still wrong, because you might have a staging server where
you do want to run this callback, making the method even more
complicated.&lt;/p&gt;

&lt;p&gt;But wait, there&amp;rsquo;s more. Let&amp;rsquo;s say you magically manage to overcome all
the above issues and actually decide to test this method. A thought pops
up in your head and you think &lt;em&gt;I should probably be able to handle if I
get a bad `API&lt;/em&gt;KEY&lt;code&gt;or a&lt;/code&gt;LIST&lt;em&gt;ID` which doesn&amp;rsquo;t exist on Mailchimp&lt;/em&gt;. But
you have no easy way of testing that, because your callback is tightly
coupled to the global configuration (or ENV variables). Wouldn&amp;rsquo;t it be
much nicer if you could just inject the &lt;code&gt;API_KEY&lt;/code&gt; and the &lt;code&gt;LIST_ID&lt;/code&gt; somehow?
Maybe even because you later decide that you need to subscribe different
users to different mailing lists.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s a little less wrong approach&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# notice there's no mailchimp in the name&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailMarketing&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Subscription&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:api_key&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;list_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;Mailchimp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# now whenever you need to subscribe a new user, you'd just write&lt;/span&gt;
&lt;span class="no"&gt;EmailMarketing&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Subscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;LIST_ID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Where do you get the &lt;code&gt;API_KEY&lt;/code&gt; and &lt;code&gt;LIST_ID&lt;/code&gt; from? It doesn&amp;rsquo;t really matter,
as long as it&amp;rsquo;s not in the &lt;code&gt;Subscription&lt;/code&gt; or &lt;code&gt;User&lt;/code&gt; classes that fetch
it. &lt;strong&gt;Every class should have a single reason to change, and if you need
to change your User model because you changed the way you store your
email marketing API key, you&amp;rsquo;re doing it wrong&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Where do you put this class? Again, it doesn&amp;rsquo;t really matter. Maybe
something like &lt;code&gt;lib/email_marketing/subscription&lt;/code&gt; might make sense. When
you later decide to add &lt;code&gt;lib/email_marketing/campaign&lt;/code&gt;, it won&amp;rsquo;t look as
stupid as having all that code in the models.&lt;/p&gt;

&lt;p&gt;Why isn&amp;rsquo;t &lt;code&gt;subscribe&lt;/code&gt; a class method? There are &lt;a href="http://blog.codeclimate.com/blog/2012/11/14/why-ruby-class-methods-resist-refactoring/"&gt;many reasons&lt;/a&gt;
why &lt;a href="http://nicksda.apotomo.de/2011/07/are-class-methods-evil/"&gt;you should use instance methods&lt;/a&gt;
and &lt;a href="http://mlomnicki.com/programming/ruby/2011/07/20/class-vs-instance-methods.html"&gt;save yourself some trouble&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Because of the problems mentioned earlier, the only way to solve this
issue correctly is to use a background queue such as Sidekiq or
Resque. There is one thing that&amp;rsquo;s always true for interacting with 3rd
party services, they will fail occasionally. It&amp;rsquo;s not a question of if,
it&amp;rsquo;s a question of when, and you have to be ready for it.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s completely normal that a service goes down for a few seconds or
even minutes every now and then. If you have the subscription logic in
your controller when the user is signing up, he might end up registering
an account but because the request to Mailchimp fails he actually won&amp;rsquo;t
get added to the mailing list.&lt;/p&gt;

&lt;p&gt;This is why you have to use a background service that will try to add
the user to the list, and if that fails it will automatically
re-schedule a retry.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsersController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
    &lt;span class="vi"&gt;@user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;
      &lt;span class="no"&gt;EmailSubscriptionWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;root_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;notice: &lt;/span&gt;&lt;span class="s2"&gt;"Welcome!"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:new&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailSubscriptionWorker&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Worker&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;list_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="c1"&gt;# read this from some config&lt;/span&gt;

    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;EmailMarketing&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Subscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;list_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You could also have a cron job that periodically checks if all users are
signed up for the service, as an alternative to the background worker,
but using a queue is a far superior solution.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Getting started with Ember App Kit</title>
    <link rel="alternate" href="/2014/03/07/getting-started-with-ember-app-kit.html"/>
    <id>/2014/03/07/getting-started-with-ember-app-kit.html</id>
    <published>2014-03-07T00:00:00Z</published>
    <updated>2014-03-07T00:00:00Z</updated>
    <author>
      <name>sensible.io team</name>
    </author>
    <content type="html">&lt;p&gt;In the following tutorial we’ll create a simple Ember.js app for logging your
water intake. Besides learning the basics of Ember.js, you will also learn how
to use &lt;a href="https://github.com/stefanpenner/ember-app-kit"&gt;Ember App Kit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;You can see the final application right below:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Animation of final product" src="/images/waterize-animation-4614d3ff.gif" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://demo.sensible.io/waterize"&gt;Link to Demo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;About Ember App Kit&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/stefanpenner/ember-app-kit"&gt;EAK&lt;/a&gt; is the basic building block
of your app. It helps you to rapidly start the development with features such as
the ES6 module transpiler, automatic reloading, the Grunt task runner, the Bower
package manager&amp;hellip;&lt;/p&gt;

&lt;p&gt;EAK uses ECMAScript 6 Modules, which means you can keep your namespace clean
and only import objects you need to the current scope. Thanks to
&lt;a href="https://github.com/square/es6-module-transpiler"&gt;es6-module-transpiler&lt;/a&gt; you can
use the current ES6 module syntax and it will be automatically compiled into
today&amp;rsquo;s JavaScript.&lt;/p&gt;

&lt;h2&gt;Creating a project&lt;/h2&gt;

&lt;p&gt;Create your project by cloning EAK&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➤ git clone git@github.com:stefanpenner/ember-app-kit.git waterize
➤ cd waterize
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Optionally you can get rid of the Git history and start fresh&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➤ rm -rf .git
➤ git init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Install required node binaries&lt;/h2&gt;

&lt;p&gt;This only needs to be done once. Install Grunt, Bower and Loom (if you want to use &lt;em&gt;generate&lt;/em&gt; command to easily generate controllers/models etc.).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➤ npm install -g grunt-cli bower loom
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Starting a development server&lt;/h2&gt;

&lt;p&gt;Install the required node packages and start the server&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➤ npm install
➤ grunt server
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally open our project in the web browser (port defaults to 8000).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;open http://localhost:8000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Generating basic routes and controllers&lt;/h2&gt;

&lt;p&gt;We&amp;rsquo;ll use &lt;em&gt;day&lt;/em&gt; controller for storing our water intake per that day.
Now let&amp;rsquo;s generate an object controller with Loom&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In Ember.js, controllers allow you to decorate your models with display logic. In general, your models will have properties that are saved to the server, while controllers will have properties that your app does not need to save to the server.&lt;/p&gt;

&lt;p&gt;&lt;cite&gt;&lt;a href="http://emberjs.com/guides/controllers/"&gt;Ember.js guide - Controllers&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➤ generate controller day
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt="select o" src="/images/eak-generate1-6b74438d.gif" /&gt;&lt;/p&gt;

&lt;p&gt;Select &lt;strong&gt;o&lt;/strong&gt; since we want an object controller, then generate a route for the controller&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When your application starts, the router is responsible for displaying templates, loading data, and otherwise setting up application state. It does so by matching the current URL to the routes that you&amp;rsquo;ve defined.&lt;/p&gt;

&lt;p&gt;&lt;cite&gt;&lt;a href="http://emberjs.com/guides/routing/defining-your-routes/"&gt;Ember.js guide - Defining Your Routes&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➤ generate route day
generating from:
  - node_modules/loom-generators-ember-appkit/loom
   created:     app/routes/day.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Change &lt;strong&gt;app/templates/application.hbs&lt;/strong&gt; to&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;'title'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Waterize&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;

{{outlet}}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Edit &lt;strong&gt;app/router.js&lt;/strong&gt; and the following at the top of the route list&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// We'll catch / and redirect user to current day&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"index"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Catch /#2014-03-03&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"day"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/:formatted"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Edit &lt;strong&gt;app/routes/index.js&lt;/strong&gt;, remove model and add&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;beforeModel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transitionTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"day"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"2033-12-21"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Inside &lt;code&gt;DayRoute&lt;/code&gt; in the &lt;strong&gt;app/routes/day.js&lt;/strong&gt; add snippet&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Ember&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now generate our main template showing the bottle.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➤ generate template day
generating from:
  - node_modules/loom-generators-ember-appkit/loom
   created:     app/templates/day.hbs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Bottle component&lt;/h2&gt;

&lt;p&gt;Generate a bottle component holding a bottle SVG dynamic image &amp;amp;
percentage logic.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➤ generate component bottle-image
    generating from:
      - node_modules/loom-generators-ember-appkit/loom
       created:     app/components/bottle-image.js
       created:     app/templates/components/bottle-image.hbs
       created:     tests/unit/components/bottle-image-tests.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Remove test for the component, since we won&amp;rsquo;t be using it now.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➤ rm tests/unit/components/bottle-image-tests.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Edit &lt;strong&gt;app/templates/components/bottle-image.hbs&lt;/strong&gt; and replace
everything with SVG of a
bottle. It&amp;rsquo;s simple path of the bottle, with the same clip path and a
blue rectangle that represents the water level.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight handlebars"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"169px"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"441px"&lt;/span&gt; &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 169 441"&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"1.1"&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt; &lt;span class="na"&gt;xmlns:xlink=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/1999/xlink"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;bottle&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;g&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Page-1"&lt;/span&gt; &lt;span class="na"&gt;stroke=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt; &lt;span class="na"&gt;stroke-width=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt; &lt;span class="na"&gt;fill-rule=&lt;/span&gt;&lt;span class="s"&gt;"evenodd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;clipPath&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"ClipBottle"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M114.611325,50.6484375 L48.5449223,50.6484375 L48.5449223,70.0136719 C48.5449223,70.0136719 22.787939,81.0417179 15.7187505,87.0292969 C8.15080179,93.4393231 4.63351106,107.20649 4.63351106,107.20649 L4.63351106,403.066413 C4.63351106,403.066413 17.3756986,431.116187 81.3929257,431.116211 C145.410153,431.116241 158.15234,403.066406 158.15234,403.066406 L158.15234,107.20649 C158.15234,107.20649 153.633342,93.2511626 145.410153,87.0292969 C137.247926,80.8535568 114.611325,70.0136719 114.611325,70.0136719 L114.611325,50.6484375 Z M114.611325,50.6484375"&lt;/span&gt; &lt;span class="na"&gt;stroke=&lt;/span&gt;&lt;span class="s"&gt;"#1EB5E8"&lt;/span&gt; &lt;span class="na"&gt;stroke-width=&lt;/span&gt;&lt;span class="s"&gt;"8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/clipPath&amp;gt;&lt;/span&gt;

      &lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M10,206 L10,432 L161,432 L161,206 L10,206 Z M10,206"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Water"&lt;/span&gt; &lt;span class="na"&gt;stroke=&lt;/span&gt;&lt;span class="s"&gt;"#979797"&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"#1EB5E8"&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;"8"&lt;/span&gt; &lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;bind-attr&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"y"&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"151"&lt;/span&gt; &lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;bind-attr&lt;/span&gt; &lt;span class="nv"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"height"&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt; &lt;span class="na"&gt;clip-path=&lt;/span&gt;&lt;span class="s"&gt;"url(#ClipBottle)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/rect&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M114.611325,50.6484375 L48.5449223,50.6484375 L48.5449223,70.0136719 C48.5449223,70.0136719 22.787939,81.0417179 15.7187505,87.0292969 C8.15080179,93.4393231 4.63351106,107.20649 4.63351106,107.20649 L4.63351106,403.066413 C4.63351106,403.066413 17.3756986,431.116187 81.3929257,431.116211 C145.410153,431.116241 158.15234,403.066406 158.15234,403.066406 L158.15234,107.20649 C158.15234,107.20649 153.633342,93.2511626 145.410153,87.0292969 C137.247926,80.8535568 114.611325,70.0136719 114.611325,70.0136719 L114.611325,50.6484375 Z M114.611325,50.6484375"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Bottle"&lt;/span&gt; &lt;span class="na"&gt;stroke=&lt;/span&gt;&lt;span class="s"&gt;"#1EB5E8"&lt;/span&gt; &lt;span class="na"&gt;stroke-width=&lt;/span&gt;&lt;span class="s"&gt;"8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M47.99606,0 C43.579958,0 40,3.58204887 40,7.99357759 L40,36.0064224 C40,40.4211534 43.5797154,44 47.99606,44 L115.00394,44 C119.420042,44 123,40.4179511 123,36.0064224 L123,7.99357759 C123,3.57884659 119.420285,0 115.00394,0 L47.99606,0 Z M47.99606,0"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"Cap"&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"#1EB5E8"&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;"40"&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"83"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"44"&lt;/span&gt; &lt;span class="na"&gt;rx=&lt;/span&gt;&lt;span class="s"&gt;"8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/rect&amp;gt;&lt;/span&gt;

      &lt;span class="nt"&gt;&amp;lt;text&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"#000000"&lt;/span&gt; &lt;span class="na"&gt;font-family=&lt;/span&gt;&lt;span class="s"&gt;"Arial"&lt;/span&gt; &lt;span class="na"&gt;font-size=&lt;/span&gt;&lt;span class="s"&gt;"32"&lt;/span&gt; &lt;span class="na"&gt;font-weight=&lt;/span&gt;&lt;span class="s"&gt;"bold"&lt;/span&gt; &lt;span class="na"&gt;letter-spacing=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;tspan&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;"43"&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;"233"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;percent&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt; %&lt;span class="nt"&gt;&amp;lt;/tspan&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/text&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/g&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Edit &lt;strong&gt;app/components/bottle-image.js&lt;/strong&gt; and add code for handling
percentage, water levels.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;BottleImageComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Ember&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// in ml&lt;/span&gt;

  &lt;span class="na"&gt;percent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"drunk"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"goal"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Calculate percentage of a goal (can be 100%+)&lt;/span&gt;
  &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"drunk"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

  &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;430&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Offset of the rectangle&lt;/span&gt;
  &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

  &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;3.75&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"percent"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Height of the rectangle&lt;/span&gt;
  &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"percent"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;BottleImageComponent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Edit &lt;strong&gt;app/templates/day.hbs&lt;/strong&gt; and replace everything with a bottle component, we&amp;rsquo;ll use a fixed drunk value for
now.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight handlebars"&gt;&lt;code&gt;&lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;bottle-image&lt;/span&gt; &lt;span class="nv"&gt;drunk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;500&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;A model is a class that defines the properties and behavior of the data that you present to the user. Anything that the user expects to see if they leave your app and come back later (or if they refresh the page) should be represented by a model.&lt;/p&gt;

&lt;p&gt;&lt;cite&gt;&lt;a href="http://emberjs.com/guides/models/defining-models/"&gt;Ember.js guide - Defining Models&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Create &lt;strong&gt;app/models/day.js&lt;/strong&gt; and fill it with basic model that will save
our stats&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Ember&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;drunk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;

  &lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Implement me&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reopenClass&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conditions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Adding model to the equation&lt;/h2&gt;

&lt;p&gt;We can now use our model in our routes, so edit &lt;strong&gt;app/routes/day.js&lt;/strong&gt; and
at the top add&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"appkit/models/day"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ES6 import, you need to import model, so it's accessible inside your route&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;to import our model and replace&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Ember&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;with&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;formatted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Edit &lt;strong&gt;app/templates/day.hbs&lt;/strong&gt; and replace fixed number &lt;em&gt;500&lt;/em&gt; to &lt;em&gt;drunk&lt;/em&gt;
so our day.hbs will look like this now&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;bottle&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt; &lt;span class="nx"&gt;drunk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;drunk&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Drinking a cup!&lt;/h2&gt;

&lt;p&gt;Now edit &lt;strong&gt;app/controllers/day.js&lt;/strong&gt; so it looks like this chunk of code&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;DayController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Ember&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ObjectController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;cups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ml&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"250 ml / 8.45 oz"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ml&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"500 ml / 16.9 oz"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;

  &lt;span class="na"&gt;selectedCup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;drinkCup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"selectedCup"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;incrementProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"drunk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ml&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="na"&gt;emptyBottle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"drunk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;DayController&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we&amp;rsquo;ll add some HTML controls. Edit &lt;strong&gt;app/templates/day.hbs&lt;/strong&gt; and under the component add&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight handlebars"&gt;&lt;code&gt;&lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;view&lt;/span&gt; &lt;span class="nv"&gt;Ember&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;Select&lt;/span&gt;
       &lt;span class="nv"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;cups&lt;/span&gt;
       &lt;span class="nv"&gt;optionValuePath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"content.ml"&lt;/span&gt;
       &lt;span class="nv"&gt;optionLabelPath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"content.name"&lt;/span&gt;
       &lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;selectedCup&lt;/span&gt;
&lt;span class="k"&gt;}}&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;action&lt;/span&gt; &lt;span class="s1"&gt;'drinkCup'&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Drink!&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;action&lt;/span&gt; &lt;span class="s1"&gt;'emptyBottle'&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;X&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Making our data persistent&lt;/h2&gt;

&lt;p&gt;To easily persist our data, we&amp;rsquo;ll use localStorage with a hash of date and ml
drunk as keys. When it comes to time handling, the easiest way is to use
&lt;a href="http://momentjs.com"&gt;Moment.js&lt;/a&gt;. Let&amp;rsquo;s install it with Bower&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➤ bower install moment --save
bower cached        git://github.com/moment/moment.git#2.5.1
bower validate      2.5.1 against git://github.com/moment/moment.git#*
bower install       moment#2.5.1
moment#2.5.1 vendor/moment
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we have MomentJS under vendor/moment, let&amp;rsquo;s include it on our HTML
page.&lt;/p&gt;

&lt;p&gt;Edit &lt;strong&gt;app/index.html&lt;/strong&gt; and under jquery.js add line&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/vendor/moment/moment.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now it&amp;rsquo;s time to implement the persistence part in &lt;strong&gt;app/models/day.js&lt;/strong&gt;.
We&amp;rsquo;ll replace everything with our model implementation&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Ember&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// Returns instance of moment for the given timestamp&lt;/span&gt;
  &lt;span class="na"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

  &lt;span class="c1"&gt;// Return formatted date&lt;/span&gt;
  &lt;span class="na"&gt;formatted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"moment"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"YYYY-MM-DD"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"moment"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

  &lt;span class="c1"&gt;// We'll use this as a key for the storage&lt;/span&gt;
  &lt;span class="na"&gt;storageKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"%@|%@"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"formatted"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"formatted"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

  &lt;span class="c1"&gt;// ml drunk&lt;/span&gt;
  &lt;span class="na"&gt;drunk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;drunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"storageKey"&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;
    &lt;span class="nx"&gt;drunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;drunk&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;drunk&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"storageKey"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

  &lt;span class="c1"&gt;// Write value into localStorage&lt;/span&gt;
  &lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"storageKey"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"drunk"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reopenClass&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"waterize"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Namespace in the localStorage&lt;/span&gt;

  &lt;span class="c1"&gt;// Query by timestamp&lt;/span&gt;
  &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conditions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conditions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;formatted&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;startOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"day"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;today&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;formatted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Wire those model changes up into the routes&lt;/h3&gt;

&lt;p&gt;Edit &lt;strong&gt;app/routes/index.js&lt;/strong&gt; and at the top of route add&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"appkit/models/day"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and change transitionTo to&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transitionTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"day"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;today&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;so when we&amp;rsquo;re on the / page, it will redirect us to the current day.&lt;/p&gt;

&lt;p&gt;Then edit &lt;strong&gt;app/routes/day.js&lt;/strong&gt; and change that query part to&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;formatted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;formatted&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;this will return the day based on the url params.&lt;/p&gt;

&lt;p&gt;Now visit &lt;a href="http://localhost:8000"&gt;http://localhost:8000&lt;/a&gt; and it should redirect
you to the current day, perfect! If you change the date, the bottle percentage
should automatically update.&lt;/p&gt;

&lt;h2&gt;Switching between the days&lt;/h2&gt;

&lt;p&gt;We&amp;rsquo;ll need to add 2 more instance methods into our model &lt;strong&gt;app/models/day.js&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// Return next day&lt;/span&gt;
  &lt;span class="nx"&gt;tomorrow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;tommorow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"moment"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"day"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;isAfter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tommorow&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tommorow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"moment"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

  &lt;span class="c1"&gt;// Return previous day&lt;/span&gt;
  &lt;span class="nx"&gt;yesterday&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"moment"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;subtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"day"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"moment"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;so our &lt;strong&gt;app/models/day.js&lt;/strong&gt; looks like this&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Ember&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// Returns instance of moment for the given timestamp&lt;/span&gt;
  &lt;span class="na"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

  &lt;span class="c1"&gt;// Return formatted date&lt;/span&gt;
  &lt;span class="na"&gt;formatted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"moment"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"YYYY-MM-DD"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"moment"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

  &lt;span class="c1"&gt;// We'll use this as a key for the storage&lt;/span&gt;
  &lt;span class="na"&gt;storageKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"%@|%@"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"formatted"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"formatted"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

  &lt;span class="c1"&gt;// ml drunk&lt;/span&gt;
  &lt;span class="na"&gt;drunk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;drunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"storageKey"&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;
    &lt;span class="nx"&gt;drunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;drunk&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;drunk&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"storageKey"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

  &lt;span class="c1"&gt;// Return next day&lt;/span&gt;
  &lt;span class="na"&gt;tomorrow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;tommorow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"moment"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"day"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;isAfter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tommorow&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tommorow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"moment"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

  &lt;span class="c1"&gt;// Return previous day&lt;/span&gt;
  &lt;span class="na"&gt;yesterday&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"moment"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;subtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"day"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"moment"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

  &lt;span class="c1"&gt;// Write value into localStorage&lt;/span&gt;
  &lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"storageKey"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"drunk"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reopenClass&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"waterize"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Namespace in the localStorage&lt;/span&gt;

  &lt;span class="c1"&gt;// Query by timestamp&lt;/span&gt;
  &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conditions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conditions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;formatted&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;startOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"day"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;today&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;formatted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Day&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we need some links to take us to previous/next days, so let&amp;rsquo;s edit &lt;strong&gt;app/templates/day.hbs&lt;/strong&gt; and at the top add&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight handlebars"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;{{#&lt;/span&gt;&lt;span class="nn"&gt;link-to&lt;/span&gt; &lt;span class="s1"&gt;'index'&lt;/span&gt; &lt;span class="nv"&gt;classNames&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"today"&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;Today&lt;span class="k"&gt;{{/&lt;/span&gt;&lt;span class="nn"&gt;link-to&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;{{#&lt;/span&gt;&lt;span class="nn"&gt;link-to&lt;/span&gt; &lt;span class="s1"&gt;'day'&lt;/span&gt; &lt;span class="nv"&gt;yesterday&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;&lt;span class="ni"&gt;&amp;amp;laquo;&lt;/span&gt;&lt;span class="k"&gt;{{/&lt;/span&gt;&lt;span class="nn"&gt;link-to&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;
Date: &lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;formatted&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;
&lt;span class="k"&gt;{{#if&lt;/span&gt; &lt;span class="nv"&gt;tomorrow&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;
&lt;span class="k"&gt;{{#&lt;/span&gt;&lt;span class="nn"&gt;link-to&lt;/span&gt; &lt;span class="s1"&gt;'day'&lt;/span&gt; &lt;span class="nv"&gt;tomorrow&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;&lt;span class="ni"&gt;&amp;amp;raquo;&lt;/span&gt;&lt;span class="k"&gt;{{/&lt;/span&gt;&lt;span class="nn"&gt;link-to&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;
&lt;span class="k"&gt;{{/if}}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Testing&lt;/h2&gt;

&lt;p&gt;Let&amp;rsquo;s add only very simple acceptance test&lt;/p&gt;

&lt;p&gt;Remove route test, because we&amp;rsquo;ve changed that route a little and it
would raise an test error.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➤ rm tests/unit/routes/index-test.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now edit &lt;strong&gt;tests/acceptance/index-test.js&lt;/strong&gt; and change that test part so it looks like this chunk of code&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Acceptances - Index'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;startApp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;teardown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Ember&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'destroy'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'index renders'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;today_link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'a.today'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;today_link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;'Today'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now run the tests with&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➤ grunt test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;BONUS for Free: Adding off-line cache manifest&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➤ npm install grunt-manifest -—save-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Create Grunt task in &lt;strong&gt;tasks/custom-options/manifest.js&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;grunt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;grunt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadNpmTasks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'grunt-manifest'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;basePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'dist'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'http://*'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'https://*'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;preferOnline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;master&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'index.html'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="s1"&gt;'assets/*.min.js'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s1"&gt;'assets/*.min.css'&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'dist/manifest.cache'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;hellip;and change html line in app/index.html to&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;!&lt;/span&gt;&lt;span class="na"&gt;--&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;if&lt;/span&gt; &lt;span class="na"&gt;dist=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt; &lt;span class="na"&gt;--&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; manifest="/manifest.cache"&lt;span class="c"&gt;&amp;lt;!-- @endif --&amp;gt;&lt;/span&gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We&amp;rsquo;ll use the manifest file only for distribution builds and disable it for development.&lt;/p&gt;

&lt;p&gt;Edit &lt;strong&gt;Gruntfile.js&lt;/strong&gt; and add our &amp;lsquo;manifest&amp;rsquo; task to the bottom of the
&lt;strong&gt;createDistVersion&lt;/strong&gt; so the end of the task looks like this chunk&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;grunt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'createDistVersion'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filterAvailable&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="s1"&gt;'htmlmin:dist'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Removes comments and whitespace&lt;/span&gt;
    &lt;span class="s1"&gt;'manifest'&lt;/span&gt;
    &lt;span class="p"&gt;]));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now kill your development server and run&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➤ grunt server:dist
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;hellip;to start a server with your distribution build. Browse your code, terminate the server and reload the page. Everything should work offline now.&lt;/p&gt;

&lt;p&gt;Source of the final product can be found here: &lt;a href="https://github.com/cyner/waterize"&gt;github.com/cyner/waterize&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Updated 2014-03-17 - Fix typos&lt;/em&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>4 Tips for Working with Dates in PostgreSQL</title>
    <link rel="alternate" href="/2013/08/26/4-tips-for-working-with-dates-in-postgresql.html"/>
    <id>/2013/08/26/4-tips-for-working-with-dates-in-postgresql.html</id>
    <published>2013-08-26T11:47:00Z</published>
    <updated>2013-08-26T11:47:00Z</updated>
    <author>
      <name>sensible.io team</name>
    </author>
    <content type="html">&lt;p&gt;Those of us who come from Rails aren&amp;rsquo;t surprised when we see something like
&lt;code&gt;5.weeks.from_now&lt;/code&gt; or &lt;code&gt;3.days.ago + 2.hours&lt;/code&gt;, which makes working with dates
much easier. But PostgreSQL got your back on this as well, you can just use the
builtin functions and get most of the same functionality.&lt;/p&gt;

&lt;h3&gt;Current Time/Date/Timestamp&lt;/h3&gt;

&lt;p&gt;There are many ways of getting a current time, but first we need to distinguish
between two types&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;always returns current value (&lt;code&gt;clock_timestamp()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;always returns current value, unless in a transaction, in which case it returns the value from the beginning of the transaction (&lt;code&gt;now()&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let&amp;rsquo;s take a look at an example&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;postgres=# BEGIN;
postgres=# SELECT now();
              now
-------------------------------
 2013-08-26 12:17:43.182331+02

postgres=# SELECT now();
              now
-------------------------------
 2013-08-26 12:17:43.182331+02

postgres=# SELECT clock_timestamp();
        clock_timestamp
-------------------------------
 2013-08-26 12:17:50.698413+02

postgres=# SELECT clock_timestamp();
        clock_timestamp
-------------------------------
 2013-08-26 12:17:51.123905+02
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, &lt;code&gt;clock_timestamp()&lt;/code&gt; changes every time the statement is
executed, but &lt;code&gt;now()&lt;/code&gt; always returns the same value. It&amp;rsquo;s also worth noting
that both of these functions take timezone into account.&lt;/p&gt;

&lt;h3&gt;Time interval, aka &lt;code&gt;3.days.ago&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;You can easily create time intervals using the &lt;code&gt;interval&lt;/code&gt; operator, for example&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;interval &amp;#39;1 day&amp;#39;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;interval &amp;#39;5 days&amp;#39;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;interval &amp;#39;5 days&amp;#39; + interval &amp;#39;3 hours&amp;#39;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;interval &amp;#39;5 days 3 hours&amp;#39;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, we can do simple math using the interval operator, which makes
it very easy to construct things like &lt;code&gt;3.days.ago&lt;/code&gt; just by doing the following&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;postgres=# SELECT now() - interval '3 days';
           ?column?
-------------------------------
 2013-08-23 12:23:40.069717+02
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Extracting the day of the week and more&lt;/h3&gt;

&lt;p&gt;Sometimes you just want to know the day of the week for a given date, or the
century, or just the day. PostgreSQL has an &lt;code&gt;extract()&lt;/code&gt; function which does
just this.&lt;/p&gt;

&lt;p&gt;Just to put this into context the examples were executed on Monday, August 26.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;postgres=# SELECT extract(DAY FROM now());
 date_part
-----------
        26

postgres=# SELECT extract(DOW FROM now());
 date_part
-----------
         1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can do much more with &lt;code&gt;extract()&lt;/code&gt;, for a complete list of examples &lt;a href="http://www.postgresql.org/docs/9.2/static/functions-datetime.html"&gt;take a look at the official documentation&lt;/a&gt;. Here&amp;rsquo;s just a few&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;day&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;century&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dow&lt;/code&gt; (day of week)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;doy&lt;/code&gt; (day of year)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;minute&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;month&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;year&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Converting between timezones&lt;/h3&gt;

&lt;p&gt;Sometimes it is useful to show a specific date in a different timezone, which is exactly what the &lt;code&gt;AT TIME ZONE&lt;/code&gt; construct is for. Let&amp;rsquo;s take a look at how it works. We&amp;rsquo;ll do this in a transaction so that the &lt;code&gt;now()&lt;/code&gt; function always returns a same value and we can easily see the difference in hours.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;postgres=# BEGIN;
BEGIN
postgres=# SELECT now();
              now
-------------------------------
 2013-08-26 12:39:39.122218+02

postgres=# SELECT now() AT TIME ZONE 'GMT';
          timezone
----------------------------
 2013-08-26 10:39:39.122218

postgres=# SELECT now() AT TIME ZONE 'GMT+1';
          timezone
----------------------------
 2013-08-26 09:39:39.122218

postgres=# SELECT now() AT TIME ZONE 'PST';
          timezone
----------------------------
 2013-08-26 02:39:39.122218
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title>PostgreSQL Sequences and Array Column Types</title>
    <link rel="alternate" href="/2013/08/24/postgresql-sequences-and-array-column-types.html"/>
    <id>/2013/08/24/postgresql-sequences-and-array-column-types.html</id>
    <published>2013-08-24T14:21:00Z</published>
    <updated>2013-08-24T14:21:00Z</updated>
    <author>
      <name>sensible.io team</name>
    </author>
    <content type="html">&lt;p&gt;This article is a &lt;a href="http://darthdeus.github.io/blog/2013/08/19/postgresql-basics-by-example/"&gt;sequel to our PostgreSQL
series&lt;/a&gt;,
which is aimed to teach you how to get the most out of your database.
You might have been led by Active Record (or Rails in general) that it
is a good idea to completely abstract away the database, but that it&amp;rsquo;s
hardly ever possible.&lt;/p&gt;

&lt;p&gt;If you plan on switching databases on any larger-than-small application, you&amp;rsquo;re
going to have to do some manual work anyway. Every database is special and you
should use it as such, instead of just settling for the lowest common
denominator.&lt;/p&gt;

&lt;p&gt;There are many features in PostgreSQL that can help you develop web
applications, such as the array &amp;amp; json column types, hstore, PostGIS and much
more. In this article we&amp;rsquo;re going to take a look at &lt;em&gt;arrays&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Every one of us remembers the moment when you first learned about databases and
you were told that if you want to store multiple values in one column you have
to split that in a 1:N relationship, because each column can only hold one
value. Well, that&amp;rsquo;s not true in the world of PostgreSQL. You are free to create
array columns with arbitrary length. You can even perform array-like queries on
them.&lt;/p&gt;

&lt;p&gt;But first we need to start by creating a table. We&amp;rsquo;ll do this with the most
obvious example - posts with multiple tags. Each post has a title, content and
an arbitrary number of tags. We also want to be able to select all posts with a
specific tag.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s first create a new database so that we can play around and drop it at the
end of out session, keeping our machine clean.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ psql -U darth postgres
postgres=# CREATE DATABASE test TEMPLATE template0;
CREATE DATABASE
postgres=# \c test;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can create our &lt;code&gt;posts&lt;/code&gt; table.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="n"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="n"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="n"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)[]&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="s1"&gt;'{}'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test=# \d posts
                                  Table "public.posts"
 Column  |           Type           |                     Modifiers
---------+--------------------------+----------------------------------------------------
 id      | integer                  | not null default nextval('posts_id_seq'::regclass)
 title   | character varying(255)   | not null
 content | text                     | not null
 tags    | character varying(255)[] | default '{}'::character varying[]
Indexes:
    "posts_pkey" PRIMARY KEY, btree (id)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But let&amp;rsquo;s stop here for a moment and take a look at our &lt;code&gt;CREATE TABLE&lt;/code&gt; query in
more depth. First we&amp;rsquo;re defining our &lt;code&gt;id&lt;/code&gt; column as &lt;code&gt;SERIAL PRIMARY KEY&lt;/code&gt;. The
&lt;code&gt;PRIMARY KEY&lt;/code&gt; is pretty self explanatory, but what about the &lt;code&gt;SERIAL&lt;/code&gt; attribute?
If you come from the world of MySQL you probably know this as &lt;code&gt;AUTO INCREMENT&lt;/code&gt;,
but there&amp;rsquo;s more to it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="n"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="n"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="n"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)[]&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="s1"&gt;'{}'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;PostgreSQL will actually create a &lt;code&gt;SEQUENCE&lt;/code&gt; for the &lt;em&gt;auto increment key&lt;/em&gt; and
use it to generate the default value. The &lt;code&gt;SERIAL&lt;/code&gt; keyword here is merely an
alias of the following.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test=# DROP TABLE posts;
DROP TABLE

test=# CREATE SEQUENCE posts_id_seq;
CREATE SEQUENCE

test=# CREATE TABLE posts (
  id INT PRIMARY KEY DEFAULT nextval('posts_id_seq'),
  title VARCHAR(255) NOT NULL,
  content TEXT NOT NULL,
  tags VARCHAR(255)[] DEFAULT '{}'
);
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "posts_pkey" for table "posts"
CREATE TABLE

test=# ALTER SEQUENCE posts_id_seq OWNED BY posts.id;
ALTER SEQUENCE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now you might be asking why in the world would you want to do it the more
complicated way, instead of using just a simple &lt;code&gt;SERIAL&lt;/code&gt; attribute. What if you
wanted the &lt;code&gt;id&lt;/code&gt; to increment by 2? Or start at a different index than 0. Well
that&amp;rsquo;s easy to do just by creating a custom &lt;code&gt;SEQUENCE&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test=# CREATE SEQUENCE derp START 1024 INCREMENT 16;
CREATE SEQUENCE

test=# SELECT nextval('derp');
 nextval
---------
    1024
(1 row)

test=# SELECT nextval('derp');
 nextval
---------
    1040
(1 row)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There are many more options you can pass in here, which is why I&amp;rsquo;d recommend you
to take a look at &lt;a href="http://www.postgresql.org/docs/8.1/static/sql-createsequence.html"&gt;the official documentation for PostgreSQL
&lt;code&gt;SEQUENCE&lt;/code&gt;s&lt;/a&gt;
if this sounds interesting. But now back to array columns.&lt;/p&gt;

&lt;h3&gt;Defining array column types&lt;/h3&gt;

&lt;p&gt;The way we tell PostgreSQL that a column type is an array is by simply appending
&lt;code&gt;[]&lt;/code&gt; at the end of the type, such as the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;things&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;names&lt;/span&gt; &lt;span class="n"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)[],&lt;/span&gt;
  &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="n"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="n"&gt;descriptions&lt;/span&gt; &lt;span class="n"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In our example code we&amp;rsquo;re also defining a default value, in this case an empty
array, which is defined as &lt;code&gt;&amp;#39;{}&amp;#39;&lt;/code&gt; (the single quotes are important here). If we
wanted a different default value, we can simply put it in the curly brackets
&lt;code&gt;&amp;#39;{thing}&amp;#39;&lt;/code&gt;. Note that these arrays columns can also be indexed and thus
lighting fast:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_test&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;things&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;GIN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;names&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now that we know the syntax, we can actually start inserting some
data.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test=# INSERT INTO posts (title, content, tags) VALUES ('sample post', 'lorem ipsum', '{apple,orange}');
INSERT 0 1

test=# INSERT INTO posts (title, content, tags) VALUES ('another post', 'fruits are bad', '{apple,hamburger}');
INSERT 0 1

test=# SELECT * FROM posts;
 id |    title     |    content     |       tags
----+--------------+----------------+-------------------
  1 | sample post  | lorem ipsum    | {apple,orange}
  2 | another post | fruits are bad | {apple,hamburger}
(2 rows)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The advantage of doing this over just serializing the tags as a string (for
example &amp;ldquo;apple,hamburger&amp;rdquo;) is that PostgreSQL knows it&amp;rsquo;s an array and it can
perform operations on it. We can easily select posts with a single tag.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test=# SELECT title FROM posts WHERE 'apple' = ANY(tags);
    title
--------------
 sample post
 another post
(2 rows)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can also update a specific element of an array (notice that the indexing
starts at 1 by default).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test=# UPDATE posts SET tags[1] = 'potato' WHERE id = 1;
UPDATE 1

test=# SELECT * FROM posts;
 id |    title     |    content     |       tags
----+--------------+----------------+-------------------
  2 | another post | fruits are bad | {apple,hamburger}
  1 | sample post  | lorem ipsum    | {potato,orange}
(2 rows)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There&amp;rsquo;s a lot operations that are supported right of the box, you can see the full list &lt;a href="http://www.postgresql.org/docs/9.2/static/functions-array.html"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This all about covers the basics of using array columns. There are more things
which you can do, for example multi-dimensional arrays, but I would encourage
you to &lt;a href="http://www.postgresql.org/docs/8.0/static/arrays.html"&gt;take a look at the official PostgreSQL
documentation&lt;/a&gt;, as it
explains everything in details.&lt;/p&gt;

&lt;p&gt;If you&amp;rsquo;re using Rails 4, you can now make use of the array columns without the
need for gems like &lt;a href="https://github.com/dockyard/postgres_ext"&gt;postgres_ext&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateUsers&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&lt;/span&gt;
    &lt;span class="n"&gt;create_table&lt;/span&gt; &lt;span class="ss"&gt;:users&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="ss"&gt;:username&lt;/span&gt;
      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="ss"&gt;:roles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;array: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;

      &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timestamps&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;One closing thought, it is important to think before using an array column. This
is not a replacement for normalization and you should really think about the way
you plan on using the data. If, for example, you wanted to create a dedicated page
where you manage all of your tags, assign them to posts and so on, using an
array column is probably not the best choice.&lt;/p&gt;

&lt;p&gt;The following articles will cover things like JSON column types, hstore,
migrating data from one type to another and much more.&lt;/p&gt;
</content>
  </entry>
</feed>
