-
-
Notifications
You must be signed in to change notification settings - Fork 277
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cop idea: Prefer #change
over #round
for Time/DateTime
#1715
Comments
#change
over #round
#change
over #round
#change
over #round
for Time/DateTime
‘change’ is a Rails thing? And it’s probably a good recommendation for Rails code in general, not just specs? Would ‘round’ be always identical to ‘change’ (i mean floor/ceil)? Good to move this to rubocop-rails? |
Yes, it should be a RSpec/Rails cop.
Perhaps, but personally I had such problems only in specs.
No,
I think if rounding affects the result, we need to use Timecop or look for problems in the code.
Yep. |
I see, thanks for this research. With what you say, it seems that indeed, this cop makes more sense in Rails RSpec specs. I recall that the the default timestamp nanosecond precision varies across DBs, and it was discarding nanoseconds in MySQL until recently. But how this is actually done? Does it round down at milliseconds? How does it even work if user.created_at has millisecond precision, and the result of ‘round’ has whole seconds precision? With this cop our ultimate goal is to avoid flakiness, right? |
No, For PostgreSQL:
Reference: https://www.toptal.com/ruby-on-rails/timestamp-truncation-rails-activerecord-tale#the-cause For MySQL:
Reference: https://www.bigbinary.com/blog/rails-5-handles-datetime-with-better-precision If mysql adapter supports precision, rails will drop nanoseconds: create_table "users", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
t.datetime "updated_at", precision: 6, null: false
end irb(main):001:0> ActiveRecord::Base.connection.select_value('SELECT version()')
=> "10.4.30-MariaDB-1:10.4.30+maria~ubu2004-log"
irb(main):002:0> ActiveRecord::Base.connection.execute("UPDATE `users` SET `updated_at` = '2016-01-18 23:59:59.999999999' WHERE `users`.`id` = 1")
=> nil
irb(main):003:0> User.find(1).updated_at.utc
=> 2016-01-18 23:59:59.999999 UTC |
Also rails drops microseconds in job argument assertions |
I don't get your question. |
user.created_at - floating point, 6 to nine digits of precision Chances of ‘eq’ to match are one in a million. Why do we even need this cop then? |
The main idea of this cop is to prevent skipping precision for datetime fields. I believe that the test above should be written more reliably. # bad, another example
expect(user.created_at.to_i).to eq Time.now.utc.to_i P.S. I think the old problem is no longer relevant. |
Could ‘change’ be considered as an option to write time comparisons more reliably? I suggest starting from scratch, getting examples of unreliable specs, and finding a common solution we could suggest everyone to use. This seems related and a good starting point rails/rails#38831 |
Describe the solution you'd like
Rubocop
ydakuka@yauhenid:~/Work/project$ bin/rails_docker rubocop -V 1.56.2 (using Parser 3.2.2.3, rubocop-ast 1.29.0, running on ruby 2.7.8) [x86_64-linux] - rubocop-capybara 2.18.0 - rubocop-factory_bot 2.23.1 - rubocop-performance 1.19.0 - rubocop-rails 2.21.0 - rubocop-rake 0.6.0 - rubocop-rspec 2.24.0 - rubocop-thread_safety 0.5.1
The text was updated successfully, but these errors were encountered: