module Raspy
Constants
- VERSION
Public Class Methods
preload_belongs_to(list:, name:, association_klass:, foreign_key:, inner_associations: nil, association_condition: nil, additional_selects: [], additional_joins: [])
click to toggle source
# File lib/raspy.rb, line 177 def self.preload_belongs_to(list:, name:, association_klass:, foreign_key:, inner_associations: nil, association_condition: nil, additional_selects: [], additional_joins: []) return if list.nil? || list.length == 0 klass = list.first.class klass.send :attr_reader, name.to_sym return if list.map{ |e| e[foreign_key.to_sym] }.compact.length == 0 association_table = association_klass.as_rusql_table selects = [association_table[:*]] selects += additional_selects condition = association_table[association_klass.primary_key.to_sym].in( list.map{ |e| e[foreign_key.to_sym] }.compact ) unless association_condition.nil? condition = condition.and( association_condition ) end query = select( *selects ). from( association_table ). where( condition ) additional_joins.each do |j| query = query.join(j) end unless additional_selects.length == 0 && additional_joins.length == 0 query = query.group_by( association_table[association_klass.primary_key.to_sym] ) end associated_objects = association_klass.find_by_sql(query.to_s).to_a if inner_associations.present? associated_objects.prefetch(inner_associations) end associated_objects_hash = associated_objects.map{ |e| [e[association_klass.primary_key.to_sym], e] }.to_h list.each do |ele| if associated_objects_hash[ele[foreign_key.to_sym]].present? ele.instance_variable_set(:"@#{name}", associated_objects_hash[ele[foreign_key.to_sym]]) end end end
preload_habtm(list:, name:, association_klass:, foreign_key:, association_foreign_key:, inner_associations:, join_table:, association_condition:)
click to toggle source
# File lib/raspy.rb, line 21 def self.preload_habtm(list:, name:, association_klass:, foreign_key:, association_foreign_key:, inner_associations:, join_table:, association_condition:) return if list.nil? || list.length == 0 klass = list.first.class klass.send :attr_reader, name.to_sym join_t = table(join_table.to_sym) join_query = select( join_t[foreign_key.to_sym], join_t[association_foreign_key.to_sym] ). from( join_t ). where( join_t[foreign_key.to_sym].in( list.map{ |e| e[klass.primary_key.to_sym] }.compact ) ) join_objects = ActiveRecord::Base.connection.execute(join_query.to_s).to_a association_table = association_klass.as_rusql_table condition = join_t[foreign_key.to_sym].in( list.map{ |e| e[klass.primary_key.to_sym] }.compact ) if association_condition.present? condition = condition.and( association_condition ) end query = select( association_table[:*] ). from( association_table ). inner_join( join_t, join_t[association_foreign_key.to_sym].equals(association_table[association_klass.primary_key.to_sym]) ). where( condition ) associated_objects = association_klass.find_by_sql(query.to_s).to_a if inner_associations.present? associated_objects.prefetch(inner_associations) end associated_objects_hash = {} associated_objects_hash = associated_objects.map{ |e| [e[association_klass.primary_key.to_sym], e] }.to_h list.each do |ele| set = [] join_objects.select{ |e| e[0] == ele[klass.primary_key.to_sym] }.map(&:last).each do |association_pk| if associated_objects_hash[association_pk].present? set << associated_objects_hash[association_pk] end end ele.instance_variable_set(:"@#{name}", set) end end
preload_has_many(list:, name:, association_klass:, foreign_key:, inner_associations: nil, association_condition: nil, reverse_association: nil)
click to toggle source
# File lib/raspy.rb, line 79 def self.preload_has_many(list:, name:, association_klass:, foreign_key:, inner_associations: nil, association_condition: nil, reverse_association: nil) return if list.nil? || list.length == 0 klass = list.first.class klass.send :attr_reader, name.to_sym if reverse_association.present? association_klass.send :attr_reader, reverse_association.to_sym end association_table = association_klass.as_rusql_table condition = association_table[foreign_key.to_sym].in( list.map{ |e| e[klass.primary_key.to_sym] }.compact ) if association_condition.present? condition = condition.and( association_condition ) end query = select( association_table[:*] ). from( association_table ). where( condition ) associated_objects = association_klass.find_by_sql(query.to_s).to_a if inner_associations.present? associated_objects.prefetch(inner_associations) end associated_objects_hash = {} associated_objects.each do |ao| associated_objects_hash[ao[foreign_key.to_sym]] ||= [] associated_objects_hash[ao[foreign_key.to_sym]] << ao end list.each do |ele| set = [] if associated_objects_hash[ele[klass.primary_key.to_sym]].present? set = associated_objects_hash[ele[klass.primary_key.to_sym]] end if reverse_association.present? set.each do |ao| ao.instance_variable_set(:"@#{reverse_association}", ele) end end ele.instance_variable_set(:"@#{name}", set) end end
preload_has_one(list:, name:, association_klass:, foreign_key:, order_type:, order_field:, inner_associations: nil, association_condition: nil, reverse_association: nil)
click to toggle source
# File lib/raspy.rb, line 132 def self.preload_has_one(list:, name:, association_klass:, foreign_key:, order_type:, order_field:, inner_associations: nil, association_condition: nil, reverse_association: nil) return if list.nil? || list.length == 0 klass = list.first.class klass.send :attr_reader, name.to_sym if reverse_association.present? association_klass.send :attr_reader, reverse_association.to_sym end query = <<-EOS.squish SELECT #{ association_klass.table_name }.* FROM #{ association_klass.table_name } INNER JOIN ( SELECT #{ association_klass.table_name }.#{ foreign_key }, #{ order_type }(#{ association_klass.table_name }.#{ order_field }) max_#{ order_field } FROM #{ association_klass.table_name } WHERE #{ association_klass.table_name }.#{ foreign_key } IN (#{ list.map{ |e| e[klass.primary_key.to_sym] }.compact.map(&:to_s).join(", ") }) #{ association_condition.present? ? " AND #{ association_condition }" : "" } GROUP BY #{ association_klass.table_name }.#{ foreign_key } ) _association ON _association.#{ foreign_key } = #{ association_klass.table_name }.#{ foreign_key } AND _association.max_#{ order_field } = #{ association_klass.table_name }.#{ order_field } WHERE #{ association_klass.table_name }.#{ foreign_key } IN (#{ list.map{ |e| e[klass.primary_key.to_sym] }.compact.map(&:to_s).join(", ") }) #{ association_condition.present? ? " AND #{ association_condition }" : "" } EOS associated_objects = association_klass.find_by_sql(query).to_a if inner_associations.present? associated_objects.prefetch(inner_associations) end associated_objects_hash = associated_objects.map{ |e| [e[foreign_key.to_sym], e] }.to_h list.each do |ele| if associated_objects_hash[ele[klass.primary_key.to_sym]].present? associated_object = associated_objects_hash[ele[klass.primary_key.to_sym]] if reverse_association.present? associated_object.instance_variable_set(:"@#{reverse_association}", ele) end ele.instance_variable_set(:"@#{name}", associated_object) end end end
preload_polymorphic_belongs_to(list:, name:, polymorphic_key_field:, polymorphic_type_field:, polymorphic_type_map:)
click to toggle source
# File lib/raspy.rb, line 222 def self.preload_polymorphic_belongs_to(list:, name:, polymorphic_key_field:, polymorphic_type_field:, polymorphic_type_map:) return if list.nil? || list.length == 0 return if polymorphic_key_field.nil? || polymorphic_type_field.nil? || polymorphic_type_map.nil? || (polymorphic_type_map.keys.length == 0) klass = list.first.class klass.send :attr_reader, name.to_sym polymorphic_type_map.keys.each do |polymorphic_type| matching_list = list.select{ |e| e[polymorphic_type_field.to_sym] == polymorphic_type } association_klass = polymorphic_type_map[polymorphic_type] Raspy.preload_belongs_to( list: matching_list, name: name, association_klass: association_klass, foreign_key: polymorphic_key_field ) end end