diff --git a/app/components/avo/fields/has_one_field/show_component.rb b/app/components/avo/fields/has_one_field/show_component.rb index dd482c2180..801a748e08 100644 --- a/app/components/avo/fields/has_one_field/show_component.rb +++ b/app/components/avo/fields/has_one_field/show_component.rb @@ -42,7 +42,7 @@ def can_see_the_create_button? end def create_path - association_id = @field.resource.model_class._reflections.with_indifferent_access[@field.association_name].inverse_of.name + association_id = @field.resource.model_class.reflect_on_association(@field.association_name).inverse_of.name args = { via_relation: association_id, diff --git a/app/components/avo/index/resource_controls_component.rb b/app/components/avo/index/resource_controls_component.rb index 8bf38f0eb8..e2ce1f4c59 100644 --- a/app/components/avo/index/resource_controls_component.rb +++ b/app/components/avo/index/resource_controls_component.rb @@ -65,7 +65,11 @@ def parent_resource end def is_has_many_association? - @reflection.is_a?(::ActiveRecord::Reflection::HasManyReflection) || @reflection.is_a?(::ActiveRecord::Reflection::ThroughReflection) + @reflection.class.in? [ + ActiveRecord::Reflection::HasManyReflection, + ActiveRecord::Reflection::HasAndBelongsToManyReflection, + ActiveRecord::Reflection::ThroughReflection + ] end def referrer_path diff --git a/app/components/avo/views/resource_index_component.rb b/app/components/avo/views/resource_index_component.rb index aa8ad60e8b..27281c47bc 100644 --- a/app/components/avo/views/resource_index_component.rb +++ b/app/components/avo/views/resource_index_component.rb @@ -66,10 +66,20 @@ def can_see_the_create_button? end def can_attach? - klass = @reflection - klass = @reflection.through_reflection if klass.is_a? ::ActiveRecord::Reflection::ThroughReflection + return false if has_reflection_and_is_read_only - @reflection.present? && klass.is_a?(::ActiveRecord::Reflection::HasManyReflection) && !has_reflection_and_is_read_only && authorize_association_for(:attach) + reflection_class = if @reflection.is_a?(::ActiveRecord::Reflection::ThroughReflection) + @reflection.through_reflection.class + else + @reflection.class + end + + return false unless reflection_class.in? [ + ActiveRecord::Reflection::HasManyReflection, + ActiveRecord::Reflection::HasAndBelongsToManyReflection + ] + + authorize_association_for(:attach) end def create_path @@ -82,7 +92,10 @@ def create_path via_record_id: @parent_record.to_param } - if @reflection.is_a? ActiveRecord::Reflection::ThroughReflection + if @reflection.class.in? [ + ActiveRecord::Reflection::ThroughReflection, + ActiveRecord::Reflection::HasAndBelongsToManyReflection + ] args[:via_relation] = params[:resource_name] end diff --git a/app/controllers/avo/application_controller.rb b/app/controllers/avo/application_controller.rb index ff330462a6..27d0e5f853 100644 --- a/app/controllers/avo/application_controller.rb +++ b/app/controllers/avo/application_controller.rb @@ -89,7 +89,7 @@ def related_resource return field.use_resource if field&.use_resource.present? - reflection = @record._reflections.with_indifferent_access[field&.for_attribute || params[:related_name]] + reflection = @record.class.reflect_on_association(field&.for_attribute || params[:related_name]) reflected_model = reflection.klass diff --git a/app/controllers/avo/associations_controller.rb b/app/controllers/avo/associations_controller.rb index 3ab2b421f9..0c3f845450 100644 --- a/app/controllers/avo/associations_controller.rb +++ b/app/controllers/avo/associations_controller.rb @@ -78,7 +78,7 @@ def create_association association_name = BaseResource.valid_association_name(@record, association_from_params) perform_action_and_record_errors do - if reflection_class == "HasManyReflection" + if has_many_reflection? @record.send(association_name) << @attachment_record else @record.send(:"#{association_name}=", @attachment_record) @@ -92,7 +92,7 @@ def destroy if reflection.instance_of? ActiveRecord::Reflection::ThroughReflection join_record.destroy! - elsif reflection_class == "HasManyReflection" + elsif has_many_reflection? @record.send(association_name).delete @attachment_record else @record.send(:"#{association_name}=", nil) @@ -106,7 +106,7 @@ def destroy private def set_reflection - @reflection = @record._reflections.with_indifferent_access[association_from_params] + @reflection = @record.class.reflect_on_association(association_from_params) end def set_attachment_class @@ -132,12 +132,11 @@ def attachment_id end def reflection_class - reflection = @record._reflections.with_indifferent_access[association_from_params] - - klass = reflection.class.name.demodulize.to_s - klass = reflection.through_reflection.class.name.demodulize.to_s if klass == "ThroughReflection" - - klass + if @reflection.is_a?(ActiveRecord::Reflection::ThroughReflection) + @reflection.through_reflection.class + else + @reflection.class + end end def authorize_if_defined(method, record = @record) @@ -188,5 +187,12 @@ def join_record reflection.through_reflection.klass.find_by(source_foreign_key => @attachment_record.id, through_foreign_key => @record.id) end + + def has_many_reflection? + reflection_class.in? [ + ActiveRecord::Reflection::HasManyReflection, + ActiveRecord::Reflection::HasAndBelongsToManyReflection + ] + end end end diff --git a/app/controllers/avo/base_controller.rb b/app/controllers/avo/base_controller.rb index 2fdbb3ab6b..45d116f484 100644 --- a/app/controllers/avo/base_controller.rb +++ b/app/controllers/avo/base_controller.rb @@ -121,7 +121,7 @@ def new def create # This means that the record has been created through another parent record and we need to attach it somehow. if params[:via_record_id].present? && params[:via_belongs_to_resource_class].nil? - @reflection = @record._reflections.with_indifferent_access[params[:via_relation]] + @reflection = @record.class.reflect_on_association(params[:via_relation]) # Figure out what kind of association does the record have with the parent record # Fills in the required info for belongs_to and has_many @@ -134,7 +134,7 @@ def create end # For when working with has_one, has_one_through, has_many_through, has_and_belongs_to_many, polymorphic - if @reflection.is_a? ActiveRecord::Reflection::ThroughReflection + if @reflection.is_a?(ActiveRecord::Reflection::ThroughReflection) || @reflection.is_a?(ActiveRecord::Reflection::HasAndBelongsToManyReflection) # find the record via_resource = Avo.resource_manager.get_resource_by_model_class(params[:via_relation_class]) @related_record = via_resource.find_record params[:via_record_id], params: params diff --git a/lib/avo/fields/belongs_to_field.rb b/lib/avo/fields/belongs_to_field.rb index 22f88abd67..c4b3a48b13 100644 --- a/lib/avo/fields/belongs_to_field.rb +++ b/lib/avo/fields/belongs_to_field.rb @@ -243,7 +243,7 @@ def target_resource else reflection_key = polymorphic_as || id - reflection_object = @record._reflections.with_indifferent_access[reflection_key] + reflection_object = @record.class.reflect_on_association(reflection_key) if reflection_object.klass.present? get_resource_by_model_class(reflection_object.klass.to_s) diff --git a/lib/avo/fields/has_base_field.rb b/lib/avo/fields/has_base_field.rb index 7d2a3fe82b..09e7795b96 100644 --- a/lib/avo/fields/has_base_field.rb +++ b/lib/avo/fields/has_base_field.rb @@ -59,7 +59,7 @@ def field_label end def target_resource - reflection = @record._reflections.with_indifferent_access[association_name] + reflection = @record.class.reflect_on_association(association_name) if reflection.klass.present? get_resource_by_model_class(reflection.klass.to_s) diff --git a/lib/avo/resources/base.rb b/lib/avo/resources/base.rb index a16c7524bc..e30eb8ba4b 100644 --- a/lib/avo/resources/base.rb +++ b/lib/avo/resources/base.rb @@ -119,7 +119,7 @@ def authorization end def valid_association_name(record, association_name) - association_name if record._reflections.with_indifferent_access[association_name].present? + association_name if record.class.reflect_on_association(association_name).present? end def valid_attachment_name(record, association_name) @@ -509,7 +509,7 @@ def hydrate_model_with_default_values if field.type == "belongs_to" - reflection = @record._reflections.with_indifferent_access[@params[:via_relation]] + reflection = @record.class.reflect_on_association(@params[:via_relation]) if @params[:via_relation].present? if field.polymorphic_as.present? && field.types.map(&:to_s).include?(@params[:via_relation_class]) # set the value to the actual record