Class: Decidim::Proposals::ProposalSearch

Inherits:
ResourceSearch
  • Object
show all
Defined in:
app/services/decidim/proposals/proposal_search.rb

Overview

A service to encapsualte all the logic when searching and filtering proposals in a participatory process.

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ ProposalSearch

Public: Initializes the service. component - A Decidim::Component to get the proposals from. page - The page number to paginate the results. per_page - The number of proposals to return per page.



12
13
14
# File 'app/services/decidim/proposals/proposal_search.rb', line 12

def initialize(options = {})
  super(Proposal.all, options)
end

Instance Method Details

#resultsObject

We overwrite the ‘results` method to ensure we only return unique results. We can’t use ‘#uniq` because it returns an Array and we’re adding scopes in the controller, and ‘#distinct` doesn’t work here because in the later scopes we’re ordering by ‘RANDOM()` in a DB level, and `SELECT DISTINCT` doesn’t work with ‘RANDOM()` sorting, so we need to perform two queries.

The correct behaviour is backed by tests.



126
127
128
# File 'app/services/decidim/proposals/proposal_search.rb', line 126

def results
  Proposal.where(id: super.pluck(:id))
end

#search_activityObject

Handle the activity filter



53
54
55
56
57
58
59
60
61
62
63
# File 'app/services/decidim/proposals/proposal_search.rb', line 53

def search_activity
  if activity.include? "voted"
    query
      .includes(:votes)
      .where(decidim_proposals_proposal_votes: {
               decidim_author_id: options[:current_user]
             })
  else
    query
  end
end

#search_originObject

Handle the origin filter



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
# File 'app/services/decidim/proposals/proposal_search.rb', line 24

def search_origin
  case origin
  when "official"
    query
      .where.not(coauthorships_count: 0)
      .joins(:coauthorships)
      .where(decidim_coauthorships: { decidim_author_type: "Decidim::Organization" })
  when "citizens"
    query
      .where.not(coauthorships_count: 0)
      .joins(:coauthorships)
      .where.not(decidim_coauthorships: { decidim_author_type: "Decidim::Organization" })
  when "user_group"
    query
      .where.not(coauthorships_count: 0)
      .joins(:coauthorships)
      .where(decidim_coauthorships: { decidim_author_type: "Decidim::UserBaseEntity" })
      .where.not(decidim_coauthorships: { decidim_user_group_id: nil })
  when "meeting"
    query
      .where.not(coauthorships_count: 0)
      .joins(:coauthorships)
      .where(decidim_coauthorships: { decidim_author_type: "Decidim::Meetings::Meeting" })
  else # Assume 'all'
    query
  end
end

Filters Proposals by the name of the classes they are linked to. By default, returns all Proposals. When a ‘related_to` param is given, then it camelcases item to find the real class name and checks the links for the Proposals.

The ‘related_to` param is expected to be in this form:

"decidim/meetings/meeting"

This can be achieved by performing ‘klass.name.underscore`.

Returns only those proposals that are linked to the given class name.



106
107
108
109
110
111
112
113
114
115
116
# File 'app/services/decidim/proposals/proposal_search.rb', line 106

def search_related_to
  from = query
         .joins(:resource_links_from)
         .where(decidim_resource_links: { to_type: related_to.camelcase })

  to = query
       .joins(:resource_links_to)
       .where(decidim_resource_links: { from_type: related_to.camelcase })

  query.where(id: from).or(query.where(id: to))
end

#search_search_textObject

Handle the search_text filter



17
18
19
20
21
# File 'app/services/decidim/proposals/proposal_search.rb', line 17

def search_search_text
  query
    .where("title ILIKE ?", "%#{search_text}%")
    .or(query.where("body ILIKE ?", "%#{search_text}%"))
end

#search_stateObject

Handle the state filter



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'app/services/decidim/proposals/proposal_search.rb', line 66

def search_state
  case state
  when "accepted"
    query.accepted
  when "rejected"
    query.rejected
  when "evaluating"
    query.evaluating
  when "withdrawn"
    query.withdrawn
  when "except_rejected"
    query.except_rejected.except_withdrawn
  else # Assume 'not_withdrawn'
    query.except_withdrawn
  end
end

#search_typeObject

Handle the amendment type filter



84
85
86
87
88
89
90
91
92
93
# File 'app/services/decidim/proposals/proposal_search.rb', line 84

def search_type
  case type
  when "proposals"
    query.where.not(id: query.joins(:amendable).pluck(:id))
  when "amendments"
    query.where(id: query.joins(:amendable).pluck(:id))
  else
    query
  end
end