The Ruby core language and standard library include two classes that represent timestamps: Time and DateTime. And even though they fill similar needs, they have different internals and aren’t comparable.

1
2
3
4
5
6
7
8
9
10
11
irb(main):001:0> require 'date'
true
irb(main):002:0> time = Time.now
2018-01-14 16:40:29 +0100
irb(main):003:0> datetime = DateTime.now
#<DateTime: 2018-01-14T16:40:40+01:00 ((2458133j,56440s,60191240n),+3600s,2299161j)>
irb(main):004:0> time < datetime
ArgumentError: comparison of Time with DateTime failed
      from (irb):5:in `<'
     from (irb):5
     from /home/chris/.rbenv/versions/2.4.2/bin/irb:11:in `<main>'

Rails adds the ActiveSupport::TimeWithZone class and extends the core classes in a number of ways including by allowing comparison of instances of different classes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
irb(main):005:0> require 'active_support'
=> true
irb(main):006:0> require 'active_support/core_ext'
=> true
irb(main):007:0> time = Time.now
=> 2018-01-14 16:43:18 +0100
irb(main):008:0> datetime = DateTime.now
=> Sun, 14 Jan 2018 16:43:24 +0100
irb(main):009:0> time < datetime
=> true
irb(main):010:0> Time.zone = 'Eastern Time (US & Canada)'
=> "Eastern Time (US & Canada)"
irb(main):011:0> time_with_zone = Time.zone.now
=> Sun, 14 Jan 2018 10:44:10 EST -05:00
irb(main):012:0> date < time_with_zone
=> true

In most cases, this frees you up to write code without having to explicitly convert between types or even know which types you’re comparing. But eventually you might find yourself try to test the equality of two timestamps which should logically be the same:

1
assert_equal email.sent_at, email_delivery.created_at

The error message in this case only deepens the mystery:

1
2
3
No visible difference in the ActiveSupport::TimeWithZone#inspect output.
You should look at the implementation of #== on ActiveSupport::TimeWithZone or its members.
Sun, 14 Jan 2018 11:13:40 EST -05:00

The thing to remember here is that all of these classes store timestamps with much more precision than they usually display. In the case of ActiveSupport::TimeWithZone, that goes down to millisecond and even nanosecond precision.

1
2
3
4
5
6
7
8
9
10
irb(main):013:0> time_with_zone.to_s
=> "2018-01-14 10:44:10 -0500"
irb(main):014:0> time_with_zone.to_i
=> 1515944650
irb(main):015:0> time_with_zone.to_f
=> 1515944650.4874508
irb(main):016:0> time_with_zone.usec
=> 487450
irb(main):017:0> time_with_zone.nsec
=> 487450777

So when we want to compare timestamps that we know to be unequal, the usual operators (>, <, …) are fine. But if we’re checking for relative equality, we’ll need to use some representations of the timestamps.

In The Minitest Cookbook I advised developers to compare dates and times using a string representation since, when you do fail a test, the message returned will usually be meaningful.

1
2
send_time = email.sent_at
assert_equal "2017-11-02 17:09", send_time.strftime("%Y-%m-%d %H:%M")

I still think that’s the way to go when you’re comparing generated data with a constant value, but in other cases like where you’re checking the equality of two generated values, it’s usually better to compare numeric representations of the timestamps as:

1
2
3
send_time = email.sent_at
delivery_time = email.delivery.created_at
assert_equal send_time.to_i, delivery_time.to_i

Keep in mind that there’s always the chance that the two timestamps might be generated across a second boundary which would cause the test as written to fail. If you’re looking for some additional insurance for this situation, you could also assert that the numeric representations of the timestamps are within a delta of one another:

1
2
3
4
send_time = email.sent_at
delivery_time = email.delivery.created_at
delta = 0.01
assert_in_delta send_time.to_f, delivery_time.to_f, delta

Rails relies on a standard project structure and a strong set of conventions to keep things neat and tidy - models separated from controllers, configuration in another folder structured just so. The exception that proves the rule in this case, though, would have to be Rails view helpers. Helpers tend to be a dumping ground for all the random bits of view logic, formatting, and utility code that accumulate in every web application, and if you’re not disciplined (and most of us aren’t), app/helpers can degenerate into a jungle quickly.

But helpers fill a necessary role in our applications by removing presentation logic from our templates and moving it to methods which makes it easier to test. So even though they’re going to be hard to organize almost by definition, we can still be disciplined about testing them. In other words: your view helpers might still look like spaghetti, but at least we can make sure it’s well-tested spaghetti.

Ruby on Rails’ bundled support for automated testing has contributed to building a culture of testing within the community, but it’s also been a source of some debate. Differences in testing styles and preferences have spawned long-running discussions and flame wars over the years. Most of this amounts to bikeshedding, but if there’s one area where The Rails Way has lagged behind RSpec, it’s been in the area of end-to-end application testing. RSpec has long had expressive feature specs based on Capybara, while Rails default integration tests, though functional, have never been as expressive.

With the release of version 5.1, Rails introduces system tests built on Capybara. These look like just the thing to fill this longstanding gap, and the fact that they’ll be configured to work right out of the box with no additional setup required will make it easier for more developers to start using them. In this post, we’re going to look at the approach Rails takes toward system tests and what kind of advantages they offer over both old-school integration tests and current solutions for testing apps with Capybara.

When I finally manage to master an API or framework
by CommitStrip.com

API versioning is one of those topics that divides developers into two camps: those who just know that their way is the best way, and those that are confused by the first camp and would rather pass on the whole thing. Once we set aside the bikeshedding, there are sound, sane justifications for choosing one method over another, but in a lot of cases, discussions move from theoretical to hypothetical problems instead of worrying about making things that work.

The good news for Rails developers is that adding versions to an existing application doesn’t have to be painful. If you know what to do, you can implement it and maintain it with little effort.

In this article, we’ll look at what you get by versioning your API, why you need to think really hard before deciding not to, and how to update your application to make it work.

The introduction of API-only applications in Rails 5 makes it easier than ever to write simplified apps that render JSON responses. This is terrific news for those of us who’ve spent years building up expertise in the platform, but as we already know, getting off on the right foot makes a big difference in how development proceeds. This tutorial offers a quick overview of the first steps you’ll use to get set up and coding on a typical Rails API application.