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)


51
52
53
54
# File 'app/services/forest_liana/search_query_builder.rb', line 51

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)


113
114
115
116
117
# File 'app/services/forest_liana/search_query_builder.rb', line 113

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



132
133
134
135
136
137
138
139
140
141
# File 'app/services/forest_liana/search_query_builder.rb', line 132

def belongs_to_filter
  if @params[:filter]
    @params[:filter].each do |field, value|
      next unless belongs_to_association?(field)
      @records = belongs_to_subfield_filter(field, value)
    end
  end

  @records
end

#belongs_to_subfield_filter(field, value) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
# File 'app/services/forest_liana/search_query_builder.rb', line 119

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
# File 'app/services/forest_liana/search_query_builder.rb', line 38

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

  @records
end

#has_many_association?(field) ⇒ Boolean

Returns:

  • (Boolean)


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

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



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'app/services/forest_liana/search_query_builder.rb', line 79

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



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

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

      if field.include?(':')
        @records = has_many_subfield_filter(field, value)
      else
        @records = has_many_field_filter(field, value)
      end
    end
  end

  @records
end

#has_many_subfield_filter(field, value) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'app/services/forest_liana/search_query_builder.rb', line 95

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