diff --git a/app/serializers/forest_liana/serializer_factory.rb b/app/serializers/forest_liana/serializer_factory.rb index 01bbc400..d795da96 100644 --- a/app/serializers/forest_liana/serializer_factory.rb +++ b/app/serializers/forest_liana/serializer_factory.rb @@ -118,12 +118,6 @@ def relationship_related_link(attribute_name) if ret[:href].blank? begin - if @options[:include].try(:include?, attribute_name.to_s) && - !SchemaHelper.is_smart_field?(object.class, attribute_name.to_s) - - object.send(attribute_name) - end - SchemaUtils.many_associations(object.class).each do |a| if a.name == attribute_name ret[:href] = "/forest/#{ForestLiana.name_for(object.class)}/#{object.id}/relationships/#{attribute_name}" @@ -137,6 +131,30 @@ def relationship_related_link(attribute_name) ret end + def has_one_relationships + return {} if self.class.to_one_associations.nil? + data = {} + self.class.to_one_associations.each do |attribute_name, attr_data| + relation = object.class.reflect_on_all_associations.find { |a| a.name == attribute_name } + + next if !should_include_attr?(attribute_name, attr_data) + + unless relation.polymorphic? + relation_class_name = ForestLiana.name_for(relation.klass).demodulize + + if object.send(relation.foreign_key.to_sym) && + @options[:fields][relation_class_name]&.size == 1 && + @options[:fields][relation_class_name]&.include?(relation.klass.primary_key.to_sym) + + attr_data[:attr_or_block] = proc { relation.klass.new(relation.klass.primary_key => object.send(relation.foreign_key.to_sym)) } + end + end + + data[attribute_name] = attr_data + end + data + end + private def intercom_integration? diff --git a/app/services/forest_liana/base_getter.rb b/app/services/forest_liana/base_getter.rb index e86e65cd..b65387cf 100644 --- a/app/services/forest_liana/base_getter.rb +++ b/app/services/forest_liana/base_getter.rb @@ -19,11 +19,12 @@ def includes_for_serialization def compute_includes @includes = ForestLiana::QueryHelper.get_one_association_names_symbol(@resource) + @optional_includes = [] end def optimize_record_loading(resource, records, force_preload = true) polymorphic, preload_loads = analyze_associations(resource) - result = records.eager_load(@includes.uniq - preload_loads - polymorphic) + result = records.eager_load(@includes.uniq - preload_loads - polymorphic - @optional_includes) result = result.preload(preload_loads) if Rails::VERSION::MAJOR >= 7 && force_preload diff --git a/app/services/forest_liana/has_many_getter.rb b/app/services/forest_liana/has_many_getter.rb index 0c5e0e19..89a35c7e 100644 --- a/app/services/forest_liana/has_many_getter.rb +++ b/app/services/forest_liana/has_many_getter.rb @@ -37,6 +37,8 @@ def records private def compute_includes + @optional_includes = [] + @includes = @association.klass .reflect_on_all_associations .select do |association| diff --git a/app/services/forest_liana/resources_getter.rb b/app/services/forest_liana/resources_getter.rb index 763a2f2b..8ad42547 100644 --- a/app/services/forest_liana/resources_getter.rb +++ b/app/services/forest_liana/resources_getter.rb @@ -31,7 +31,7 @@ def self.get_ids_from_request(params, user) def perform polymorphic_association, preload_loads = analyze_associations(@resource) - includes = @includes.uniq - polymorphic_association - preload_loads + includes = @includes.uniq - polymorphic_association - preload_loads - @optional_includes has_smart_fields = @params[:fields][@collection_name].split(',').any? do |field| ForestLiana::SchemaHelper.is_smart_field?(@resource, field) end @@ -132,26 +132,38 @@ def columns_for_cross_database_association(association_name) def compute_includes associations_has_one = ForestLiana::QueryHelper.get_one_associations(@resource) + @optional_includes = [] + if @field_names_requested + includes = associations_has_one.map do |association| + association_name = association.name.to_s - includes = associations_has_one.map(&:name) - includes_for_smart_search = [] + if @params[:fields].key?(association_name) && + @params[:fields][association_name].split(',').size == 1 && + @params[:fields][association_name].split(',').include?(association.klass.primary_key) - if @collection && @collection.search_fields - includes_for_smart_search = @collection.search_fields - .select { |field| field.include? '.' } - .map { |field| field.split('.').first.to_sym } + @field_names_requested << association.foreign_key + @optional_includes << association.name + end - includes_has_many = SchemaUtils.many_associations(@resource) - .select { |association| SchemaUtils.model_included?(association.klass) } - .map(&:name) + association.name + end - includes_for_smart_search = includes_for_smart_search & includes_has_many - end + includes_for_smart_search = [] + if @collection && @collection.search_fields + includes_for_smart_search = @collection.search_fields + .select { |field| field.include? '.' } + .map { |field| field.split('.').first.to_sym } + + includes_has_many = SchemaUtils.many_associations(@resource) + .select { |association| SchemaUtils.model_included?(association.klass) } + .map(&:name) + + includes_for_smart_search = includes_for_smart_search & includes_has_many + end - if @field_names_requested @includes = (includes & @field_names_requested).concat(includes_for_smart_search) else - @includes = includes + @includes = associations_has_one.map(&:name) end end @@ -298,7 +310,7 @@ def pagination? def compute_select_fields select = ['_forest_admin_eager_load'] - @params[:fields][@collection_name].split(',').each do |path| + @field_names_requested.each do |path| association = get_one_association(path) if association while association.options[:through]