mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Reflection for attachments
Add the ability to reflect on the attachments that have been defined using ActiveRecord::Reflection.
This commit is contained in:
parent
0d7f13a622
commit
bc3b6ea461
4 changed files with 106 additions and 17 deletions
|
@ -11,27 +11,33 @@ module ActiveRecord
|
|||
included do
|
||||
class_attribute :_reflections, instance_writer: false, default: {}
|
||||
class_attribute :aggregate_reflections, instance_writer: false, default: {}
|
||||
class_attribute :attachment_reflections, instance_writer: false, default: {}
|
||||
end
|
||||
|
||||
def self.create(macro, name, scope, options, ar)
|
||||
klass = \
|
||||
case macro
|
||||
when :composed_of
|
||||
AggregateReflection
|
||||
when :has_many
|
||||
HasManyReflection
|
||||
when :has_one
|
||||
HasOneReflection
|
||||
when :belongs_to
|
||||
BelongsToReflection
|
||||
else
|
||||
raise "Unsupported Macro: #{macro}"
|
||||
end
|
||||
|
||||
reflection = klass.new(name, scope, options, ar)
|
||||
reflection = reflection_class_for(macro).new(name, scope, options, ar)
|
||||
options[:through] ? ThroughReflection.new(reflection) : reflection
|
||||
end
|
||||
|
||||
def self.reflection_class_for(macro)
|
||||
case macro
|
||||
when :composed_of
|
||||
AggregateReflection
|
||||
when :has_many
|
||||
HasManyReflection
|
||||
when :has_one
|
||||
HasOneReflection
|
||||
when :belongs_to
|
||||
BelongsToReflection
|
||||
when :has_one_attached
|
||||
HasOneAttachedReflection
|
||||
when :has_many_attached
|
||||
HasManyAttachedReflection
|
||||
else
|
||||
raise "Unsupported Macro: #{macro}"
|
||||
end
|
||||
end
|
||||
|
||||
def self.add_reflection(ar, name, reflection)
|
||||
ar.clear_reflections_cache
|
||||
name = name.to_s
|
||||
|
@ -42,14 +48,18 @@ module ActiveRecord
|
|||
ar.aggregate_reflections = ar.aggregate_reflections.merge(name.to_s => reflection)
|
||||
end
|
||||
|
||||
def self.add_attachment_reflection(ar, name, reflection)
|
||||
ar.attachment_reflections.merge!(name.to_s => reflection)
|
||||
end
|
||||
|
||||
# \Reflection enables the ability to examine the associations and aggregations of
|
||||
# Active Record classes and objects. This information, for example,
|
||||
# can be used in a form builder that takes an Active Record object
|
||||
# and creates input fields for all of the attributes depending on their type
|
||||
# and displays the associations to other objects.
|
||||
#
|
||||
# MacroReflection class has info for AggregateReflection and AssociationReflection
|
||||
# classes.
|
||||
# MacroReflection class has info for the AggregateReflection and
|
||||
# AssociationReflection classes.
|
||||
module ClassMethods
|
||||
# Returns an array of AggregateReflection objects for all the aggregations in the class.
|
||||
def reflect_on_all_aggregations
|
||||
|
@ -64,6 +74,21 @@ module ActiveRecord
|
|||
aggregate_reflections[aggregation.to_s]
|
||||
end
|
||||
|
||||
# Returns an array of reflection objects for all the attachments in the
|
||||
# class.
|
||||
def reflect_on_all_attachments
|
||||
attachment_reflections.values
|
||||
end
|
||||
|
||||
# Returns the reflection object for the named +attachment+.
|
||||
#
|
||||
# User.reflect_on_attachment(:avatar)
|
||||
# # => the avatar reflection
|
||||
#
|
||||
def reflect_on_attachment(attachment)
|
||||
attachment_reflections[attachment.to_s]
|
||||
end
|
||||
|
||||
# Returns a Hash of name of the reflection as the key and an AssociationReflection as the value.
|
||||
#
|
||||
# Account.reflections # => {"balance" => AggregateReflection}
|
||||
|
@ -136,6 +161,8 @@ module ActiveRecord
|
|||
# HasOneReflection
|
||||
# BelongsToReflection
|
||||
# HasAndBelongsToManyReflection
|
||||
# HasOneAttachedReflection
|
||||
# HasManyAttachedReflection
|
||||
# ThroughReflection
|
||||
# PolymorphicReflection
|
||||
# RuntimeReflection
|
||||
|
@ -412,6 +439,22 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
# Holds all the metadata about a has_one_attached attachment as it was
|
||||
# specified in the Active Record class.
|
||||
class HasOneAttachedReflection < MacroReflection #:nodoc:
|
||||
def macro
|
||||
:has_one_attached
|
||||
end
|
||||
end
|
||||
|
||||
# Holds all the metadata about a has_many_attached attachment as it was
|
||||
# specified in the Active Record class.
|
||||
class HasManyAttachedReflection < MacroReflection #:nodoc:
|
||||
def macro
|
||||
:has_many_attached
|
||||
end
|
||||
end
|
||||
|
||||
# Holds all the metadata about an association as it was specified in the
|
||||
# Active Record class.
|
||||
class AssociationReflection < MacroReflection #:nodoc:
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
* Add the ability to reflect on defined attachments using the existing
|
||||
ActiveRecord reflection mechanism.
|
||||
|
||||
*Kevin Deisz*
|
||||
|
||||
* Variant arguments of `false` or `nil` will no longer be passed to the
|
||||
processor. For example, the following will not have the monochrome
|
||||
variation applied:
|
||||
|
|
|
@ -48,6 +48,12 @@ module ActiveStorage
|
|||
else
|
||||
before_destroy { public_send(name).detach }
|
||||
end
|
||||
|
||||
ActiveRecord::Reflection.add_attachment_reflection(
|
||||
self,
|
||||
name,
|
||||
ActiveRecord::Reflection.create(:has_one_attached, name, nil, { dependent: dependent }, self)
|
||||
)
|
||||
end
|
||||
|
||||
# Specifies the relation between multiple attachments and the model.
|
||||
|
@ -105,6 +111,12 @@ module ActiveStorage
|
|||
else
|
||||
before_destroy { public_send(name).detach }
|
||||
end
|
||||
|
||||
ActiveRecord::Reflection.add_attachment_reflection(
|
||||
self,
|
||||
name,
|
||||
ActiveRecord::Reflection.create(:has_many_attached, name, nil, { dependent: dependent }, self)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
29
activestorage/test/models/reflection_test.rb
Normal file
29
activestorage/test/models/reflection_test.rb
Normal file
|
@ -0,0 +1,29 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "test_helper"
|
||||
|
||||
class ActiveStorage::ReflectionTest < ActiveSupport::TestCase
|
||||
test "allows reflecting for all attachment" do
|
||||
expected_classes =
|
||||
User.reflect_on_all_attachments.all? do |reflection|
|
||||
reflection.is_a?(ActiveRecord::Reflection::HasOneAttachedReflection) ||
|
||||
reflection.is_a?(ActiveRecord::Reflection::HasManyAttachedReflection)
|
||||
end
|
||||
|
||||
assert expected_classes
|
||||
end
|
||||
|
||||
test "allows reflecting on a singular has_one_attached attachment" do
|
||||
reflection = User.reflect_on_attachment(:avatar)
|
||||
|
||||
assert_equal :avatar, reflection.name
|
||||
assert_equal :has_one_attached, reflection.macro
|
||||
end
|
||||
|
||||
test "allows reflecting on a singular has_many_attached attachment" do
|
||||
reflection = User.reflect_on_attachment(:highlights)
|
||||
|
||||
assert_equal :highlights, reflection.name
|
||||
assert_equal :has_many_attached, reflection.macro
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue