Extract query object: WhereObjectChanges
This is the first query object in PT, so I'll explain the rationale. In my mind, the Query Object pattern is a subclass of the Method Object pattern. http://refactoring.com/catalog/replaceMethodWithMethodObject.html The goal is simple, to break up a very large method. In this case, there is another big advantage; it gives us a place to extract methods that will actually be private. Better still, little private methods will not pollut the namespace of classes that mix in `VersionConcern`.
This commit is contained in:
parent
c7efd62fe2
commit
012533ad7d
|
@ -2,7 +2,7 @@
|
||||||
# one by one as the offenses are removed from the code base.
|
# one by one as the offenses are removed from the code base.
|
||||||
|
|
||||||
Metrics/AbcSize:
|
Metrics/AbcSize:
|
||||||
Max: 30 # Goal: 15
|
Max: 28 # Goal: 15
|
||||||
|
|
||||||
Metrics/CyclomaticComplexity:
|
Metrics/CyclomaticComplexity:
|
||||||
Max: 8 # Goal: 6
|
Max: 8 # Goal: 6
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
module PaperTrail
|
||||||
|
module Queries
|
||||||
|
module Versions
|
||||||
|
# @api private
|
||||||
|
class WhereObjectChanges
|
||||||
|
# - version_model_class - The class that VersionConcern was mixed into.
|
||||||
|
# - attributes - A `Hash` of attributes and values. See the public API
|
||||||
|
# documentation for details.
|
||||||
|
# @api private
|
||||||
|
def initialize(version_model_class, attributes = {})
|
||||||
|
@version_model_class = version_model_class
|
||||||
|
|
||||||
|
# Currently, this `deep_dup` is necessary because the `jsonb` branch
|
||||||
|
# modifies `@attributes`, and that would be a nasty suprise for
|
||||||
|
# consumers of this class.
|
||||||
|
# TODO: Stop modifying `@attributes`, then remove `deep_dup`.
|
||||||
|
@attributes = attributes.deep_dup
|
||||||
|
end
|
||||||
|
|
||||||
|
# @api private
|
||||||
|
def execute
|
||||||
|
case @version_model_class.columns_hash["object_changes"].type
|
||||||
|
when :jsonb
|
||||||
|
jsonb
|
||||||
|
when :json
|
||||||
|
json
|
||||||
|
else
|
||||||
|
text
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# @api private
|
||||||
|
def json
|
||||||
|
predicates = []
|
||||||
|
values = []
|
||||||
|
@attributes.each do |field, value|
|
||||||
|
predicates.push(
|
||||||
|
"((object_changes->>? ILIKE ?) OR (object_changes->>? ILIKE ?))"
|
||||||
|
)
|
||||||
|
values.concat([field, "[#{value.to_json},%", field, "[%,#{value.to_json}]%"])
|
||||||
|
end
|
||||||
|
sql = predicates.join(" and ")
|
||||||
|
@version_model_class.where(sql, *values)
|
||||||
|
end
|
||||||
|
|
||||||
|
# @api private
|
||||||
|
def jsonb
|
||||||
|
@attributes.each { |field, value| @attributes[field] = [value] }
|
||||||
|
@version_model_class.where("object_changes @> ?", @attributes.to_json)
|
||||||
|
end
|
||||||
|
|
||||||
|
# @api private
|
||||||
|
def text
|
||||||
|
arel_field = @version_model_class.arel_table[:object_changes]
|
||||||
|
where_conditions = @attributes.map { |field, value|
|
||||||
|
::PaperTrail.serializer.where_object_changes_condition(arel_field, field, value)
|
||||||
|
}
|
||||||
|
where_conditions = where_conditions.reduce { |a, e| a.and(e) }
|
||||||
|
@version_model_class.where(where_conditions)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,5 +1,6 @@
|
||||||
require "active_support/concern"
|
require "active_support/concern"
|
||||||
require "paper_trail/attribute_serializers/object_changes_attribute"
|
require "paper_trail/attribute_serializers/object_changes_attribute"
|
||||||
|
require "paper_trail/queries/versions/where_object_changes"
|
||||||
|
|
||||||
module PaperTrail
|
module PaperTrail
|
||||||
# Originally, PaperTrail did not provide this module, and all of this
|
# Originally, PaperTrail did not provide this module, and all of this
|
||||||
|
@ -167,29 +168,7 @@ module PaperTrail
|
||||||
# @api public
|
# @api public
|
||||||
def where_object_changes(args = {})
|
def where_object_changes(args = {})
|
||||||
raise ArgumentError, "expected to receive a Hash" unless args.is_a?(Hash)
|
raise ArgumentError, "expected to receive a Hash" unless args.is_a?(Hash)
|
||||||
|
Queries::Versions::WhereObjectChanges.new(self, args).execute
|
||||||
if columns_hash["object_changes"].type == :jsonb
|
|
||||||
args.each { |field, value| args[field] = [value] }
|
|
||||||
where("object_changes @> ?", args.to_json)
|
|
||||||
elsif columns_hash["object_changes"].type == :json
|
|
||||||
predicates = []
|
|
||||||
values = []
|
|
||||||
args.each do |field, value|
|
|
||||||
predicates.push(
|
|
||||||
"((object_changes->>? ILIKE ?) OR (object_changes->>? ILIKE ?))"
|
|
||||||
)
|
|
||||||
values.concat([field, "[#{value.to_json},%", field, "[%,#{value.to_json}]%"])
|
|
||||||
end
|
|
||||||
sql = predicates.join(" and ")
|
|
||||||
where(sql, *values)
|
|
||||||
else
|
|
||||||
arel_field = arel_table[:object_changes]
|
|
||||||
where_conditions = args.map { |field, value|
|
|
||||||
PaperTrail.serializer.where_object_changes_condition(arel_field, field, value)
|
|
||||||
}
|
|
||||||
where_conditions = where_conditions.reduce { |a, e| a.and(e) }
|
|
||||||
where(where_conditions)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def primary_key_is_int?
|
def primary_key_is_int?
|
||||||
|
|
Loading…
Reference in New Issue