5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
# File 'lib/similar_models.rb', line 5
def has_similar_models(*many_to_many_associations, as: nil)
as = "similar_#{model_name.plural}" unless as
define_method as do
table_name = self.class.table_name
primary_key = self.class.primary_key
primary_key_ref = "#{table_name}.#{primary_key}"
association_scopes = []
many_to_many_associations.each do |many_to_many_association|
assocation = self.class.reflect_on_association(many_to_many_association)
join_table, foreign_key, association_foreign_key = self.class.join_table_values(assocation)
association_scopes << self.class.where(
"#{join_table}.#{association_foreign_key} IN \
(select #{join_table}.#{association_foreign_key} from #{join_table} \
where #{join_table}.#{foreign_key} = :foreign_key)", foreign_key: self.id
).joins("INNER JOIN #{join_table} ON #{join_table}.#{foreign_key} = #{primary_key_ref}")
end
scope = self.class.select("#{table_name}.*, count(#{primary_key_ref}) AS #{as}_model_count").
where.not(primary_key => self.id).order("#{as}_model_count DESC")
group_by_clause = primary_key
if association_scopes.one?
scope.merge(association_scopes.first).group(group_by_clause)
else
group_by_clause = self.class.column_names.join(', ')
scope.from("((#{association_scopes.map(&:to_sql).join(') UNION ALL (')})) AS #{table_name}").group(group_by_clause)
end
end
def self.join_table_values(many_to_many_assocation)
if many_to_many_assocation.macro == :has_and_belongs_to_many
join_table = many_to_many_assocation.join_table
foreign_key = many_to_many_assocation.foreign_key
association_foreign_key = many_to_many_assocation.association_foreign_key
elsif many_to_many_assocation.macro == :has_many
join_table = many_to_many_assocation.through_reflection.table_name
foreign_key = many_to_many_assocation.through_reflection.foreign_key
association_foreign_key = many_to_many_assocation.foreign_key
end
[join_table, foreign_key, association_foreign_key]
end
end
|