module PostgresExt::Serializers::ActiveModel::ArraySerializer
Public Class Methods
new(*)
click to toggle source
Calls superclass method
# File lib/postgres_ext/serializers/active_model/array_serializer.rb, line 17 def initialize(*) super @_ctes = [] @_results_tables = [] @_embedded = [] end
prepended(base)
click to toggle source
# File lib/postgres_ext/serializers/active_model/array_serializer.rb, line 3 def self.prepended(base) base.send :include, IncludeMethods end
Private Instance Methods
_arel_to_json_array_arel(arel, name)
click to toggle source
# File lib/postgres_ext/serializers/active_model/array_serializer.rb, line 158 def _arel_to_json_array_arel(arel, name) json_table = Arel::Table.new "#{name}_attributes_filter" json_select_manager = json_table.project _results_as_json_array(json_table.name, name) json_select_manager.project Arel::Nodes::As.new Arel.sql('1'), Arel.sql('match') @_ctes << _postgres_cte_as(json_table.name, _visitor.accept(arel)) @_ctes << _postgres_cte_as("#{name}_as_json_array", _visitor.accept(json_select_manager)) @_results_tables << { table: "#{name}_as_json_array", column: name } end
_array_agg(column, aliaz = nil)
click to toggle source
# File lib/postgres_ext/serializers/active_model/array_serializer.rb, line 191 def _array_agg(column, aliaz = nil) _postgres_function_node 'array_agg', [column], aliaz end
_array_agg_as_json(column, aliaz = nil)
click to toggle source
# File lib/postgres_ext/serializers/active_model/array_serializer.rb, line 195 def _array_agg_as_json(column, aliaz = nil) array_agg = _array_agg [column] _postgres_function_node 'array_to_json', [array_agg], aliaz end
_coalesce_arrays(column, aliaz = nil)
click to toggle source
# File lib/postgres_ext/serializers/active_model/array_serializer.rb, line 136 def _coalesce_arrays(column, aliaz = nil) _postgres_function_node 'coalesce', [column, Arel.sql("'{}'::int[]")], aliaz end
_include_relation_in_root(relation, *args)
click to toggle source
# File lib/postgres_ext/serializers/active_model/array_serializer.rb, line 35 def _include_relation_in_root(relation, *args) local_options = args.extract_options! foreign_key_column = args[0] constraining_table = args[1] relation_query = relation.dup relation_query_arel = relation_query.arel_table @_embedded << relation.table_name klass = ActiveRecord::Relation === relation ? relation.klass : relation if local_options[:serializer].present? serializer_class = local_options[:serializer] else serializer_class = _serializer_class(klass) end _serializer = serializer_class.new klass.new, options attributes = serializer_class._attributes attributes.each do |name, key| if name.to_s == key.to_s if serializer_class.respond_to? "#{name}__sql" relation_query = relation_query.select Arel::Nodes::As.new Arel.sql(serializer_class.send("#{name}__sql", options[:scope])), Arel.sql(name.to_s) elsif klass.respond_to? "#{name}__sql" relation_query = relation_query.select Arel::Nodes::As.new Arel.sql(klass.send("#{name}__sql")), Arel.sql(name.to_s) else relation_query = relation_query.select(relation_query_arel[name]) end end end if foreign_key_column && constraining_table relation_query = relation_query.where(relation_query_arel[foreign_key_column].in(constraining_table.project(constraining_table[:id]))) end associations = serializer_class._associations association_sql_tables = [] ids_table_name = nil id_query = nil unless associations.empty? ids_table_name = "#{relation.table_name}_ids" ids_table_arel = Arel::Table.new ids_table_name id_query = relation.dup.select(:id) if foreign_key_column && constraining_table id_query.where!(relation_query_arel[foreign_key_column].in(constraining_table.project(constraining_table[:id]))) end end associations.each do |key, association_class| association = association_class.new key, _serializer, options association_reflection = klass.reflect_on_association(key) if association.embed_ids? if association_reflection.macro == :has_many unless @_ctes.find { |as| as.left == ids_table_name } @_ctes << _postgres_cte_as(ids_table_name, "(#{id_query.to_sql})") end association_sql_tables << _process_has_many_relation(key, association_reflection, relation_query, ids_table_arel) else relation_query = relation_query.select(relation_query_arel["#{key}_id"]) end end if association.embed_in_root? && !@_embedded.member?(key.to_s) _include_relation_in_root(association_reflection.klass, association_reflection.foreign_key, ids_table_arel, serializer: association.target_serializer) end end arel = relation_query.arel.dup association_sql_tables.each do |assoc_hash| assoc_table = Arel::Table.new assoc_hash[:table] arel.join(assoc_table, Arel::Nodes::OuterJoin).on(relation_query_arel[:id].eq(assoc_table[assoc_hash[:foreign_key]])) arel.project _coalesce_arrays(assoc_table[assoc_hash[:ids_column]], assoc_hash[:ids_column]) end _arel_to_json_array_arel(arel, relation_query.table_name) end
_postgres_cte_as(name, sql_string)
click to toggle source
# File lib/postgres_ext/serializers/active_model/array_serializer.rb, line 181 def _postgres_cte_as(name, sql_string) Arel::Nodes::As.new Arel.sql(name), Arel.sql(sql_string) end
_postgres_function_node(name, values, aliaz = nil)
click to toggle source
# File lib/postgres_ext/serializers/active_model/array_serializer.rb, line 200 def _postgres_function_node(name, values, aliaz = nil) Arel::Nodes::NamedFunction.new(name, values, aliaz) end
_postgres_serializable_array()
click to toggle source
# File lib/postgres_ext/serializers/active_model/array_serializer.rb, line 26 def _postgres_serializable_array _include_relation_in_root(object, serializer: @options[:each_serializer]) jsons_select_manager = _results_table_arel jsons_select_manager.with @_ctes object.klass.connection.select_value _visitor.accept(jsons_select_manager) end
_process_has_many_relation(key, association_reflection, relation_query, ids_table_arel)
click to toggle source
# File lib/postgres_ext/serializers/active_model/array_serializer.rb, line 115 def _process_has_many_relation(key, association_reflection, relation_query, ids_table_arel) association_class = association_reflection.klass association_arel_table = association_class.arel_table association_query = association_class.group association_arel_table[association_reflection.foreign_key] association_query = association_query.select(association_arel_table[association_reflection.foreign_key]) id_column_name = "#{key.to_s.singularize}_ids" cte_name = "#{id_column_name}_by_#{relation_query.table_name}" association_query = association_query.select(_array_agg(association_arel_table[:id], id_column_name)) association_query = association_query.having(association_arel_table[association_reflection.foreign_key].in(ids_table_arel.project(ids_table_arel[:id]))) @_ctes << _postgres_cte_as(cte_name, "(#{association_query.to_sql})") { table: cte_name, ids_column: id_column_name, foreign_key: association_reflection.foreign_key } end
_relation_to_json_array_arel(relation)
click to toggle source
# File lib/postgres_ext/serializers/active_model/array_serializer.rb, line 168 def _relation_to_json_array_arel(relation) json_table = Arel::Table.new "#{relation.table_name}_json" json_select_manager = json_table.project _results_as_json_array(json_table.name, relation.table_name) @_ctes << _postgres_cte_as(json_table.name, "(#{relation.to_sql})") json_select_manager end
_results_as_json_array(table_name, aliaz = nil)
click to toggle source
# File lib/postgres_ext/serializers/active_model/array_serializer.rb, line 185 def _results_as_json_array(table_name, aliaz = nil) row_as_json = _row_to_json table_name array_of_json = _postgres_function_node 'array_agg', [row_as_json] _postgres_function_node 'array_to_json', [array_of_json], aliaz end
_results_table_arel()
click to toggle source
# File lib/postgres_ext/serializers/active_model/array_serializer.rb, line 140 def _results_table_arel first = @_results_tables.shift first_table = Arel::Table.new first[:table] jsons_select = first_table.project first_table[first[:column]] @_results_tables.each do |table_info| table = Arel::Table.new table_info[:table] jsons_select = jsons_select.project table[table_info[:column]] jsons_select.join(table).on(first_table[:match].eq(table[:match])) end @_ctes << _postgres_cte_as('jsons', _visitor.accept(jsons_select)) jsons_table = Arel::Table.new 'jsons' jsons_row_to_json = _row_to_json jsons_table.name jsons_table.project jsons_row_to_json end
_row_to_json(table_name, aliaz = nil)
click to toggle source
# File lib/postgres_ext/serializers/active_model/array_serializer.rb, line 177 def _row_to_json(table_name, aliaz = nil) _postgres_function_node 'row_to_json', [Arel.sql(table_name)], aliaz end
_serializer_class(klass)
click to toggle source
# File lib/postgres_ext/serializers/active_model/array_serializer.rb, line 132 def _serializer_class(klass) klass.active_model_serializer end
_visitor()
click to toggle source
# File lib/postgres_ext/serializers/active_model/array_serializer.rb, line 128 def _visitor @_visitior ||= object.klass.connection.visitor end