0

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
rwold
  • 2,216
  • 1
  • 14
  • 22
  • can you provide the output after `yaml_string = report_params.to_yaml`? To eliminate the possibility that yaml is already serializing your times – 23tux May 03 '18 at 12:49
  • It was as above, but this showed me the serialization was being called several times, with different inputs, so thanks ... – rwold May 03 '18 at 13:33

0 Answers0