Class: ForestLiana::SearchQueryBuilder

Inherits:
Object
  • Object
show all
Defined in:
app/services/forest_liana/search_query_builder.rb

Instance Method Summary collapse

Constructor Details

#initialize(resource, params) ⇒ SearchQueryBuilder

Returns a new instance of SearchQueryBuilder.



4
5
6
7
# File 'app/services/forest_liana/search_query_builder.rb', line 4

def initialize(resource, params)
  @resource = @records = resource
  @params = params
end

Instance Method Details

#association?(field) ⇒ Boolean

Returns:

  • (Boolean)


53
54
55
56
# File 'app/services/forest_liana/search_query_builder.rb', line 53

def association?(field)
  field = field.split(':').first if field.include?(':')
  @resource.reflect_on_association(field.to_sym).present?
end

#belongs_to_association?(field) ⇒ Boolean

Returns:

  • (Boolean)


117
118
119
120
121
# File 'app/services/forest_liana/search_query_builder.rb', line 117

def belongs_to_association?(field)
  field = field.split(':').first if field.include?(':')
  association = @resource.reflect_on_association(field.to_sym)
  [:belongs_to, :has_one].include?(association.try(:macro))
end

#belongs_to_filterObject



136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'app/services/forest_liana/search_query_builder.rb', line 136

def belongs_to_filter
  if @params[:filter]
    @params[:filter].each do |field, values|
      next unless belongs_to_association?(field)

      values.split(',').each do |value|
        @records = belongs_to_subfield_filter(field, value)
      end
    end
  end

  @records
end

#belongs_to_subfield_filter(field, value) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/services/forest_liana/search_query_builder.rb', line 123

def belongs_to_subfield_filter(field, value)
  field, subfield = field.split(':')

  association = @resource.reflect_on_association(field.to_sym)
  return if association.blank?

  operator, value = OperatorValueParser.parse(value)

  @records = @records
    .joins(field.to_sym)
    .where("#{association.table_name}.#{subfield} #{operator} '#{value}'")
end

#filter_paramObject



38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'app/services/forest_liana/search_query_builder.rb', line 38

def filter_param
  if @params[:filter]
    @params[:filter].each do |field, values|
      next if association?(field)
      values.split(',').each do |value|
        operator, value = OperatorValueParser.parse(value)
        @records = OperatorValueParser.add_where(@records, field, operator,
                                                 value)
      end
    end
  end

  @records
end

#has_many_association?(field) ⇒ Boolean

Returns:

  • (Boolean)


58
59
60
61
62
63
# File 'app/services/forest_liana/search_query_builder.rb', line 58

def has_many_association?(field)
  field = field.split(':').first if field.include?(':')
  association = @resource.reflect_on_association(field.to_sym)

  [:has_many, :has_and_belongs_to_many].include?(association.try(:macro))
end

#has_many_field_filter(field, value) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'app/services/forest_liana/search_query_builder.rb', line 83

def has_many_field_filter(field, value)
  association = @resource.reflect_on_association(field.to_sym)
  return if association.blank?

  operator, value = OperatorValueParser.parse(value)

  @records = @records
    .select("#{@resource.table_name}.*,
            COUNT(#{association.table_name}.id)
            #{association.table_name}_has_many_count")
    .joins(ArelHelpers.join_association(@resource, association.name,
                                        Arel::Nodes::OuterJoin))
    .group("#{@resource.table_name}.id")
    .having("COUNT(#{association.table_name}) #{operator} #{value}")
end

#has_many_filterObject



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

def has_many_filter
  if @params[:filter]
    @params[:filter].each do |field, values|
      next unless has_many_association?(field)

      values.split(',').each do |value|
        if field.include?(':')
          @records = has_many_subfield_filter(field, value)
        else
          @records = has_many_field_filter(field, value)
        end
      end
    end
  end

  @records
end

#has_many_subfield_filter(field, value) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'app/services/forest_liana/search_query_builder.rb', line 99

def has_many_subfield_filter(field, value)
  field, subfield = field.split(':')

  association = @resource.reflect_on_association(field.to_sym)
  return if association.blank?

  operator, value = OperatorValueParser.parse(value)

  @records = @records
    .select("#{@resource.table_name}.*,
            COUNT(#{association.table_name}.id)
            #{association.table_name}_has_many_count")
    .joins(ArelHelpers.join_association(@resource, association.name,
                                        Arel::Nodes::OuterJoin))
    .group("#{@resource.table_name}.id, #{association.table_name}.#{subfield}")
    .having("#{association.table_name}.#{subfield} #{operator} '#{value}'")
end

#performObject



9
10
11
12
13
14
15
16
# File 'app/services/forest_liana/search_query_builder.rb', line 9

def perform
  @records = search_param
  @records = filter_param
  @records = has_many_filter
  @records = belongs_to_filter

  @records
end

#search_paramObject



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'app/services/forest_liana/search_query_builder.rb', line 18

def search_param
  if @params[:search]
    conditions = []

    @resource.columns.each_with_index do |column, index|
      if column.name == 'id'
        conditions << "#{@resource.table_name}.id =
          #{@params[:search].to_i}"
      elsif column.type == :string || column.type == :text
        conditions <<
          "#{column.name} ILIKE '%#{@params[:search].downcase}%'"
      end
    end

    @records = @resource.where(conditions.join(' OR '))
  end

  @records
end