paper-trail-gem--paper_trail/lib/paper_trail/serializers/yaml.rb

43 lines
1.4 KiB
Ruby
Raw Normal View History

require "yaml"
module PaperTrail
module Serializers
2016-04-09 05:08:34 +00:00
# The default serializer for, e.g. `versions.object`.
module YAML
Deprecate where_object_changes reading YAML from text column * clarify the issue with `where_object_changes` for numeric values History --- [The first problem mention](https://github.com/airblade/paper_trail/commit/1ad78383aa58d6b74e237f84310f7440712710ab). [The major issue](https://github.com/airblade/paper_trail/issues/803) with relevant discussions. Details --- I see the problem only with one specific case – when the method is `where_object_changes` and the serializer is YAML. Which is a default configuration. I see there are 6 types of queries with a numeric value for `where_object_changes` and `where_object` (grabbed from `version_spec.rb`): ``` .where_object_changes N1 SELECT "versions".* FROM "versions" WHERE "versions"."item_id" = 1 AND "versions"."item_type" = 'Widget' AND (object_changes @> '{"an_integer":[1]}') ORDER BY "versions"."created_at" ASC, "versions"."id" ASC N1 SELECT "versions".* FROM "versions" WHERE "versions"."item_id" = 1 AND "versions"."item_type" = 'Widget' AND ("versions"."object_changes" ILIKE '% an_integer: - 1 %' OR "versions"."object_changes" ILIKE '% an_integer: -% - 1 %') ORDER BY "versions"."created_at" ASC, "versions"."id" ASC N3 SELECT "versions".* FROM "versions" WHERE "versions"."item_id" = 1 AND "versions"."item_type" = 'Widget' AND (((object_changes->>'an_integer' ILIKE '[1,%') OR (object_changes->>'an_integer' ILIKE '[%,1]%'))) ORDER BY "versions"."created_at" ASC, "versions"."id" ASC .where_object N4 SELECT "versions".* FROM "versions" WHERE (object @> '{"an_integer":1}') N5 SELECT "versions".* FROM "versions" WHERE (object->>'an_integer' = '1') N6 SELECT "versions".* FROM "versions" WHERE ("versions"."object" ILIKE '% an_integer: 1 %') ``` The only problematic one is N2. It incorrectly matches `object_changes` like ``` --- name: - - Kimberli an_integer: - - 0 created_at: - - 2017-09-28 18:30:13.369889000 Z updated_at: - - 2017-09-28 18:30:13.369889000 Z id: - - 1 --- name: - foobar - Hayes an_integer: - 77 - 1 updated_at: - 2017-09-28 18:30:13.383966000 Z - 2017-09-28 18:30:13.395539000 Z ```
2017-10-23 17:07:27 +00:00
E_WHERE_OBJ_CHANGES = <<-STR.squish.freeze
where_object_changes has a known issue. When reading YAML from a text
column, it may return more records than expected. Instead of a warning,
this method may raise an error in the future. Please join the discussion
at https://github.com/airblade/paper_trail/pull/997
STR
extend self # makes all instance methods become module methods as well
def load(string)
::YAML.load string
end
def dump(object)
::YAML.dump object
end
# Returns a SQL LIKE condition to be used to match the given field and
# value in the serialized object.
def where_object_condition(arel_field, field, value)
arel_field.matches("%\n#{field}: #{value}\n%")
end
# Returns a SQL LIKE condition to be used to match the given field and
# value in the serialized `object_changes`.
def where_object_changes_condition(arel_field, field, value)
Deprecate where_object_changes reading YAML from text column * clarify the issue with `where_object_changes` for numeric values History --- [The first problem mention](https://github.com/airblade/paper_trail/commit/1ad78383aa58d6b74e237f84310f7440712710ab). [The major issue](https://github.com/airblade/paper_trail/issues/803) with relevant discussions. Details --- I see the problem only with one specific case – when the method is `where_object_changes` and the serializer is YAML. Which is a default configuration. I see there are 6 types of queries with a numeric value for `where_object_changes` and `where_object` (grabbed from `version_spec.rb`): ``` .where_object_changes N1 SELECT "versions".* FROM "versions" WHERE "versions"."item_id" = 1 AND "versions"."item_type" = 'Widget' AND (object_changes @> '{"an_integer":[1]}') ORDER BY "versions"."created_at" ASC, "versions"."id" ASC N1 SELECT "versions".* FROM "versions" WHERE "versions"."item_id" = 1 AND "versions"."item_type" = 'Widget' AND ("versions"."object_changes" ILIKE '% an_integer: - 1 %' OR "versions"."object_changes" ILIKE '% an_integer: -% - 1 %') ORDER BY "versions"."created_at" ASC, "versions"."id" ASC N3 SELECT "versions".* FROM "versions" WHERE "versions"."item_id" = 1 AND "versions"."item_type" = 'Widget' AND (((object_changes->>'an_integer' ILIKE '[1,%') OR (object_changes->>'an_integer' ILIKE '[%,1]%'))) ORDER BY "versions"."created_at" ASC, "versions"."id" ASC .where_object N4 SELECT "versions".* FROM "versions" WHERE (object @> '{"an_integer":1}') N5 SELECT "versions".* FROM "versions" WHERE (object->>'an_integer' = '1') N6 SELECT "versions".* FROM "versions" WHERE ("versions"."object" ILIKE '% an_integer: 1 %') ``` The only problematic one is N2. It incorrectly matches `object_changes` like ``` --- name: - - Kimberli an_integer: - - 0 created_at: - - 2017-09-28 18:30:13.369889000 Z updated_at: - - 2017-09-28 18:30:13.369889000 Z id: - - 1 --- name: - foobar - Hayes an_integer: - 77 - 1 updated_at: - 2017-09-28 18:30:13.383966000 Z - 2017-09-28 18:30:13.395539000 Z ```
2017-10-23 17:07:27 +00:00
::ActiveSupport::Deprecation.warn(E_WHERE_OBJ_CHANGES)
# Need to check first (before) and secondary (after) fields
m1 = "%\n#{field}:\n- #{value}\n%"
m2 = "%\n#{field}:\n-%\n- #{value}\n%"
arel_field.matches(m1).or(arel_field.matches(m2))
end
end
end
end