TL;DR: I have an ActiveRecord model in Rails 5.1 which has a composite field, serialised as YAML to a text field in MySQL. I want date fields formatted in a very specific way, but Rails is trying to be clever when it writes to DB, and I don't understand why.
Details
I'm trying to persist a very simple model
class ReportService < ApplicationRecord
# AR associations omitted
serialize :report_params, ReportParamsSerializer
end
The report params serialiser isn't doing any fancy, just stripping off some quotes from a string (rationale behind this explained in this SO question):
class ReportParamsSerializer
def self.dump(report_params)
yaml_string = report_params.to_yaml
quoted_date_regex = /\'(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d)\'/
yaml_string.gsub!(quoted_date_regex, '\1 ')
yaml_string
end
def self.load(report_params)
YAML.load(report_params) unless report_params.nil?
end
end
here report_params
is just some hash:
{"title"=>nil, "date_from"=>"2018-05-02 04:00:00", "date_to"=>"2018-05-03 03:59:00", "output"=>"PDF", ...}
And printing the output to console gives the YAML I want:
---
title:
date_from: 2018-05-02 04:00:00
date_to: 2018-05-03 03:59:00
...
However, when I look in the database, I see this:
---
title:
date_from: 2018-05-02 05:00:00.000000000 +01:00
date_to: 2018-05-03 04:59:00.000000000 +01:00
....
Any idea why this is happening?
EDIT: I added more logging statements to show me when the serializer was invoked.
def self.dump(report_params)
yaml_string = report_params.to_yaml
puts "presubstitution: #{yaml_string}"
quoted_date_regex = /\'(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d)\'/
yaml_string.gsub!(quoted_date_regex, '\1 ')
puts "post_substitution: #{yaml_string}"
yaml_string
end
Running
puts "report args: #{report_args.inspect}"
puts "as YAML:"
puts ReportParamsSerializer.dump(report_args[:report_params])
ReportService.create(report_args)
gives me output like:
as YAML:
presubstitution: ---
title:
date_from: '2018-05-01 23:00:00'
date_to: '2018-05-02 22:59:00'
...
post_substitution: ---
title:
date_from: 2018-05-01 23:00:00
date_to: 2018-05-02 22:59:00
---
title:
date_from: 2018-05-01 23:00:00
date_to: 2018-05-02 22:59:00
...
presubstitution: ---
title:
date_from: 2018-05-02 00:00:00.000000000 +01:00
date_to: 2018-05-02 23:59:00.000000000 +01:00
...
post_substitution: ---
title:
date_from: 2018-05-02 00:00:00.000000000 +01:00
date_to: 2018-05-02 23:59:00.000000000 +01:00
...
SQL (47.7ms) INSERT INTO `report_services` (other_stuff, `report_params`, ) VALUES (other_values, '---\ntitle: \ndate_from: 2018-05-02 00:00:00.000000000 +01:00\ndate_to: 2018-05-02 23:59:00.000000000 +01:00\ ...)
presubstitution: ---
title:
date_from: 2018-05-02 00:00:00.000000000 +01:00
date_to: 2018-05-02 23:59:00.000000000 +01:00
...
post_substitution: ---
title:
date_from: 2018-05-02 00:00:00.000000000 +01:00
date_to: 2018-05-02 23:59:00.000000000 +01:00