Module: User::Querying

Included in:
User
Defined in:
app/models/user/querying.rb

Overview

TODO: THIS FILE SHOULD NOT EXIST, EVIL SQL SHOULD BE ENCAPSULATED IN EvilQueries, throwing all of this stuff in user violates demeter like WHOA

Instance Method Summary collapse

Instance Method Details

#aspects_with_person(person) ⇒ Object


137
138
139
# File 'app/models/user/querying.rb', line 137

def aspects_with_person person
  contact_for(person).aspects
end

#aspects_with_shareable(base_class_name_or_class, shareable_id) ⇒ Object


107
108
109
110
111
# File 'app/models/user/querying.rb', line 107

def aspects_with_shareable(base_class_name_or_class, shareable_id)
  base_class_name = base_class_name_or_class
  base_class_name = base_class_name_or_class.base_class.to_s if base_class_name_or_class.is_a?(Class)
  self.aspects.joins(:aspect_visibilities).where(:aspect_visibilities => {:shareable_id => shareable_id, :shareable_type => base_class_name})
end

#construct_public_followings_sql(opts) ⇒ Object


70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'app/models/user/querying.rb', line 70

def construct_public_followings_sql(opts)
  Rails.logger.debug("[EVIL-QUERY] user.construct_public_followings_sql")
  
  # For PostgreSQL and MySQL/MariaDB we use a different query
  # see issue: https://github.com/diaspora/diaspora/issues/5014
  if AppConfig.postgres?
    query = opts[:klass].where(:author_id => Person.in_aspects(opts[:by_members_of]).select("people.id"), :public => true, :pending => false)
  else
    aspects = Aspect.where(:id => opts[:by_members_of])
    person_ids = Person.connection.select_values(people_in_aspects(aspects).select("people.id").to_sql)
    query = opts[:klass].where(:author_id => person_ids, :public => true, :pending => false)
  end

  unless(opts[:klass] == Photo)
    query = query.where(:type => opts[:type])
  end

  ugly_select_clause(query, opts)
end

#construct_shareable_from_others_query(opts) ⇒ Object


51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'app/models/user/querying.rb', line 51

def construct_shareable_from_others_query(opts)
  conditions = {
      :pending => false,
      :share_visibilities => {:hidden => opts[:hidden]},
      :contacts => {:user_id => self.id, :receiving => true}
  }

  conditions[:type] = opts[:type] if opts.has_key?(:type)

  query = opts[:klass].joins(:contacts).where(conditions)

  if opts[:by_members_of]
    query = query.joins(:contacts => :aspect_memberships).where(
      :aspect_memberships => {:aspect_id => opts[:by_members_of]})
  end

  ugly_select_clause(query, opts)
end

#construct_shareable_from_self_query(opts) ⇒ Object


90
91
92
93
94
95
96
97
98
99
100
# File 'app/models/user/querying.rb', line 90

def construct_shareable_from_self_query(opts)
  conditions = {:pending => false }
  conditions[:type] = opts[:type] if opts.has_key?(:type)
  query = self.person.send(opts[:klass].to_s.tableize).where(conditions)

  if opts[:by_members_of]
    query = query.joins(:aspect_visibilities).where(:aspect_visibilities => {:aspect_id => opts[:by_members_of]})
  end

  ugly_select_clause(query, opts)
end

#contact_for(person) ⇒ Object


102
103
104
105
# File 'app/models/user/querying.rb', line 102

def contact_for(person)
  return nil unless person
  contact_for_person_id(person.id)
end

#contact_for_person_id(person_id) ⇒ Object


113
114
115
# File 'app/models/user/querying.rb', line 113

def contact_for_person_id(person_id)
  Contact.where(:user_id => self.id, :person_id => person_id).includes(:person => :profile).first
end

#find_visible_shareable_by_id(klass, id, opts = {}) ⇒ Object


8
9
10
11
# File 'app/models/user/querying.rb', line 8

def find_visible_shareable_by_id(klass, id, opts={} )
  key = (opts.delete(:key) || :id)
  ::EvilQuery::VisibleShareableById.new(self, klass, key, id, opts).post!
end

#has_contact_for?(person) ⇒ Boolean


119
120
121
# File 'app/models/user/querying.rb', line 119

def has_contact_for?(person)
  Contact.exists?(:user_id => self.id, :person_id => person.id)
end

#people_in_aspects(requested_aspects, opts = {}) ⇒ Object


123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'app/models/user/querying.rb', line 123

def people_in_aspects(requested_aspects, opts={})
  allowed_aspects = self.aspects & requested_aspects
  aspect_ids = allowed_aspects.map(&:id)

  people = Person.in_aspects(aspect_ids)

  if opts[:type] == 'remote'
    people = people.where(:owner_id => nil)
  elsif opts[:type] == 'local'
    people = people.where('people.owner_id IS NOT NULL')
  end
  people
end

#photos_from(person, opts = {}) ⇒ Object


145
146
147
148
149
150
# File 'app/models/user/querying.rb', line 145

def photos_from(person, opts={})
  opts = prep_opts(Photo, opts)
  ::EvilQuery::ShareablesFromPerson.new(self, Photo, person).make_relation!
    .by_max_time(opts[:max_time])
    .limit(opts[:limit])
end

#posts_from(person) ⇒ Object


141
142
143
# File 'app/models/user/querying.rb', line 141

def posts_from(person)
  ::EvilQuery::ShareablesFromPerson.new(self, Post, person).make_relation!
end

#ugly_select_clause(query, opts) ⇒ Object


45
46
47
48
49
# File 'app/models/user/querying.rb', line 45

def ugly_select_clause(query, opts)
  klass = opts[:klass]
  select_clause ='DISTINCT %s.id, %s.updated_at AS updated_at, %s.created_at AS created_at' % [klass.table_name, klass.table_name, klass.table_name]
  query.select(select_clause).order(opts[:order_with_table]).where(klass.arel_table[opts[:order_field]].lt(opts[:max_time]))
end

#visible_ids_from_sql(klass, opts = {}) ⇒ Array<Integer>


25
26
27
28
29
30
31
32
# File 'app/models/user/querying.rb', line 25

def visible_ids_from_sql(klass, opts={})
  opts = prep_opts(klass, opts)
  opts[:klass] = klass
  opts[:by_members_of] ||= self.aspect_ids

  post_ids = klass.connection.select_values(visible_shareable_sql(klass, opts)).map { |id| id.to_i }
  post_ids += klass.connection.select_values("#{construct_public_followings_sql(opts).to_sql} LIMIT #{opts[:limit]}").map {|id| id.to_i }
end

#visible_shareable_ids(klass, opts = {}) ⇒ Object


19
20
21
22
# File 'app/models/user/querying.rb', line 19

def visible_shareable_ids(klass, opts={})
  opts = prep_opts(klass, opts)
  visible_ids_from_sql(klass, opts)
end

#visible_shareable_sql(klass, opts = {}) ⇒ Object


34
35
36
37
38
39
40
41
42
43
# File 'app/models/user/querying.rb', line 34

def visible_shareable_sql(klass, opts={})
  table = klass.table_name
  opts = prep_opts(klass, opts)
  opts[:klass] = klass

  shareable_from_others = construct_shareable_from_others_query(opts)
  shareable_from_self = construct_shareable_from_self_query(opts)

  "(#{shareable_from_others.to_sql} LIMIT #{opts[:limit]}) UNION ALL (#{shareable_from_self.to_sql} LIMIT #{opts[:limit]}) ORDER BY #{opts[:order]} LIMIT #{opts[:limit]}"
end

#visible_shareables(klass, opts = {}) ⇒ Object


13
14
15
16
17
# File 'app/models/user/querying.rb', line 13

def visible_shareables(klass, opts={})
  opts = prep_opts(klass, opts)
  shareable_ids = visible_shareable_ids(klass, opts)
  klass.where(:id => shareable_ids).select('DISTINCT '+klass.to_s.tableize+'.*').limit(opts[:limit]).order(opts[:order_with_table]).order(klass.table_name+".id DESC")
end