<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://illuminatedcomputing.com/">
  <id>https://illuminatedcomputing.com/</id>
  <title>Illuminated Computing</title>
  <updated>2023-10-16T00:00:00Z</updated>
  <link rel="alternate" href="https://illuminatedcomputing.com/" type="text/html"/>
  <link rel="self" href="https://illuminatedcomputing.com/tags/rails/atom.xml" type="application/atom+xml"/>
  <author>
    <name>Paul A. Jungwirth</name>
    <uri>https://illuminatedcommputing.com/</uri>
  </author>
  <entry>
    <id>tag:illuminatedcomputing.com,2023-10-16:/posts/2023/10/rails-actionmailer/</id>
    <title type="html">Rails ActionMailer Internals</title>
    <published>2023-10-16T00:00:00Z</published>
    <updated>2023-10-16T00:00:00Z</updated>
    <link rel="alternate" href="https://illuminatedcomputing.com/posts/2023/10/rails-actionmailer/" type="text/html"/>
    <content type="html">
&lt;p&gt;When it comes to sending email in Rails, I’ve wondered for years about the gap between this:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="class"&gt;UserMailer&lt;/span&gt; &amp;lt; &lt;span class="constant"&gt;ApplicationMailer&lt;/span&gt;
  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;welcome&lt;/span&gt;(user)
    &lt;span class="instance-variable"&gt;@user&lt;/span&gt; = user
    mail(&lt;span class="key"&gt;to&lt;/span&gt;: user.email)
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and this:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="class"&gt;User&lt;/span&gt;
  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;send_welcome_notification&lt;/span&gt;
    &lt;span class="constant"&gt;UserMailer&lt;/span&gt;.welcome(&lt;span class="predefined-constant"&gt;self&lt;/span&gt;).deliver_later
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We are defining an &lt;em&gt;instance method&lt;/em&gt;, but we are calling a &lt;em&gt;class method&lt;/em&gt;. What’s going on there? I finally decided to take a closer look.&lt;/p&gt;

&lt;p&gt;Well naturally this is implemented by &lt;a href="https://github.com/rails/rails/blob/main/actionmailer/lib/action_mailer/base.rb#L628-L635"&gt;&lt;code&gt;method_missing&lt;/code&gt;&lt;/a&gt;. When you call &lt;code&gt;UserMailer.welcome&lt;/code&gt;, the class will call your instance method—sort of! Actually &lt;code&gt;method_missing&lt;/code&gt; just returns a &lt;a href="https://api.rubyonrails.org/v7.0.8/classes/ActionMailer/MessageDelivery.html"&gt;&lt;code&gt;MessageDelivery&lt;/code&gt;&lt;/a&gt; object, which provides lazy evaluation. It’s like a promise (but not asynchronous). Your method doesn’t get called until you resolve the “promise,” which normally would happen when you say &lt;code&gt;deliver_now&lt;/code&gt;. You can also call &lt;a href="https://api.rubyonrails.org/v7.0.8/classes/ActionMailer/MessageDelivery.html#method-i-message"&gt;&lt;code&gt;#message&lt;/code&gt;&lt;/a&gt; which must resolve the promise (and returns whatever your method returned—sort of!).&lt;/p&gt;

&lt;p&gt;What if you say &lt;code&gt;deliver_later&lt;/code&gt;? That &lt;em&gt;still&lt;/em&gt; doesn’t call your method. Instead it queues up a job, and later &lt;em&gt;that&lt;/em&gt; will say &lt;code&gt;deliver_now&lt;/code&gt; to finally call your method.&lt;/p&gt;

&lt;p&gt;But if you’re using Sidekiq (with &lt;code&gt;config.active_job.queue_adapter = :sidekiq&lt;/code&gt;), you might wonder how that &lt;code&gt;#welcome&lt;/code&gt; method works, since we’re passing a &lt;code&gt;User&lt;/code&gt; class and Sidekiq &lt;a href="https://github.com/sidekiq/sidekiq/wiki/Best-Practices#1-make-your-job-parameters-small-and-simple"&gt;can only serialize primitive types&lt;/a&gt;. But it does work! The trick is that Rails’ &lt;a href="https://github.com/sidekiq/sidekiq/blob/main/lib/active_job/queue_adapters/sidekiq_adapter.rb#L21-L26"&gt;queue adapter for Sidekiq&lt;/a&gt; does its own serialization before handing off the job to Sidekiq, and it tells Sidekiq to run &lt;a href="https://github.com/sidekiq/sidekiq/blob/main/lib/active_job/queue_adapters/sidekiq_adapter.rb#L66-L75"&gt;its own Worker subclass&lt;/a&gt; that will deserialize things correctly.&lt;/p&gt;

&lt;p&gt;All this assumes that your mailer method returns a &lt;a href="https://api.rubyonrails.org/classes/Mail/Message.html"&gt;&lt;code&gt;Mail::Message&lt;/code&gt;&lt;/a&gt; instance. That’s what &lt;a href="https://api.rubyonrails.org/v7.0.8/classes/ActionMailer/Base.html#method-i-mail"&gt;&lt;code&gt;#mail&lt;/code&gt;&lt;/a&gt; is giving you. But what if you &lt;em&gt;don’t&lt;/em&gt;? What if you call &lt;code&gt;mail&lt;/code&gt; but not as the last line of your method? What if you call it more than once?&lt;/p&gt;

&lt;p&gt;Well actually &lt;a href="https://github.com/rails/rails/blob/main/actionmailer/lib/action_mailer/base.rb#L870"&gt;&lt;code&gt;#mail&lt;/code&gt;&lt;/a&gt; (linking to the source code this time) remembers the message it generated, so even if you don’t return that from your own method, Rails will still send it properly. In fact it doesn’t matter what your own method returns!&lt;/p&gt;

&lt;p&gt;And if you call &lt;code&gt;#mail&lt;/code&gt; multiple times, then Rails will return early and do nothing for the second and third calls—sort of! If you pass any arguments or a block, then Rails will evaluate it again. But it still only knows how to store &lt;em&gt;one&lt;/em&gt; &lt;code&gt;Message&lt;/code&gt;. So when you finally call &lt;code&gt;deliver_now&lt;/code&gt;, only one email will go out (ask me how I know).&lt;/p&gt;

&lt;p&gt;Btw it turns out this is pretty much all documented on the &lt;a href="https://github.com/rails/rails/blob/main/actionmailer/lib/action_mailer/base.rb"&gt;&lt;code&gt;ActionMailer::Base&lt;/code&gt;&lt;/a&gt; class, but it’s not really covered in the &lt;a href="https://guides.rubyonrails.org/action_mailer_basics.html"&gt;Rails Guide&lt;/a&gt;, so I never came across it. I only found those docs when I decided to read the code. I don’t know if other Rails devs spend much time reading Rails’ own code, but I’ve found it helpful again and again. It’s not hard and totally worth it!&lt;/p&gt;

&lt;p&gt;Another trick I’ve used for years is &lt;code&gt;bundle show actionmailer&lt;/code&gt; (or in the old days &lt;code&gt;cd $(bundle show actionmailer)&lt;/code&gt;, before they broke that with a deprecation notice), and then you can add &lt;code&gt;pp&lt;/code&gt; or &lt;code&gt;binding.pry&lt;/code&gt; wherever you like. It’s a great way to test your understanding of what’s happening or discover the internals of something.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:illuminatedcomputing.com,2023-06-29:/posts/2023/06/rails-dirty-methods/</id>
    <title type="html">Rails dirty methods</title>
    <published>2023-06-29T00:00:00Z</published>
    <updated>2023-06-29T00:00:00Z</updated>
    <link rel="alternate" href="https://illuminatedcomputing.com/posts/2023/06/rails-dirty-methods/" type="text/html"/>
    <content type="html">
&lt;p&gt;Rails has lots of methods to see what attributes have changed on your model. Some tell you the changes you haven’t yet saved; some, the changes you just saved. But the behavior and names of these attributes &lt;a href="https://blog.toshima.ru/2017/04/06/saved-change-to-attribute.html"&gt;have&lt;/a&gt; &lt;a href="https://www.fastruby.io/blog/rails/upgrades/active-record-5-1-api-changes.html"&gt;changed&lt;/a&gt; &lt;a href="https://www.bigbinary.com/blog/rails-6-1-adds-_previously_was-attribute-methods"&gt;over&lt;/a&gt; &lt;a href="https://blog.saeloun.com/2020/03/24/rails-attribute_name_previously_changed-accepts-from-and-to-arguments/"&gt;time&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I thought I had a handle on this until I saw &lt;code&gt;saved_change_to_attribute?&lt;/code&gt; and wondered how it differs from &lt;code&gt;attribute_previously_changed?&lt;/code&gt;. Turns out they are identical!&lt;/p&gt;

&lt;p&gt;Well sort of. The spelling I’m used to, &lt;code&gt;attribute_previously_changed?&lt;/code&gt;, comes from &lt;a href="https://github.com/rails/rails/blob/6-1-stable/activemodel/lib/active_model/dirty.rb#L187-L189"&gt;&lt;code&gt;ActiveModel::Dirty&lt;/code&gt;&lt;/a&gt; (and is a bit older), whereas &lt;code&gt;saved_change_to_attribute?&lt;/code&gt; is defined in &lt;a href="https://github.com/rails/rails/blob/6-1-stable/activerecord/lib/active_record/attribute_methods/dirty.rb#L51-L53"&gt;&lt;code&gt;ActiveRecord::AttributeMethods::Dirty&lt;/code&gt;&lt;/a&gt;. Not all ActiveModels are ActiveRecords. But in your ActiveRecord classes, they do the same thing.&lt;/p&gt;

&lt;p&gt;I’ve linked to Rails 6.1 here. They were nearly identical before that, but for a while one took extra options and the other didn’t. You have to go back to Rails 5.0 to get a more substantial difference, when we had &lt;code&gt;attribute_previously_changed?&lt;/code&gt; but not &lt;code&gt;saved_change_to_attribute?&lt;/code&gt;. They are still identical today in Rails 7. I’m surprised they don’t deprecate the ActiveRecord methods and just use ActiveModel.&lt;/p&gt;

&lt;p&gt;Just to give a quick catalog, here is the full set of methods. Anywhere you see &lt;code&gt;attribute&lt;/code&gt; you can replace it with the name of the attribute you care about (which just calls the generic method with its name as parameter).&lt;/p&gt;

&lt;p&gt;before you save:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;changes
changed_attributes              # can't replace "attribute"
attribute_change
attribute_changed?
attribute_was

changes_to_save
has_changes_to_save?
attributes_in_database          # can't replace "attribute"
attribute_in_database
changed_attribute_names_to_save # can't replace "attribute"
attribute_change_to_be_saved
will_save_change_to_attribute?&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;after you save:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;previous_changes
attribute_previous_change
attribute_previously_changed?
attribute_previously_was

saved_changes
saved_changes?
saved_change_to_attribute
saved_change_to_attribute?
attribute_before_last_save&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I’ve grouped the methods from each file, and you can see there are many synonyms.&lt;/p&gt;

&lt;p&gt;By the way if you are making heavy use of ActiveRecord callbacks and using these methods to trigger them (e.g. &lt;code&gt;after_commit :send_shipped_notification if: :shipped_at_previously_changed?&lt;/code&gt;), watch out! The conditions on these get evaluated one-by-one, so if some earlier callback saves further changes to the model, your old &lt;code&gt;previous_changes&lt;/code&gt; are lost! The callback you expect to get called just doesn’t. I’ve had to debug that failure way too many times.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:illuminatedcomputing.com,2018-08-04:/posts/2018/08/rails-email-testing/</id>
    <title type="html">Testing Your ActionMailer Configuration</title>
    <published>2018-08-04T00:00:00Z</published>
    <updated>2018-08-04T00:00:00Z</updated>
    <link rel="alternate" href="https://illuminatedcomputing.com/posts/2018/08/rails-email-testing/" type="text/html"/>
    <content type="html">
&lt;p&gt;Sometimes with Rails you just want to test basic email sending from the console. Here is how you can do it, without needing a Mailer or views or anything:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ActionMailer::Base.mail(
  to:      'dest@example.com',
  from:    'src@example.com', 
  subject: 'test',
  body:    'testing',
).deliver_now&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or in older versions use &lt;code&gt;deliver&lt;/code&gt; instead of &lt;code&gt;deliver_now&lt;/code&gt;. This will use your ActionMailer settings but doesn’t require anything else, so you can test just the SMTP config (or whatever).&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:illuminatedcomputing.com,2018-06-30:/posts/2018/06/activerecord_if_method/</id>
    <title type="html">Adding an if method to ActiveRecord::Relation</title>
    <published>2018-06-30T00:00:00Z</published>
    <updated>2018-06-30T00:00:00Z</updated>
    <link rel="alternate" href="https://illuminatedcomputing.com/posts/2018/06/activerecord_if_method/" type="text/html"/>
    <content type="html">
&lt;p&gt;I often find myself chaining ActiveRecord scopes, like this:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;q = &lt;span class="constant"&gt;Article&lt;/span&gt;
  .not_deleted
  .published_within(start_date, end_date)
q = q.with_tags(tags) &lt;span class="keyword"&gt;if&lt;/span&gt; tags.any?&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I wish there were a nicer way to put in the conditional scopes, without assigning to a temporary variable. What I really want is to write this:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="constant"&gt;Article&lt;/span&gt;
  .not_deleted
  .published_within(start_date, end_date)
  .if(tags.any?) { with_tags(tags) }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Wouldn’t that be nicer?&lt;/p&gt;

&lt;p&gt;Many years ago I brought this up &lt;a href="https://groups.google.com/forum/#!msg/pdxruby/AmXgXog5440/j4_zSkyrTM0J"&gt;on the pdxruby mailing list&lt;/a&gt;, and no one seemed very interested, but I’ve always wanted it in my projects.&lt;/p&gt;

&lt;p&gt;Here is a naïve implementation, which just for simplicity I’ll add to &lt;code&gt;Object&lt;/code&gt; instead of &lt;code&gt;ActiveRecord::Relation&lt;/code&gt; (where it really belongs):&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="class"&gt;Object&lt;/span&gt;

  &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;if&lt;/span&gt;(condition, &amp;amp;block)
    condition ? instance_eval(&amp;amp;block) : &lt;span class="predefined-constant"&gt;self&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="integer"&gt;5&lt;/span&gt;.if(&lt;span class="predefined-constant"&gt;true&lt;/span&gt;)  { &lt;span class="predefined-constant"&gt;self&lt;/span&gt; + &lt;span class="integer"&gt;7&lt;/span&gt; }    &lt;span class="comment"&gt;# equals 12&lt;/span&gt;
&lt;span class="integer"&gt;5&lt;/span&gt;.if(&lt;span class="predefined-constant"&gt;false&lt;/span&gt;) { &lt;span class="predefined-constant"&gt;self&lt;/span&gt; + &lt;span class="integer"&gt;7&lt;/span&gt; }    &lt;span class="comment"&gt;# equals 5&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That &lt;em&gt;almost&lt;/em&gt; works! The problem is that inside the block, things don’t really act like a closure. If we used this implementation, our example above would give a &lt;code&gt;NameError&lt;/code&gt; about not finding a &lt;code&gt;tags&lt;/code&gt; method or local variable. That’s because everything inside the block is evaluated with &lt;code&gt;self&lt;/code&gt; set to the &lt;code&gt;ActiveRecord::Relation&lt;/code&gt; instance.&lt;/p&gt;

&lt;p&gt;Fortunately there is a way to fix it! Before calling the block, we can save the outside &lt;code&gt;self&lt;/code&gt;, and then we can use &lt;code&gt;method_missing&lt;/code&gt; to delegate any failures to there.&lt;/p&gt;

&lt;p&gt;There is a nice writeup of &lt;a href="https://www.skorks.com/2013/03/a-closure-is-not-always-a-closure-in-ruby/"&gt;this “cloaking” trick&lt;/a&gt; if you want more details. But if you read that article, perhaps you will notice it is not thread-safe, because it temporarily adds a method to the class, and two threads could stomp on each other if they did that at the same time.&lt;/p&gt;

&lt;p&gt;This approach was in Rails ActiveSupport for a while as &lt;a href="https://github.com/rails/rails/commit/d921b799747aacb47dc8bbca9b2eefe25159e9d5"&gt;&lt;code&gt;Proc#bind&lt;/code&gt;&lt;/a&gt;. They even fixed the multi-threading problem (more or less . . .) by generating a different method name every time. Unfortunately that created a new problem: since &lt;code&gt;define_method&lt;/code&gt; takes a symbol, this creates more and more symbols, which in Ruby are never garbage collected! Effectively this is a memory leak. Eventually the Rails team &lt;a href="https://github.com/rails/rails/commit/9c857db75788c21f6184279c130e79f21c750f9f"&gt;deprecated it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But we can still add something similar that doesn’t leak memory and is thread-safe. We just have to protect the brief moment when we define the method and then remove it, which is simple with a &lt;a href="https://ruby-doc.org/core-2.5.0/Mutex.html"&gt;&lt;code&gt;Mutex&lt;/code&gt;&lt;/a&gt;. In theory taking a lock adds some overhead, and possibly contention, but we don’t expect this to be a “hot spot”, so in practice the contention should be zero and the overhead trivial.&lt;/p&gt;

&lt;p&gt;And here is our implementation (not on &lt;code&gt;Object&lt;/code&gt; any more):&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="keyword"&gt;module&lt;/span&gt; &lt;span class="class"&gt;ActiveRecord&lt;/span&gt;
  &lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="class"&gt;Relation&lt;/span&gt;

    &lt;span class="constant"&gt;CLOAKER_MUTEX&lt;/span&gt; = &lt;span class="constant"&gt;Mutex&lt;/span&gt;.new

    &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;if&lt;/span&gt;(condition, &amp;amp;block)
      &lt;span class="keyword"&gt;if&lt;/span&gt; condition
        meth = &lt;span class="predefined-constant"&gt;self&lt;/span&gt;.class.class_eval &lt;span class="keyword"&gt;do&lt;/span&gt;
          &lt;span class="constant"&gt;CLOAKER_MUTEX&lt;/span&gt;.synchronize &lt;span class="keyword"&gt;do&lt;/span&gt;
            define_method &lt;span class="symbol"&gt;:cloaker_&lt;/span&gt;, &amp;amp;block
            meth = instance_method &lt;span class="symbol"&gt;:cloaker_&lt;/span&gt;
            remove_method &lt;span class="symbol"&gt;:cloaker_&lt;/span&gt;
            meth
          &lt;span class="keyword"&gt;end&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
        with_previous_context(block.binding) { meth.bind(&lt;span class="predefined-constant"&gt;self&lt;/span&gt;).call }
      &lt;span class="keyword"&gt;else&lt;/span&gt;
        &lt;span class="predefined-constant"&gt;self&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;with_previous_context&lt;/span&gt;(binding, &amp;amp;block)
      &lt;span class="instance-variable"&gt;@previous_context&lt;/span&gt; = binding.eval(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;self&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;)
      result = block.call
      &lt;span class="instance-variable"&gt;@previous_context&lt;/span&gt; = &lt;span class="predefined-constant"&gt;nil&lt;/span&gt;
      result
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;method_missing&lt;/span&gt;(method, *args, &amp;amp;block)
      &lt;span class="keyword"&gt;super&lt;/span&gt;
    &lt;span class="keyword"&gt;rescue&lt;/span&gt; &lt;span class="constant"&gt;NameError&lt;/span&gt; =&amp;gt; e
      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="instance-variable"&gt;@previous_context&lt;/span&gt;
        &lt;span class="instance-variable"&gt;@previous_context&lt;/span&gt;.send(method, *args, &amp;amp;block)
      &lt;span class="keyword"&gt;else&lt;/span&gt;
        raise e
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Put that in &lt;code&gt;config/initializers&lt;/code&gt; and try it out!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; I’ve been asked for a license for this code, so I’m releasing it under the MIT license:&lt;/p&gt;

&lt;p&gt;Copyright © 2018–2022 Paul Jungwirth&lt;/p&gt;

&lt;p&gt;Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:&lt;/p&gt;

&lt;p&gt;The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&lt;/p&gt;

&lt;p&gt;THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:illuminatedcomputing.com,2017-12-05:/posts/2017/12/temporal-databases-bibliography/</id>
    <title type="html">Temporal Databases Annotated Bibliography</title>
    <published>2017-12-05T00:00:00Z</published>
    <updated>2017-12-05T00:00:00Z</updated>
    <link rel="alternate" href="https://illuminatedcomputing.com/posts/2017/12/temporal-databases-bibliography/" type="text/html"/>
    <content type="html">
&lt;p&gt;I’ve been reading about temporal databases for a few years now, so I think it’s time I share my bibliography and notes. This is presented in “narrative order”, so that you can get a sense of how the research has developed. This article somewhat overlaps a mini literature review I wrote on the &lt;a href="https://www.mail-archive.com/pgsql-hackers@postgresql.org/msg324631.html"&gt;Postgres hackers mailing list&lt;/a&gt;, but this article is more complete and in a place where I can keep it updated.&lt;/p&gt;

&lt;p&gt;Temporal databases let you track the history of things over time: both the history of changes to the database (e.g. for auditing) and the history of the thing itself. They are not the same thing as time-series databases: whereas a time-series database has time-stamped &lt;em&gt;events&lt;/em&gt;, a temporal database stores the history of &lt;em&gt;things&lt;/em&gt;, typically by adding a start/end time to each row (so two timestamps, not one). With time-series the challenge is typically scale; with temporal the challenge is with complexity and correctness.&lt;/p&gt;

&lt;h2 id="research"&gt;Research&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Abdullah Tansel, James Clifford, Shashi Gadia, Sushil Jajodia, Arie Segev, and Richard T. Snodgrass (editors). &lt;em&gt;Temporal Databases: Theory, Design, and Implementation.&lt;/em&gt; 1993.&lt;/strong&gt; I only became aware of this in 2023. I own a copy now but haven’t read it cover to cover. I’m curious to see the variety of ideas back then, before things got standardized. It’s amazing how many old ideas are just forgotten. Codd’s &lt;a href="https://dl.acm.org/doi/10.1145/320107.320109"&gt;“Extending the data base relational model to capture more meaning”&lt;/a&gt; from 1979 is famous for introducing &lt;code&gt;NULL&lt;/code&gt; and outer joins, but no one seems to remember the second half, with graph databases and queries that dynamically build themselves by querying the system catalog. So I bet this book has creative ideas that could inspire modern developments.&lt;/p&gt;

&lt;p&gt;Already this book answered one question I had. Can a planner reorder/transform temporal operations the same way it can non-temporal ones? In other words, do they have the same algebraic properties? On page 175 in the chapter on TQuel I found this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Theorem 12&lt;/strong&gt; The following equivalences hold for the valid-time algebra.&lt;/p&gt;

&lt;p&gt;Q ∪̂ R ≡ R ∪̂ Q&lt;/p&gt;

&lt;p&gt;Q ⨯̂ R ≡ R ⨯̂ Q&lt;/p&gt;

&lt;p&gt;σ̂&lt;sub&gt;F&lt;sub&gt;1&lt;/sub&gt;&lt;/sub&gt;(σ̂&lt;sub&gt;F&lt;sub&gt;2&lt;/sub&gt;&lt;/sub&gt;(Q)) ≡ σ̂&lt;sub&gt;F&lt;sub&gt;2&lt;/sub&gt;&lt;/sub&gt;(σ̂&lt;sub&gt;F&lt;sub&gt;1&lt;/sub&gt;&lt;/sub&gt;(Q))&lt;/p&gt;

&lt;p&gt;Q ∪̂ (R ∪̂ S) ≡ (Q ∪̂ R) ∪̂ S&lt;/p&gt;

&lt;p&gt;Q ⨯̂ (R ⨯̂ S) ≡ (Q ⨯̂ R) ⨯̂ S&lt;/p&gt;

&lt;p&gt;Q ⨯̂ (R ∪̂ S) ≡ (Q ⨯̂ R) ∪̂ (Q ⨯̂ S)&lt;/p&gt;

&lt;p&gt;σ̂&lt;sub&gt;F&lt;/sub&gt;(Q ∪̂ R) ≡ σ̂&lt;sub&gt;F&lt;/sub&gt;(Q) ∪̂ σ̂&lt;sub&gt;F&lt;/sub&gt;(R)&lt;/p&gt;

&lt;p&gt;σ̂&lt;sub&gt;F&lt;/sub&gt;(Q −̂ R) ≡ σ̂&lt;sub&gt;F&lt;/sub&gt;(Q) −̂ σ̂&lt;sub&gt;F&lt;/sub&gt;(R)&lt;/p&gt;

&lt;p&gt;π̂&lt;sub&gt;X&lt;/sub&gt;(Q ∪̂ R) ≡ π̂&lt;sub&gt;X&lt;/sub&gt;(Q) ∪̂ π̂&lt;sub&gt;X&lt;/sub&gt;(R)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Theorem 13&lt;/strong&gt; The distributive property of Cartesian product over difference, or Q ⨯̂ (R −̂ S) ≡ (Q ⨯̂ R) −̂ (Q ⨯̂ S), does &lt;em&gt;not&lt;/em&gt; hold for the valid-time algebra.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I discuss this in more depth in &lt;a href="https://illuminatedcomputing.com/posts/2026/07/tquel-paper/"&gt;“TQuel Paper: Implementing Temporal Operators in Postgres”&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Snodgrass, Richard T. &lt;em&gt;Developing Time-Oriented Database Applications in SQL&lt;/em&gt;. 1999.&lt;/strong&gt; The seminal work on temporal databases and still the most useful introduction I know. Covers the “combinatorial explosion” of non-temporal/state-temporal/system-temporal/bi-temporal tables, current/sequenced/non-sequenced queries, &lt;code&gt;SELECT&lt;/code&gt;/&lt;code&gt;INSERT&lt;/code&gt;/&lt;code&gt;UPDATE&lt;/code&gt;/&lt;code&gt;DELETE&lt;/code&gt;, different RDBMS vendors, etc. Very similar to the proposed TSQL2 standard that was ultimately not accepted but still influenced &lt;a href="https://info.teradata.com/htmlpubs/DB_TTU_16_00/index.html#page/SQL_Reference%2FB035-1186-160K%2Fjst1472240640825.html%23"&gt;Teradata’s temporal support&lt;/a&gt;. Available as a free PDF from &lt;a href="https://www2.cs.arizona.edu/~rts/publications.html"&gt;his website&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hugh Darwen and C. J. Date. “An Overview and Analysis of Proposals Based on the TSQL2 Approach.”&lt;/strong&gt; Latest draft 2005, but originally written earlier. Criticizes the TSQL2 proposal’s use of “statement modifiers”, especially their problems with composability when a view/subquery/CTE/function returns a temporal result. Available &lt;a href="https://web.archive.org/web/20240728071358/https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.116.7598"&gt;as a PDF&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ralph Kimball and Margy Ross. &lt;em&gt;The Data Warehouse Toolkit&lt;/em&gt;. 3rd edition, 2013.&lt;/strong&gt; (2nd edition 2002, 1st 1996.) (My notes are based on reading the 2nd edition, but I don’t think there are major relevant changes.) This book is not about temporal databases per se, but in Chapter 4 (and scattered around elsewhere) he talks about dealing with data that changes over time (“Slowly Changing Dimensions”). His first suggestion (Type 1) is to ignore the problem and overwrite old data with new. His Type 2 approach (make a new row) is better but loses the continuity between the old row and the new. Type 3 fixes that but supports only one change, not several. This writing is evidence for the need to handle temporal data, and the contortions that result from not having a systematic approach. (These criticisms and the realization that Kimball is trying to solve the same problems as temporal databases come from Johnston’s second book below; I’m glad he made the connection between Kimball and temporal databases!) (&lt;a href="http://www.dsc.ufcg.edu.br/~sampaio/Livros/alph%20Kimball.%20The%20Data%20Warehouse%20Toolkit..%20The%20Complete%20Guide%20to%20Dimensional%20Modelling%20%28Wiley%2C2002%29%28ISBN%200471200247%29%28449s%29.pdf"&gt;pdf&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C. J. Date, Hugh Darwen, Nikos Lorentzos. &lt;em&gt;Time and Relational Theory, Second Edition: Temporal Databases in the Relational Model and SQL&lt;/em&gt;. 2nd edition, 2014.&lt;/strong&gt; (First edition published in 2002.) I read this in March 2018. If you’ve read Date &amp;amp; Darwen’s other works you know they are quite rigorous, often critical of SQL’s compromises vs the pure relational model (e.g. &lt;code&gt;NULL&lt;/code&gt; and non-distinct results), and not always very practical. Nonetheless this book is full of great ideas, and I hope anyone thinking about implementing temporal features in an RDBMS product will read it. They mostly deal with state-time, not transaction-time, which is great since that’s where the field most needs attention, although they also show how to apply their ideas to transaction-time tables too.&lt;/p&gt;

&lt;p&gt;The core idea is that a temporal table should really have a row for each second (or millisecond or day or whatever is your finest granularity of time), saying what was true at that moment. Then the primary key is just the second plus the regular primary key. This idea isn’t new, but they use it to define everything else in the book. This makes thinking about temporal queries a lot easier, so that if you ever have any hesitation about something, you can think about it in terms of one-row-per-second and it starts to be easy.&lt;/p&gt;

&lt;p&gt;Of course no database could adopt that in practice, so they offer operators to transform rows with start/end ranges to one-row-per-second and back again. In almost every case you don’t have to use those operators, but they are a solid theoretical basis for the next step: defining interval-aware primary keys, foreign keys, and all the relational operators. Finally they show how you implement things without “materializing” the expanded version of the data.&lt;/p&gt;

&lt;p&gt;Another idea implicit in that is that temporal concerns belong in the SQL &lt;em&gt;operators&lt;/em&gt;, not as “statement modifiers” like in TSQL2. Really that might be the most important idea in the whole book, so I’m glad to see it being applied to Postgres in the papers by Dignös et al (below).&lt;/p&gt;

&lt;p&gt;They also argue (vs SQL:2011) that a single interval column type is better than separate start/end columns, which I agree with. Strangely they go against all the existing research by using closed/closed intervals (e.g. &lt;code&gt;[Jan2017,Dec2017]&lt;/code&gt;) instead of closed/open (&lt;code&gt;[Jan2017,Jan2018)&lt;/code&gt;), without really giving much justification. They also avoid using &lt;code&gt;NULL&lt;/code&gt; for an unbounded side (e.g. &lt;code&gt;[Jan2017,NULL)&lt;/code&gt;), preferring a magic “end of time” date (&lt;code&gt;[Jan2017,Jan3000)&lt;/code&gt;). I wasn’t surprised by the second decision, given the authors’ history, but the first was less explicable. In both cases their approach sadly marginalizes their work and imposes barriers to adopting it in real SQL products.&lt;/p&gt;

&lt;p&gt;I really appreciate how these authors have insisted that valid time (and the same with transaction time) should be a regular column, not something different. That was a big part of their complaint against TSQL2. To be honest when I first read Snodgrass the idea of using pseudo-columns seemed so suboptimal it was hard to take seriously (“Of course they don’t mean it.”), so I’m glad these authors have insisted on pointing out that approach’s shortcomings. Unfortunately in SQL:2011 valid-time is still a pseudo-column made up of two regular date/time columns. The problem is in composability: using a temporal query as a subquery, view, or function result: it all works cleanly if the interval is just another input to your interval-aware operators, but not if you need some kind of extra pseudo-column metadata. I hope implementers will take their advice seriously and not build temporal features on such a distorting idea.&lt;/p&gt;

&lt;p&gt;Something I disagreed with was their suggestion to use tables in sixth-normal form—basically every column gets its own table—since attributes can have different lifespans. I can see how that is purer, but it seems like just too much complexity. They probably suspected the same because they always show how to do things with either that approach or tables in a more traditional third-normal form (or &lt;a href="https://en.wikipedia.org/wiki/Boyce%E2%80%93Codd_normal_form"&gt;BCNF&lt;/a&gt; if you prefer). Even that is slightly distorted in order to avoid &lt;code&gt;NULL&lt;/code&gt;s, but you can easily look past that.&lt;/p&gt;

&lt;p&gt;Finally, I appreciated that on page 282 they mention DDL on temporal databases. Like everyone they say it’s beyond the scope of their current discussion, but it’s a penetrating insight to say, “the database catalog might itself need to be treated as a temporal database.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;SQL:2011 Draft standard&lt;/em&gt;.&lt;/strong&gt; (&lt;a href="https://web.archive.org/web/20160402092111/http://jtc1sc32.org/doc/N1951-2000/32N1964T-text_for_ballot-FCD_9075-2.pdf"&gt;pdf&lt;/a&gt;) Personally I find the standard pretty disappointing. It uses separate start/end columns instead of built-in range types, although range types offer benefits like exclusion constraints and convenient operators for things like “overlaps” that are verbose to code correctly by hand. It only mentions inner joins, not the various outer joins, semi-joins (&lt;code&gt;EXISTS&lt;/code&gt;), anti-joins (&lt;code&gt;NOT EXISTS&lt;/code&gt;), or aggregates. Many of its features apply only to system-time, not application-time, even though applicaion-time is the more interesting and less-available feature. (There are lots of auditing add-ons, but almost nothing for tracking the history of things.) The syntax seems too specific, lacking appropriate generality. A lot of these drawbacks seem motivated by a goal that goes back to TSQL2: to let people add temporal support to old tables without breaking any existing queries. That has always seemed to me like an unlikely possibility, and an unfortunate source of distortions. I don’t expect something for free, and I don’t mind doing work to migrate a table to a temporal format, as long as the result is good. Instead we get an (ostensible) one-time benefit for a prolonged compromise in functionality and ease-of-use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Krishna Kulkarni and Jan-Eike Michels. “Temporal Features in SQL:2011”. &lt;em&gt;SIGMOD Record&lt;/em&gt;, September 2012.&lt;/strong&gt; Nice overview of the temporal features included in the SQL:2011 standard. &lt;a href="https://sigmodrecord.org/publications/sigmodRecord/1209/pdfs/07.industry.kulkarni.pdf"&gt;Here is a PDF&lt;/a&gt; of the paper. See also &lt;a href="https://web.archive.org/web/20230524033629/http://metadata-standards.org/Document-library/Documents-by-number/WG2-N1501-N1550/WG2_N1536_koa046-Temporal-features-in-SQL-standard.pdf"&gt;these slides by Kulkani&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Peter Vanroose. “Temporal Data &amp;amp; Time Travel in PostgreSQL,” FOSDEM 2015.&lt;/strong&gt; (&lt;a href="https://wiki.postgresql.org/images/6/64/Fosdem20150130PostgresqlTemporal.pdf"&gt;Slides as a pdf&lt;/a&gt;) Lots of good detail here about SQL:2011. I’d love to see a recording of this talk if it’s available, but I haven’t found it yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tom Johnston and Randall Weis. &lt;em&gt;Managing Time in Relational Databases: How to Design, Update and Query Temporal Data&lt;/em&gt;. 2010.&lt;/strong&gt; I finished this in May/June 2019. Although it concentrates on the authors’ proprietary middleware add-on to MS SQL Server called Asserted Versioning, it nonetheless has many ideas for building practical temporal features on any RDBMS. I liked their creativity and willingness to improve on SQL:2011 when they could. (Technically their book predates the final form of the standard.) Their middleware approach did sometimes lead them to behavior that would be strange in a more SQL-oriented solution. For example their temporal updates and deletes can only target a single record by ID (but they also mention they have a fix for this), and if that ID is not found you get an error. In ordinary SQL you would not get an error if an &lt;code&gt;UPDATE&lt;/code&gt; or &lt;code&gt;DELETE&lt;/code&gt; didn’t change any rows, and on the other hand you could hit more rows than one by not using the primary key. They mention that at the time of writing they were trying to replace their middleware approach with an implemention using views and instead-of triggers (something that has been done elsewhere too), and I expect that would wind up behaving more like ordinary SQL. They also introduce an interesting idea of future-dating records’ system-time (“assertion-time” in their lingo) so that the database will not make them “effective” until you’re ready. This has some nice practical use-cases, but there are pretty serious drawbacks. In their system a future-dated record is essentially immutable, so you had better not change your mind! Despite this book’s many contributions, I think everything here was also covered in Johnston’s second book, which is probably what I’d read if I had to choose one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tom Johnston. &lt;em&gt;Bitemporal Data: Theory and Practice&lt;/em&gt;. 2014.&lt;/strong&gt; I felt like I found a kindred soul when I read how he connects database design and ontology, as I’ve always thought of programming as “applied philosophy.” Databases as Aristotelian propositional logic is inseparable from the mathematical set-based theory. Johnston gives helpful distinctions between the physical rows in the table, the assertions they represent, and the things themselves. Eventually this leads to a grand vision of connecting every assertion’s bitemporal (or tritemporal) history to its speaker, somewhat like some ideas in the Semantic Web, although this doesn’t sound very practical. Like Date he seems to be landing on something like sixth-normal form, with a view-like presentation layer to bring all the attributes back together again. (Also like Date he seems to acknowledge 6NF may not be practical.) He points out how unsatisfactory Kimball’s suggestions are. He also criticizes the limitations of SQL:2011 and offers some amendments to make it more useful. Describes a (patented) idea of “episodes” to optimize certain temporal queries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Anton Dignös, Michael H. Böhlen, and Johann Gamper. “Temporal Alignment”, SIGMOD ’12.&lt;/strong&gt; Amazing! Shows how to define temporal versions of every relational operator by a combination of the traditional operators and just two simple transforms, which they call “align” and “split”. Gives a very readable exposition of the new theory and then describes how they patched Postgres 9.0 and benchmarked the performance. I think this solves the composability problems Date objected to in TSQL2, and unlike SQL:2011 it is general and comprehensive. The focus is on state-time, and I’m not sure how it will map onto bi-temporal, but even just having good state-time functionality would be tremendous. And the paper is only 12 easy-to-read pages! (&lt;a href="https://files.ifi.uzh.ch/boehlen/Papers/modf174-dignoes.pdf"&gt;pdf&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Anton Dignös, Michael Hanspeter Böhlen, Johann Gamper, and Christian S. Jensen. “Extending the kernal of a relational DBMS with comprehensive support for sequenced temporal queries,” &lt;em&gt;ACM Transactions on Database Systems&lt;/em&gt;, 41(4):1-46.&lt;/strong&gt; Continues the previous paper but adds support for scaling the inputs to aggregate groups according to how much of their time period goes into each group. Gives more benchmarks against a patched Postgres 9.5. (&lt;a href="http://www.zora.uzh.ch/id/eprint/130374/1/Extending_the_kernel.pdf"&gt;pdf&lt;/a&gt;) These researchers are now trying to contribute their work to the Postgres core project, of which I am very much in favor. :-)&lt;/p&gt;

&lt;h2 id="tools"&gt;Tools&lt;/h2&gt;

&lt;p&gt;Finally here are some tools for temporal support in Postgres. The sad theme is that pretty much everything gives audit support but not history support:&lt;/p&gt;

&lt;h3 id="postgres"&gt;Postgres&lt;/h3&gt;

&lt;p&gt;The most complete implementation of bi-temporal tables is Vik Fearing’s &lt;a href="https://github.com/xocolatl/periods"&gt;periods extension&lt;/a&gt;. Since Postgres uses a bison grammar, an extension can’t add new syntax, but this one does a great job working around that limitation to provide almost everything from the SQL:2011 standard.&lt;/p&gt;

&lt;p&gt;Henrietta (Hettie) Dombrovskaya has a &lt;a href="https://github.com/hettie-d/pg_bitemporal"&gt;&lt;code&gt;pg_temporal&lt;/code&gt; repository&lt;/a&gt; with talks, slides, and code. I haven’t tried building it but I believe her company is using this in production. She is an awesome speaker, so her talks are great intros to this topic too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/pgaudit/pgaudit"&gt;The pgaudit extension&lt;/a&gt; looks pretty useful but I haven’t tried it yet. According to the AWS docs you can even use this &lt;a href="http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html"&gt;on RDS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Vlad Arkhipov’s &lt;a href="https://pgxn.org/dist/temporal_tables/"&gt;temporal tables extension&lt;/a&gt; only supports system-time (auditing). Also &lt;a href="https://github.com/arkhipov/temporal_tables"&gt;on Github&lt;/a&gt; and &lt;a href="http://clarkdave.net/2015/02/historical-records-with-postgresql-and-temporal-tables-and-sql-2011/"&gt;a nice writeup by Clark Dave&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Magnus Hagander presented an approach to capturing system-time history in a separate schema at PGConf US 2015 and PGDay’15 Russia. Here are &lt;a href="https://www.hagander.net/talks/tardis_orm.pdf"&gt;slides&lt;/a&gt; and &lt;a href="https://www.youtube.com/watch?v=TRgni5q0YM8"&gt;video&lt;/a&gt;. Quite elegant if you want to ask questions like “what did we think as of time t?” If I recall correctly this is similar to one of the ideas proposed at the end of Snodgrass, although I haven’t compared them carefully. Hagander points out that DDL changes against temporal databases are challenging and hopefully infrequent. This is a topic that is almost completely absent from the literature, except for a brief mention in Johnston 2014.&lt;/p&gt;

&lt;p&gt;I’ve heard about a &lt;a href="https://github.com/Actuarial-Sciences-for-Africa-ASA/BitemporalPostgres.jl"&gt;Julia project for temporal data in Postgres&lt;/a&gt;. I’m not sure how it works, but it looks interesting!&lt;/p&gt;

&lt;h3 id="ruby"&gt;Ruby&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/ifad/chronomodel"&gt;Chronomodel&lt;/a&gt; extends the ActiveRecord ORM to record system-time history. The &lt;a href="https://github.com/Casecommons/pg_audit_log"&gt;&lt;code&gt;pg_audit_log&lt;/code&gt; gem&lt;/a&gt; works fine but like many audit solutions is rather write-only. I wouldn’t want to build any functionality that has to query its tables to reconstruct history. You could also try &lt;a href="https://github.com/airblade/paper_trail"&gt;&lt;code&gt;paper_trail&lt;/code&gt;&lt;/a&gt; or &lt;a href="https://github.com/collectiveidea/audited"&gt;&lt;code&gt;audited&lt;/code&gt; (formerly &lt;code&gt;acts_as_audited&lt;/code&gt;)&lt;/a&gt;. Of these projects only Chronomodel seems to be aware of temporal database research.&lt;/p&gt;

&lt;h2 id="further_research"&gt;Further Research&lt;/h2&gt;

&lt;p&gt;Temporal databases are exciting because there is still so much to do. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;What should the UI look like? Even one dimension adds a lot of complexity, let alone bi-temporal. How do you present this to users? As usual an audit history is easier, and it’s possible to find existing examples, whereas a state-time history is more challenging but probably more valuable. How should we let people view and edit the history of something? How does it work if there is a “Save” button vs save-as-you-type?&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;What does “full stack” temporal support look like? Do we extend REST? What would be a nice ORM interface? Should we use triggers to hide the temporal behavior behind regular-looking SQL? Or maybe extend SQL so you can more explicitly say what you want to do?&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;code&gt;SELECT&lt;/code&gt; support for “as of” semantics or “over time” semantics.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Temporal foreign keys. I have &lt;a href="https://github.com/pjungwir/time_for_keys"&gt;a POC Postgres extension&lt;/a&gt; and &lt;a href="https://commitfest.postgresql.org/45/4308/"&gt;am making progress adding it to core&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;DDL changes. For example if you want to add a &lt;code&gt;NOT NULL&lt;/code&gt; column, what do you do with the old data? Could there be built-in support to apply constraints only to a given time span?&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Future time. There are some cool ideas about this in Johnson’s books, and I’ve heard of fintech folks doing something here.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Temporal upsert. This would be an &lt;code&gt;INSERT&lt;/code&gt; that falls back to &lt;code&gt;FOR PORTION OF&lt;/code&gt; for spans that already exist. Quite often this is what an application really wants. Johnson talks about how the standard should have included something here.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Outer joins and aggregates. Dignös et al show how to do this, but it’s not in the standard. I’d love to get their old patch working again and try to get something similar into Postgres, once the basics are finished. I’ve written &lt;a href="https://github.com/pjungwir/temporal_ops"&gt;SQL implementations&lt;/a&gt; of temporal outer join, semi-join, anti-join, &lt;code&gt;UNION&lt;/code&gt;, &lt;code&gt;EXCEPT&lt;/code&gt;, and &lt;code&gt;INTERSECT&lt;/code&gt;, but those won’t perform as well as built-in RDBMS support. If Postgres gets &lt;a href="https://commitfest.postgresql.org/patch/5083/"&gt;inlining PL/pgSQL functions&lt;/a&gt; it will be faster. Even better would be a C implementation using &lt;code&gt;CustomScan&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <id>tag:illuminatedcomputing.com,2017-04-12:/posts/2017/04/scaling-sidekiq/</id>
    <title type="html">Scaling Sidekiq</title>
    <published>2017-04-12T00:00:00Z</published>
    <updated>2017-04-12T00:00:00Z</updated>
    <link rel="alternate" href="https://illuminatedcomputing.com/posts/2017/04/scaling-sidekiq/" type="text/html"/>
    <content type="html">
&lt;p&gt;&lt;a href="https://github.com/mperham/sidekiq"&gt;Sidekiq&lt;/a&gt; is a great option for handling background jobs in Ruby projects. Here I’ll show you how to get the best utilization out of a box dedicated to running Sidekiq jobs. Whether you have one machine or ten, the goal is to work off as many jobs as possible from each machine.&lt;/p&gt;

&lt;h2 id="cpu_utilization"&gt;CPU Utilization&lt;/h2&gt;

&lt;p&gt;To do that, we want to keep every core busy. You can monitor your CPU activity with a tool like &lt;a href="https://linux.die.net/man/8/vmstat"&gt;vmstat(8)&lt;/a&gt;. If you say &lt;code&gt;vmstat 10&lt;/code&gt;, you’ll get a new row every ten seconds, like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 9  0  92056 553620 174128 6268208    0    0     1    25 1323 1443 23 77  0  0  0
 8  0  92056 552628 174128 6268492    0    0    14    38 1307 1447 22 78  0  0  0
 8  0  92056 551760 174132 6268672    0    0     3    49 1317 1461 23 77  0  0  0
 8  0  92056 550544 174140 6268832    0    0     1    28 1353 1490 23 77  0  0  0
 8  0  92056 550296 174148 6268940    0    0     1    35 1240 1360 22 78  0  0  0&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The last few columns show percentage of CPU time doing user work (&lt;code&gt;us&lt;/code&gt;), system work (&lt;code&gt;sy&lt;/code&gt;)—which more or less means executing kernel system calls—, idle (&lt;code&gt;id&lt;/code&gt;), and blocked on I/O (&lt;code&gt;wa&lt;/code&gt;, “waiting”). Add the first two together to get how much your CPU is working.&lt;/p&gt;

&lt;p&gt;There is also &lt;code&gt;st&lt;/code&gt;, which means “stolen time”! If you are running a VM, this means the time your hypervisor gives to someone else. You will probably see all zeros in this column, so I’ll ignore it going forward. We want to get our idle and wait time as close to zero as possible, without drowning the machine in too much work. Above we have a machine that is doing a good job keeping busy. You can see that its user and system time are at 100, and the other columns are zero.&lt;/p&gt;

&lt;p&gt;So how do we do this? Usually it means running lots of jobs at the same time, not one-after-another. Even a one-core machine can juggle many jobs. That’s because jobs typically have to block on I/O, for example when they talk to the network or save things to disk. While that job is waiting for an answer, your CPU can work on another one.&lt;/p&gt;

&lt;p&gt;(This is not really relevant here, but &lt;a href="http://www.linux-mag.com/id/308/"&gt;disk I/O is a little different than other I/O&lt;/a&gt;. &lt;a href="https://www.remlab.net/op/nonblock.shtml"&gt;Technically, reading/writing with a regular file can’t “block” but only “sleep”&lt;/a&gt;. That &lt;a href="http://neugierig.org/software/blog/2011/12/nonblocking-disk-io.html"&gt;completely messes up non-blocking I/O for regular files&lt;/a&gt;, and &lt;a href="http://lse.sourceforge.net/io/aio.html"&gt;even the newer &lt;code&gt;aio&lt;/code&gt; functions have many limitations&lt;/a&gt; and in fact are &lt;a href="http://man7.org/linux/man-pages/man7/aio.7.html"&gt;implemented by threads in userspace&lt;/a&gt;—but fortunately we are not talking about single-threaded non-blocking I/O; we are talking about multiple processes/threads. Whether you call it blocking or sleeping, the CPU will still schedule different work if something is stuck on a regular file &lt;code&gt;read&lt;/code&gt;. And if this paragraph doesn’t make sense, feel free to dismiss it as a pedantic footnote. :-)&lt;/p&gt;

&lt;h2 id="threads"&gt;Threads&lt;/h2&gt;

&lt;p&gt;Sidekiq is great here because it supports multi-threading. Multiple threads let you do concurrent work &lt;em&gt;in one Ruby process&lt;/em&gt; (at least as long as you are not &lt;a href="http://www.csinaction.com/2014/10/10/multithreading-in-the-mri-ruby-interpreter/"&gt;still stuck on Ruby 1.8&lt;/a&gt;). Without threads you’d need a separate process for each concurrent job, and that can use up memory quickly, especially with something like Rails. It is always sad to have more CPU available that you can’t use because you’re out of RAM.&lt;/p&gt;

&lt;p&gt;In practice, threads mostly help if you are using a concurrent Ruby implementation like JRuby. MRI Ruby has a Global Interpreter Lock (GIL), which prevents two threads from executing at once. Still, even in MRI you will still see some benefit, because when one thread blocks on I/O, MRI can make progress on another. So despite the GIL, MRI can still make sure at least &lt;em&gt;some&lt;/em&gt; thread is running.&lt;/p&gt;

&lt;p&gt;With Sidekiq, you can say how many threads to run with the &lt;code&gt;concurrency&lt;/code&gt; setting. Normally you’d set this in your &lt;code&gt;sidekiq.yml&lt;/code&gt; file. Note that each thread needs its own database connection! That means if your &lt;code&gt;concurrency&lt;/code&gt; is 10, then in your &lt;code&gt;database.yml&lt;/code&gt; you must have a &lt;code&gt;pool&lt;/code&gt; of 10 also (or more). Otherwise the threads will halt each other waiting to check out a database connection, and what is the point of that? They might even get timeout errors.&lt;/p&gt;

&lt;h2 id="processes"&gt;Processes&lt;/h2&gt;

&lt;p&gt;But wait, there’s more! We can push the &lt;code&gt;concurrency&lt;/code&gt; up and up, and still see something like this from vmstat:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0  92048 585840 174148 6269120    0    0     0    16  956  990  7 18 75  0  0
 1  0  92048 585212 174160 6269256    0    0     1    23 1012 1037  8 17 75  0  0
 1  0  92048 580456 174164 6269312    0    0     1    33  896  884  8 17 75  0  0&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Why is the idle CPU time stuck at 75?&lt;/p&gt;

&lt;p&gt;It turns out this is a four-core machine, and even with multiple threads, a single MRI process can only use one core, because of the GIL. That’s not what we want at all!&lt;/p&gt;

&lt;p&gt;So the answer is to run more processes—at least one per core. You can see how many cores you’ve got by saying &lt;code&gt;cat /proc/cpuinfo&lt;/code&gt;. If you are using something like &lt;a href="http://godrb.com/"&gt;&lt;code&gt;god&lt;/code&gt;&lt;/a&gt;, it is easy to put several processes into a group and control them together, like so:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;app_root = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;/var/www/myapp/current&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class="integer"&gt;4&lt;/span&gt;.times &lt;span class="keyword"&gt;do&lt;/span&gt; |i|
  &lt;span class="constant"&gt;God&lt;/span&gt;.watch &lt;span class="keyword"&gt;do&lt;/span&gt; |w|
    w.name     = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;myapp-sidekiq-&lt;/span&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;#{&lt;/span&gt;i&lt;span class="inline-delimiter"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;
    w.group    = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;myapp-sidekiq&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;
    w.log      = &lt;span class="constant"&gt;File&lt;/span&gt;.join(app_root, &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;log&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;#{&lt;/span&gt;w.name&lt;span class="inline-delimiter"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="content"&gt;.log&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;)
    w.pid_file = &lt;span class="constant"&gt;File&lt;/span&gt;.join(app_root, &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;current&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;tmp&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;pids&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;#{&lt;/span&gt;w.name&lt;span class="inline-delimiter"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="content"&gt;.pid&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;)
    w.start    = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;lt;&amp;lt;-EOS&lt;/span&gt;&lt;/span&gt;.gsub(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="char"&gt;\n&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt; &lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;)&lt;span class="string"&gt;&lt;span class="content"&gt;
      cd '&lt;/span&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;#{&lt;/span&gt;app_root&lt;span class="inline-delimiter"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="content"&gt;' &amp;amp;&amp;amp;
        bundle exec ./bin/sidekiq --environment production
                                  --pidfile '&lt;/span&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;#{&lt;/span&gt;w.pid_file&lt;span class="inline-delimiter"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="content"&gt;'
                                  --logfile '&lt;/span&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;#{&lt;/span&gt;w.log&lt;span class="inline-delimiter"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="content"&gt;'
                                  --daemon&lt;/span&gt;&lt;span class="delimiter"&gt;
    EOS&lt;/span&gt;&lt;/span&gt;
    &lt;span class="comment"&gt;# ...&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you aren’t using god and don’t know how to do this with your own process manager, then I think &lt;a href="https://github.com/mperham/sidekiq/wiki/Ent-Multi-Process"&gt;Sidekiq Enterprise has a similar feature called Swarms&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="scheduling_cores"&gt;Scheduling cores&lt;/h2&gt;

&lt;p&gt;That gets us almost there, but there is still a problem. You might &lt;em&gt;still&lt;/em&gt; see idle time stuck somewhere, like (on a 4-core system) 25. The problem is that while the kernel does its best to use your whole CPU, it can still wind up putting two Sidekiq processes on the same core, and since they are such long-lived processes, they are stuck that way, competing for their shared core while another one sits idle. The kernel doesn’t know ahead of time that they are going to run for days and keep so busy.&lt;/p&gt;

&lt;p&gt;Fortunately we can still force each process onto its own core. For that we use the &lt;a href="https://linux.die.net/man/1/taskset"&gt;taskset(1)&lt;/a&gt; command. When you say &lt;code&gt;taskset -c 2 date&lt;/code&gt;, you are telling Linux to run &lt;code&gt;date&lt;/code&gt; on core 2. (Core numbers start from zero, as you can see in &lt;code&gt;/proc/cpuinfo&lt;/code&gt;.) So our god config would become:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;w.start    = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;&amp;lt;&amp;lt;-EOS&lt;/span&gt;&lt;/span&gt;.gsub(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="char"&gt;\n&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt; &lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;)&lt;span class="string"&gt;&lt;span class="content"&gt;
  cd '&lt;/span&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;#{&lt;/span&gt;app_root&lt;span class="inline-delimiter"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="content"&gt;' &amp;amp;&amp;amp;
    bundle exec taskset -c &lt;/span&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;#{&lt;/span&gt;i&lt;span class="inline-delimiter"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="content"&gt; ./bin/sidekiq --environment production
                                              --pidfile '&lt;/span&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;#{&lt;/span&gt;w.pid_file&lt;span class="inline-delimiter"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="content"&gt;'
                                              --logfile '&lt;/span&gt;&lt;span class="inline"&gt;&lt;span class="inline-delimiter"&gt;#{&lt;/span&gt;w.log&lt;span class="inline-delimiter"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="content"&gt;'
                                              --daemon&lt;/span&gt;&lt;span class="delimiter"&gt;
EOS&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After that, we’ll have one process on each core. At this point, you should start experimenting with your &lt;code&gt;concurrency&lt;/code&gt; setting, to make each core fully utilized. The right setting there will depend on how much blocking a job does, but I have seen useful numbers up to 20. Just try some things out, and watch &lt;code&gt;vmstat&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note that you &lt;em&gt;don’t&lt;/em&gt; have to increase the connection pool size in &lt;code&gt;database.yml&lt;/code&gt; as you add cores (just concurrency). That’s because each process is a separate thing, each with its own pool. But you &lt;em&gt;do&lt;/em&gt; have to increase the max connections on your database server. For instance with Postgres you’d want to set &lt;code&gt;max_connections&lt;/code&gt; in &lt;code&gt;postgresql.conf&lt;/code&gt;. Here you need to allow enough connections for &lt;code&gt;concurrency&lt;/code&gt; times cores (times servers), plus some more for your actual Rails app serving web requests, plus some more for anything else you’ve got going on. That can be a lot of connections! Don’t be surprised if improving your job throughput exposes a bottleneck elsewhere in your system.&lt;/p&gt;

&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Tuning Sidekiq can be complicated, because of the double layers of threads plus processes. You need a confident understanding of how Ruby and your operating system handle concurrency, and it helps to use tools like &lt;code&gt;vmstat&lt;/code&gt; to measure what’s going on and verify your understanding. If you have a box dedicated to just Sidekiq jobs, my recommendation is to run one process per core, using &lt;code&gt;taskset&lt;/code&gt; to keep them separate, and then tune &lt;code&gt;concurrency&lt;/code&gt; from there. Hopefully this will help with your own projects!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:illuminatedcomputing.com,2015-04-28:/posts/2015/04/paperclip_expiring_url_and_request_has_expired/</id>
    <title type="html">Paperclip expiring_url and "Request has expired"</title>
    <published>2015-04-28T00:00:00Z</published>
    <updated>2015-04-28T00:00:00Z</updated>
    <link rel="alternate" href="https://illuminatedcomputing.com/posts/2015/04/paperclip_expiring_url_and_request_has_expired/" type="text/html"/>
    <content type="html">
&lt;p&gt;I hit a weird error today. My project stores user uploads on S3 with &lt;code&gt;private&lt;/code&gt; permissions, and we use the &lt;a href="https://github.com/thoughtbot/paperclip"&gt;Paperclip&lt;/a&gt; &lt;a href="https://github.com/thoughtbot/paperclip/wiki/Restricting-Access-to-Objects-Stored-on-Amazon-S3"&gt;&lt;code&gt;expiring_url&lt;/code&gt; method&lt;/a&gt; to let people download them. This started failing with a error like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;Error&amp;gt;
  &amp;lt;Code&amp;gt;AccessDenied&amp;lt;/Code&amp;gt;
  &amp;lt;Message&amp;gt;Request has expired&amp;lt;/Message&amp;gt;
  &amp;lt;Expires&amp;gt;2015-04-28T18:30:51Z&amp;lt;/Expires&amp;gt;
  &amp;lt;ServerTime&amp;gt;2015-04-28T18:32:52Z&amp;lt;/ServerTime&amp;gt;
  &amp;lt;RequestId&amp;gt;BLAHBLAHBLAHBLAH&amp;lt;/RequestId&amp;gt;
  &amp;lt;HostId&amp;gt;
    MOREBLAHMOREBLAHMOREBLAHMOREBLAHMOREBLAHMOREBLAHMOREBLAH
  &amp;lt;/HostId&amp;gt;
&amp;lt;/Error&amp;gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The problem was that this error occurred immediately, even though we were generating the URLs with a 10 minute expiration time. Well, it turns out S3 was living in the future by 7 minutes (according to &lt;code&gt;ServerTime&lt;/code&gt; above), and our own app was living in the past by another 5. So 5 + 7 = 12 and our URLs were expired before we even generated them. 10 minutes is the example time in the Paperclip documentation linked above, but I guess it’s too short. Watch out for clock skew out there folks!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:illuminatedcomputing.com,2014-12-23:/posts/2014/12/acts_as_list-with-soft-delete/</id>
    <title type="html">Rails acts_as_list with Soft Delete</title>
    <published>2014-12-23T00:00:00Z</published>
    <updated>2014-12-23T00:00:00Z</updated>
    <link rel="alternate" href="https://illuminatedcomputing.com/posts/2014/12/acts_as_list-with-soft-delete/" type="text/html"/>
    <content type="html">
&lt;p&gt;Two really useful gems for a Rails project are &lt;a href="https://github.com/swanandp/acts_as_list"&gt;acts_as_list&lt;/a&gt; and &lt;a href="https://github.com/JackDanger/permanent_records"&gt;permanent_records&lt;/a&gt; (or the somewhat more common &lt;a href="https://github.com/ActsAsParanoid/acts_as_paranoid"&gt;acts_as_paranoid&lt;/a&gt;). The first one, &lt;code&gt;acts_as_list&lt;/code&gt;, adds a &lt;code&gt;position&lt;/code&gt; column to your model to provide natural ordering. Usually you don’t want global ordering, but only within an owning model, e.g. the &lt;code&gt;Page&lt;/code&gt; objects inside a &lt;code&gt;Book&lt;/code&gt; have position &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt;, and the &lt;code&gt;Page&lt;/code&gt; objects inside a different &lt;code&gt;Book&lt;/code&gt; also go &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt;. You can use the &lt;code&gt;scope&lt;/code&gt; option to achieve that:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="class"&gt;Page&lt;/span&gt;
  belongs_to &lt;span class="symbol"&gt;:book&lt;/span&gt;
  acts_as_list &lt;span class="key"&gt;scope&lt;/span&gt;: &lt;span class="symbol"&gt;:book&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The problem is that if you are soft-deleting pages using a &lt;code&gt;deleted_at&lt;/code&gt; column, &lt;code&gt;acts_as_list&lt;/code&gt; doesn’t know to exclude deleted pages from the list. This gets annoying if you want to move pages up and down: Imagine you have page 1, then 5 deleted pages, and now you add a new page &lt;code&gt;p&lt;/code&gt; to the end. You want to move your new page to the beginning. You have a button that calls &lt;code&gt;p.move_higher&lt;/code&gt;, but the page won’t appear to move until the user presses the button five times. That is pretty confusing!&lt;/p&gt;

&lt;p&gt;Fortunately &lt;code&gt;acts_as_list&lt;/code&gt; lets you pass a string to &lt;code&gt;scope&lt;/code&gt; that it will evaluate when necessary, and you can even embed Ruby code in it. Look at this, and notice the single quotes!:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="class"&gt;Page&lt;/span&gt;
  belongs_to &lt;span class="symbol"&gt;:book&lt;/span&gt;
  acts_as_list &lt;span class="key"&gt;scope&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;book_id = #{book_id} AND deleted_at IS NULL&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With that code, &lt;code&gt;acts_as_list&lt;/code&gt; will only consider non-deleted pages, so moving a page works as it should.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:illuminatedcomputing.com,2014-07-24:/posts/2014/07/missing-flash/</id>
    <title type="html">Flash movie (.swf) won't load in Rails 4</title>
    <published>2014-07-24T00:00:00Z</published>
    <updated>2014-07-24T00:00:00Z</updated>
    <link rel="alternate" href="https://illuminatedcomputing.com/posts/2014/07/missing-flash/" type="text/html"/>
    <content type="html">
&lt;p&gt;I work on a Rails project that serves Flash &lt;code&gt;.swf&lt;/code&gt; files out of Rails controllers, like this:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;send_file swf_filename, &lt;span class="key"&gt;disposition&lt;/span&gt;: &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;inline&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I know that’s a crazy approach, but the reason is that these movies should only be seen by logged-in users. (Also I didn’t set it up like this. :-)&lt;/p&gt;

&lt;p&gt;Recently some customers complained that Flash movies wouldn’t load. I was pulling my hair out figuring out why. I couldn’t reproduce it. The Rails and nginx logs showed no errors. Their browsers were retrieving the file, but then they would just display a blank white page, sometimes with a thin border where the movie should be.&lt;/p&gt;

&lt;p&gt;Finally I was able to reproduce it on a different machine, and from there I eventually figured out it only happened for people running on the latest version of Flash. I installed the Flash debugger, I turned on tracing, but that didn’t detect any errors.&lt;/p&gt;

&lt;p&gt;Another clue was that the problem wasn’t happening on another site that shares this codebase. By comparing browser requests between the sites, I was able to figure out the cause was an &lt;code&gt;X-Content-Type-Options&lt;/code&gt; HTTP header with a &lt;code&gt;nosniff&lt;/code&gt; value.&lt;/p&gt;

&lt;p&gt;It turns out that Rails 4 adds this header by default, and although the working site was still on Rails 3, my predecessor had upgraded the problem site to 4. So one fix is to turn off that header like this:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;response.headers.except! &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;X-Content-Type-Options&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But a better fix would be to add a header that indicates the correct Content Type. We were serving the file as &lt;code&gt;application/octet-stream&lt;/code&gt;, so with &lt;code&gt;nosniff&lt;/code&gt; the browser couldn’t figure out how to handle the file. We needed to serve the &lt;code&gt;.swf&lt;/code&gt; file as &lt;code&gt;application/x-shockwave-flash&lt;/code&gt; instead:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;response.headers[&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;Content-Type&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;] = &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;application/x-shockwave-flash&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Hopefully this will help someone else out there!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>tag:illuminatedcomputing.com,2014-04-18:/posts/2014/04/timezones/</id>
    <title type="html">Dates and Time Zones in Rails</title>
    <published>2014-04-18T00:00:00Z</published>
    <updated>2014-04-18T00:00:00Z</updated>
    <link rel="alternate" href="https://illuminatedcomputing.com/posts/2014/04/timezones/" type="text/html"/>
    <content type="html">
&lt;p&gt;I work on a video education app that needs to report how many lessons were assigned each day. I have a timetracking app that needs to invoice based on when one month starts and another ends. And I’ve got another app for watching cronjobs, that counts how many failures happened in a given day. All these apps share a problem: if they get time zones wrong, they will give incorrect results. For instance, if a video lesson was assigned on Tuesday after 5pm PDT, its UTC time will be Wednesday. Even though all three apps only show dates, not times, time zones still matter. So here are some lessons I’ve learned dealing with Rails time zones, both programming myself and leading a team.&lt;/p&gt;

&lt;p&gt;But first, here are two articles that lay some groundwork:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://danilenko.org/2012/7/6/rails_timezones/"&gt;The Exhaustive Guide to Rails Time Zones&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="https://web.archive.org/web/20160619104315/http://www.elabs.se:80/blog/36-working-with-time-zones-in-ruby-on-rails"&gt;Working with time zones in Ruby on Rails&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both those posts describe some nice methods provided by ActiveSupport/Rails, as well as why you’d want to use them instead of built-in Ruby methods. For instance, saying &lt;code&gt;Time.now&lt;/code&gt; will get you the time in your OS’s default time zone, whereas &lt;code&gt;Time.zone.now&lt;/code&gt; will get you the time in whatever timezone you put in &lt;code&gt;config/application.rb&lt;/code&gt;. It’s a good idea to use the Rails timezone, since you have more control over that and it’s part of your source control.&lt;/p&gt;

&lt;p&gt;If you want to explore, take a look at &lt;code&gt;ActiveSupport::TimeZone&lt;/code&gt;. You can get a specific time zone like this:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;tz = &lt;span class="constant"&gt;ActiveSupport&lt;/span&gt;::&lt;span class="constant"&gt;TimeZone&lt;/span&gt;[&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;Pacific Time (US &amp;amp; Canada)&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That &lt;code&gt;tz&lt;/code&gt; will be the start of just about everything you do with time. An &lt;code&gt;ActiveSupport::TimeZone&lt;/code&gt; is also what you get from &lt;code&gt;Time.zone&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Those other articles are great, but this post talks about time zones from a higher level, aspiring to share best practices rather than helpful methods. In my examples I’ll assume a Postgres database, although there’s nothing here that won’t work on MySQL as well.&lt;/p&gt;

&lt;h2 id="scope_your_time_zones"&gt;Scope Your Time Zones&lt;/h2&gt;

&lt;p&gt;The first thing to remember is that all times are relative to somebody. Probably that’s a user, but maybe it’s something else. For my video education app, sometimes it’s a teacher and sometimes it’s a student. For my cronjob app, it’s a job (and sometimes a user). But there is always a reference point. In that sense, the articles above that recommend &lt;code&gt;Time.zone.now&lt;/code&gt; are wrong. &lt;code&gt;Time.zone.now&lt;/code&gt; is no better than &lt;code&gt;Time.now&lt;/code&gt; if you need many time zones—and who doesn’t? So it should really be &lt;code&gt;user.time_zone.now&lt;/code&gt;. I’d recommend adding this method to your &lt;code&gt;User&lt;/code&gt; class right from the beginning, so that even if you haven’t yet implemented user-specific time zones, you are still writing the rest of your app correctly:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;time_zone&lt;/span&gt;
  &lt;span class="constant"&gt;ActiveSupport&lt;/span&gt;::&lt;span class="constant"&gt;TimeZone&lt;/span&gt;[&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;Pacific Time (US &amp;amp; Canada)&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;]
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id="ignore_time_zones_as_much_as_possible"&gt;Ignore Time Zones as Much as Possible&lt;/h2&gt;

&lt;p&gt;Now that you’ve got time zones everwhere, the next step is to get rid of them. Thinking about time zones is hard, and finding time zone bugs is hard. You want to avoid them as much as possible!&lt;/p&gt;

&lt;p&gt;It’s been said that in C, if you start thinking about big endian vs little endian, you’re probably doing things wrong. Oftentimes when programmers half-understand something, they do more than they should, and that’s very true with time zones. Your code will be a lot easier to understand if you tackle time zones with a few well-placed strokes, rather than lots of fiddling all over the place.&lt;/p&gt;

&lt;p&gt;One thing to remember is that 07:05:00 PDT and 14:05:00 UTC are the &lt;em&gt;same instant&lt;/em&gt;. If you converted both to seconds since the epoch, you’d get the same number. So in that sense, changing the time zone doesn’t change anything: it’s just a bit of extra metadata hanging onto the time representing someone’s perspective. Knowing that x PDT and y UTC are the same instant is really helpful when you feel the urge to fiddle with timezones. Is your fiddling just a noop?&lt;/p&gt;

&lt;p&gt;By default, Rails comes configured with its default time zone as UTC. Leave it that way! Since every time needs a reference point anyway, your code shouldn’t care about the Rails-wide setting. UTC is a good neutral choice. For one thing, it doesn’t have daylight savings time. And if you see it, you know you’re dealing with a time-zone-less value.&lt;/p&gt;

&lt;p&gt;You should also leave your OS time zone as UTC, if possible. Keeping it consistent with Rails will remove one chance for abiguiuty. And again, it’s a good neutral.&lt;/p&gt;

&lt;p&gt;You also want UTC in your database. If you use a migration to create columns with &lt;code&gt;t.timestamps&lt;/code&gt; or &lt;code&gt;t.datetime :foo&lt;/code&gt;, Rails will make a &lt;code&gt;TIMESTAMP WITHOUT TIME ZONE&lt;/code&gt; column. You can think of this as a time in UTC if you like. Really it’s an int of (micro)seconds since the epoch. Whenever you give a time to ActiveRecord, it will convert it to UTC before it hits Postgres. Or more correctly, it will strip off the timezone part and give Postgres the int. Remember, it’s the same instant! But it’s nice to imagine the column as UTC. If you’re in psql and type &lt;code&gt;SELECT created_at FROM lessons&lt;/code&gt;, that’s what you’re seeing.&lt;/p&gt;

&lt;p&gt;When everything in your stack is UTC, it’s like looking through nice clear glass. You don’t have to think about conversions at each layer.&lt;/p&gt;

&lt;p&gt;You should also strive to make your app code as time-zone-less as possible. The big principle here is to handle time zones once, hopefully at the beginning of the HTTP request, when you decide the correct reference point for all times. Usually that’s &lt;code&gt;current_user.time_zone&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The second article above suggests you add this to your controller:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;around_filter &lt;span class="symbol"&gt;:user_time_zone&lt;/span&gt;, &lt;span class="key"&gt;if&lt;/span&gt;: &lt;span class="symbol"&gt;:current_user&lt;/span&gt;

&lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;user_time_zone&lt;/span&gt;(&amp;amp;block)
  &lt;span class="constant"&gt;Time&lt;/span&gt;.use_zone(current_user.time_zone, &amp;amp;block)
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That makes me pretty uncomfortable. The idea is that you can say &lt;code&gt;Time.zone&lt;/code&gt; everywhere else in your app and always get the current user’s time zone. But I’d rather be explicit about where the time zone is coming from. (Also see below for why &lt;code&gt;use_time&lt;/code&gt; doesn’t help at all for &lt;em&gt;parsing&lt;/em&gt; times.) Instead, write code to take a &lt;code&gt;tz&lt;/code&gt; argument if necessary (emphasis on the if necessary). This will make your code less surprising, less coupled, and easier to test.&lt;/p&gt;

&lt;p&gt;Even better is to write your code to take just a time. Almost always that’s really what you want. Remember that no matter the time zone, it’s all the same instant. Usually a single time is sufficient, because it can be a reference point for creating other times, using &lt;code&gt;t + 1.day&lt;/code&gt; or &lt;code&gt;t + 2.weeks&lt;/code&gt; or whatever. Use a (user|cronjob|foo)-scoped time zone to get your first time, and then forget about time zones for the rest of the stack. If you implemented the &lt;code&gt;User#time_zone&lt;/code&gt; method above, your time zone code is already well-encapsulated, so there’s no need for an &lt;code&gt;around_filter&lt;/code&gt; to further abbreviate things.&lt;/p&gt;

&lt;p&gt;Here is another approach I don’t like. This &lt;a href="https://web.archive.org/web/20150308140507/http://icu.iorahealth.com:80/blog/2012/05/07/expressing-postgresql-timestamps-without-zones-in-local-timee/"&gt;blog post&lt;/a&gt; suggests you deal with time zones in Postgres like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;SELECT created_at AT TIME ZONE 'UTC' AT TIME ZONE 'US/Pacific'&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Does that look strange to you? What’s happening is that you start with a &lt;code&gt;TIMESTAMP WITHOUT TIME ZONE&lt;/code&gt;, so first you tack on a time zone (just metadata), then you convert it to Pacific time. In other words, you’re doing this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;time without zone -&amp;gt; assumed to be UTC -&amp;gt; converted to Pacific Time&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It’s good to know that this is how to get a Postgres timestamp converted to whatever time zone you want, but I wouldn’t recommend it in a Rails app (which is the article’s context). For one thing, Rails and Postgres don’t use the same names for all timezones, so you have to maintain your own mapping between the two. This is one of those chores that will keep nagging you for the life of your app, so I’d rather just avoid it. But more important, this approach means you have to pass your timezone all the way down to the database layer. I’d rather deal with time zones early, get to a TimeWithZone (or even an int), and then forget about time zones for the rest of the code.&lt;/p&gt;

&lt;h2 id="remember_daylight_savings_time"&gt;Remember Daylight Savings Time&lt;/h2&gt;

&lt;p&gt;This is a small tip, but be careful about DST. You should avoid ever writing a fixed offset or a string like “PDT”. This is wrong:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="constant"&gt;Time&lt;/span&gt;.new(&lt;span class="integer"&gt;2014&lt;/span&gt;, &lt;span class="integer"&gt;4&lt;/span&gt;, &lt;span class="integer"&gt;8&lt;/span&gt;, &lt;span class="integer"&gt;3&lt;/span&gt;, &lt;span class="integer"&gt;15&lt;/span&gt;, &lt;span class="integer"&gt;0&lt;/span&gt;, &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;-07:00&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you were after PDT, your code is broken during PST. If you were after MST, your code is broken during MDT. Similarly in SQL if you say &lt;code&gt;AT TIME ZONE 'PDT'&lt;/code&gt;, you’ve broken PST.&lt;/p&gt;

&lt;p&gt;If you stick with the ActiveSupport::TimeZone instances, you can forget about DST, and things will just work. That’s why there is no such thing as this:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="constant"&gt;ActiveSupport&lt;/span&gt;::&lt;span class="constant"&gt;TimeZone&lt;/span&gt;[&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;PDT&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;only this:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="constant"&gt;ActiveSupport&lt;/span&gt;::&lt;span class="constant"&gt;TimeZone&lt;/span&gt;[&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;Pacific Time (US &amp;amp; Canada)&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id="even_dates_are_times"&gt;Even Dates are Times&lt;/h2&gt;

&lt;p&gt;When you think you’re just dealing with dates, time zones probably still matter. Was the lesson assigned on Tuesday or Wednesday? It depends. From the teacher’s perspective? The student’s? The principal’s? Unless you’re really sure, I’d recommend always storing a full date+time in your database. Also, in Ruby avoid converting things to &lt;code&gt;Date&lt;/code&gt;. Of course if you read the articles above you know you don’t want this:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="constant"&gt;Date&lt;/span&gt;.today&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But this isn’t any better:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="constant"&gt;Time&lt;/span&gt;.zone.today&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or even this:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;current_user.time_zone.today&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here is a query I’ve seen:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="constant"&gt;Lesson&lt;/span&gt;.where(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;date(created_at) &amp;gt;= ?&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;, tz.today - &lt;span class="integer"&gt;3&lt;/span&gt;.days)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But that’s wrong, because you’re stripping off all the time zone information. It’s going to report Tuesday’s lessons in Wednesday. (It also means you need a database index on the expression &lt;code&gt;date(created_at)&lt;/code&gt;, which is probably less often useful than a normal index on just the column.)&lt;/p&gt;

&lt;p&gt;To improve this query, I’d write it like this:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="constant"&gt;Lesson&lt;/span&gt;.where(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;created_at &amp;gt;= ?&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;, tz.now.midnight - &lt;span class="integer"&gt;3&lt;/span&gt;.days)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If today is Wednesday (for you), that will give all the lessons created since the beginning of Sunday. Because we’re carrying a full time all the way down to the database query, we don’t have problems with the definition of “today.”&lt;/p&gt;

&lt;p&gt;If you are ever tempted to use &lt;code&gt;today&lt;/code&gt; or &lt;code&gt;to_date&lt;/code&gt;, you probably want these methods instead:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;tz.now.midnight     &lt;span class="comment"&gt;# the start of today, 00:00:00&lt;/span&gt;
tz.now.end_of_day   &lt;span class="comment"&gt;# 23:59:59&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id="parsing_times"&gt;Parsing times&lt;/h2&gt;

&lt;p&gt;Now that you’ve got a per-user time zone, you want to use that to parse date/time inputs from that user. If you user types “3:15”, you want to interpret that as 3:15 in the user’s time zone.&lt;/p&gt;

&lt;p&gt;There is a &lt;code&gt;parse&lt;/code&gt; method on &lt;code&gt;ActiveSupport::TimeZone&lt;/code&gt;, but unfortunately no &lt;code&gt;strptime&lt;/code&gt;. If you say this, you get the wrong result:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="constant"&gt;Time&lt;/span&gt;.strptime(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;2014-04-08 03:15&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;%Y-%m-%d %H:%M&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;).in_time_zone(tz)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s because &lt;code&gt;strptime&lt;/code&gt; assumes the time is in the default time zone (hopefully UTC), and &lt;code&gt;in_time_zone&lt;/code&gt; does not change the “instant” the time represents, only the perspective used to view it. If you’re lucky to have a standardish format, this will work:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;tz.parse(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;2014-04-08 03:15&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If your format is something weirder, or you just don’t trust &lt;code&gt;parse&lt;/code&gt; with its heuristic-based approach, then you’re probably out of luck. A previous version of this article recommended &lt;code&gt;Time.use_zone(tz) { Time.strptime(...) }&lt;/code&gt;, but that doesn’t work, because &lt;code&gt;use_time&lt;/code&gt; only changes &lt;code&gt;Time.zone&lt;/code&gt;. It doesn’t change &lt;code&gt;Time.strptime&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Another approach with &lt;code&gt;strptime&lt;/code&gt; that doesn’t work is to concatenate the time zone to your string and use &lt;code&gt;%Z&lt;/code&gt; (and friends) in your format, like this:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="constant"&gt;Time&lt;/span&gt;.strptime(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt;2014-04-08 03:15&lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt; + &lt;span class="string"&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;span class="content"&gt; &lt;/span&gt;&lt;span class="delimiter"&gt;'&lt;/span&gt;&lt;/span&gt; + tz.formatted_offset, &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;%Y-%m-%d %H:%M %:z&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The problem here is that &lt;code&gt;tz.formatted_offset&lt;/code&gt; really depends on the time of year because of Daylight Savings Time. But you don’t know that until you parse the string. You could pass the timezone abbreviation instead, like &lt;code&gt;PDT&lt;/code&gt;, but that has the same problem. And &lt;code&gt;%Z&lt;/code&gt; doesn’t understand long names like &lt;code&gt;Pacific Time (US &amp;amp; Canada)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The only approach I know that works is to parse the time with your default time zone, then feed the bits into &lt;code&gt;tz.local&lt;/code&gt;, like so:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;t = &lt;span class="constant"&gt;Time&lt;/span&gt;.strptime(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;2014-04-08 03:15&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;%Y-%m-%d %H:%M&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;)
tz.local(t.year, t.month, t.mday, t.hour, t.min)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sorry, that’s the best I can do!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: I &lt;a href="https://github.com/rails/rails/pull/19618"&gt;added a &lt;code&gt;strptime&lt;/code&gt; method to the &lt;code&gt;TimeZone&lt;/code&gt; class&lt;/a&gt; (my first Rails code contribution), so hopefully you’ll start seeing it in future versions!&lt;/p&gt;

&lt;h2 id="displaying_times"&gt;Displaying times&lt;/h2&gt;

&lt;p&gt;So much for times as inputs. Times as outputs is a lot easier. Your rule should be to ignore time zones until the last minute, when you actually format the value for rendering. So it should go right into your view:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;= lesson.created_at.in_time_zone(current_user.time_zone).strftime("%A, %B %-d, %Y")&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You might want a helper for this though, something like:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;format_time&lt;/span&gt;(time, tz, format)
  time.in_time_zone(tz).strftime(format)
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then your Haml can be:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;= format_time(lesson.created_at, current_user.time_zone, "%A, %B %-d, %Y")&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or de-parameterize that as much as you like:&lt;/p&gt;

&lt;div class="CodeRay"&gt;&lt;div class="code"&gt;&lt;pre&gt;&lt;code class="language-ruby"&gt;&lt;span class="keyword"&gt;def&lt;/span&gt; &lt;span class="function"&gt;format_time&lt;/span&gt;(time)
  time.in_time_zone(current_user.time_zone).strftime(&lt;span class="string"&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;span class="content"&gt;%A, %B %-d, %Y&lt;/span&gt;&lt;span class="delimiter"&gt;"&lt;/span&gt;&lt;/span&gt;)
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;= format_time(lesson.created_at)&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;So in general, my principles for handling times in Rails are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Even dates are times.&lt;/li&gt;

&lt;li&gt;Set “global” time zones to UTC everywhere you can.&lt;/li&gt;

&lt;li&gt;Don’t ever use global time zones; scope it to a user or whatever is appropriate.&lt;/li&gt;

&lt;li&gt;To most of your code, a time is just an instant.&lt;/li&gt;

&lt;li&gt;Push time zone inputs to the very beginning of your request, to the top of your stack.&lt;/li&gt;

&lt;li&gt;Push time zone outputs to the very end of your request, when rendering the view.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Good luck!&lt;/p&gt;
</content>
  </entry>
</feed>

