mirror of
https://github.com/paper-trail-gem/paper_trail.git
synced 2022-11-09 11:33:19 -05:00
Extract private methods re: has many through
I'm not sure about the names of these new methods, and am open to ideas.
This commit is contained in:
parent
1a8514ae00
commit
c116d9685c
2 changed files with 65 additions and 39 deletions
|
@ -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: 41 # Goal: 15
|
Max: 37 # Goal: 15
|
||||||
|
|
||||||
Metrics/CyclomaticComplexity:
|
Metrics/CyclomaticComplexity:
|
||||||
Max: 13 # Goal: 6
|
Max: 13 # Goal: 6
|
||||||
|
|
|
@ -68,6 +68,65 @@ module PaperTrail
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Examine the `source_reflection`, i.e. the "source" of `assoc` the
|
||||||
|
# `ThroughReflection`. The source can be a `BelongsToReflection`
|
||||||
|
# or a `HasManyReflection`.
|
||||||
|
#
|
||||||
|
# If the association is a has_many association again, then call
|
||||||
|
# reify_has_manys for each record in `through_collection`.
|
||||||
|
#
|
||||||
|
# @api private
|
||||||
|
def hmt_collection(through_collection, assoc, options, transaction_id)
|
||||||
|
if !assoc.source_reflection.belongs_to? && through_collection.present?
|
||||||
|
hmt_collection_through_has_many(
|
||||||
|
through_collection, assoc, options, transaction_id
|
||||||
|
)
|
||||||
|
else
|
||||||
|
hmt_collection_through_belongs_to(
|
||||||
|
through_collection, assoc, options, transaction_id
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# @api private
|
||||||
|
def hmt_collection_through_has_many(through_collection, assoc, options, transaction_id)
|
||||||
|
through_collection.each do |through_model|
|
||||||
|
reify_has_manys(transaction_id, through_model, options)
|
||||||
|
end
|
||||||
|
|
||||||
|
# At this point, the "through" part of the association chain has
|
||||||
|
# been reified, but not the final, "target" part. To continue our
|
||||||
|
# example, `model.sections` (including `model.sections.paragraphs`)
|
||||||
|
# has been loaded. However, the final "target" part of the
|
||||||
|
# association, that is, `model.paragraphs`, has not been loaded. So,
|
||||||
|
# we do that now.
|
||||||
|
through_collection.flat_map { |through_model|
|
||||||
|
through_model.public_send(assoc.name.to_sym).to_a
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# @api private
|
||||||
|
def hmt_collection_through_belongs_to(through_collection, assoc, options, transaction_id)
|
||||||
|
collection_keys = through_collection.map { |through_model|
|
||||||
|
through_model.send(assoc.source_reflection.foreign_key)
|
||||||
|
}
|
||||||
|
version_id_subquery = assoc.klass.paper_trail_version_class.
|
||||||
|
select("MIN(id)").
|
||||||
|
where("item_type = ?", assoc.class_name).
|
||||||
|
where("item_id IN (?)", collection_keys).
|
||||||
|
where(
|
||||||
|
"created_at >= ? OR transaction_id = ?",
|
||||||
|
options[:version_at],
|
||||||
|
transaction_id
|
||||||
|
).
|
||||||
|
group("item_id").
|
||||||
|
to_sql
|
||||||
|
versions = versions_by_id(assoc.klass, version_id_subquery)
|
||||||
|
collection = Array.new assoc.klass.where(assoc.klass.primary_key => collection_keys)
|
||||||
|
prepare_array_for_has_many(collection, options, versions)
|
||||||
|
collection
|
||||||
|
end
|
||||||
|
|
||||||
# Set all the attributes in this version on the model.
|
# Set all the attributes in this version on the model.
|
||||||
def reify_attributes(model, version, attrs)
|
def reify_attributes(model, version, attrs)
|
||||||
enums = model.class.respond_to?(:defined_enums) ? model.class.defined_enums : {}
|
enums = model.class.respond_to?(:defined_enums) ? model.class.defined_enums : {}
|
||||||
|
@ -244,45 +303,12 @@ module PaperTrail
|
||||||
# `through_collection` will contain Sections.
|
# `through_collection` will contain Sections.
|
||||||
through_collection = model.send(assoc.options[:through])
|
through_collection = model.send(assoc.options[:through])
|
||||||
|
|
||||||
# Examine the `source_reflection`, i.e. the "source" of `assoc` the
|
# Now, given the collection of "through" models (e.g. sections), load
|
||||||
# `ThroughReflection`. The source can be a `BelongsToReflection`
|
# the collection of "target" models (e.g. paragraphs)
|
||||||
# or a `HasManyReflection`.
|
collection = hmt_collection(through_collection, assoc, options, transaction_id)
|
||||||
#
|
|
||||||
# If the association is a has_many association again, then call
|
|
||||||
# reify_has_manys for each record in `through_collection`.
|
|
||||||
if !assoc.source_reflection.belongs_to? && through_collection.present?
|
|
||||||
through_collection.each do |through_model|
|
|
||||||
reify_has_manys(transaction_id, through_model, options)
|
|
||||||
end
|
|
||||||
|
|
||||||
# At this point, the "through" part of the association chain has
|
# Finally, assign the `collection` of "target" models, e.g. to
|
||||||
# been reified, but not the final, "target" part. To continue our
|
# `model.paragraphs`.
|
||||||
# example, `model.sections` (including `model.sections.paragraphs`)
|
|
||||||
# has been loaded. However, the final "target" part of the
|
|
||||||
# association, that is, `model.paragraphs`, has not been loaded. So,
|
|
||||||
# we do that now.
|
|
||||||
collection = through_collection.flat_map { |through_model|
|
|
||||||
through_model.public_send(assoc.name.to_sym).to_a
|
|
||||||
}
|
|
||||||
else
|
|
||||||
collection_keys = through_collection.map { |through_model|
|
|
||||||
through_model.send(assoc.source_reflection.foreign_key)
|
|
||||||
}
|
|
||||||
|
|
||||||
version_id_subquery = assoc.klass.paper_trail_version_class.
|
|
||||||
select("MIN(id)").
|
|
||||||
where("item_type = ?", assoc.class_name).
|
|
||||||
where("item_id IN (?)", collection_keys).
|
|
||||||
where("created_at >= ? OR transaction_id = ?", options[:version_at], transaction_id).
|
|
||||||
group("item_id").
|
|
||||||
to_sql
|
|
||||||
versions = versions_by_id(assoc.klass, version_id_subquery)
|
|
||||||
collection = Array.new assoc.klass.where(assoc.klass.primary_key => collection_keys)
|
|
||||||
prepare_array_for_has_many(collection, options, versions)
|
|
||||||
end
|
|
||||||
|
|
||||||
# To continue our example above, assign to `model.paragraphs` the
|
|
||||||
# `collection` (an array of `Paragraph`s).
|
|
||||||
model.send(assoc.name).proxy_association.target = collection
|
model.send(assoc.name).proxy_association.target = collection
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue