Fixed bug: Organization search queries don't find case insensitive results.
This commit is contained in:
parent
61aa8fb84a
commit
809a698c03
4 changed files with 67 additions and 6 deletions
|
@ -17,6 +17,7 @@ class ApplicationModel < ActiveRecord::Base
|
|||
include ApplicationModel::HasExternalSync
|
||||
include ApplicationModel::ChecksImport
|
||||
include ApplicationModel::CanTouchReferences
|
||||
include ApplicationModel::CanQueryCaseInsensitiveWhereOrSql
|
||||
|
||||
self.abstract_class = true
|
||||
end
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
|
||||
module ApplicationModel::CanQueryCaseInsensitiveWhereOrSql
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
|
||||
# Builds a case insenstive WHERE ... OR ... SQL query.
|
||||
#
|
||||
# @see .or_cis
|
||||
#
|
||||
# @example
|
||||
# Organization.where_or_cis(%i[name note], "%zammad%").to_sql
|
||||
# #=> "SELECT `organizations`.* FROM `organizations` WHERE (`organizations`.`name` LIKE '%zammad%' OR `organizations`.`note` LIKE '%zammad%')"
|
||||
#
|
||||
# @return [ActiveRecord::Relation] the ActiveRecord relation that can be combined or executed
|
||||
scope :where_or_cis, ->(*args) { where(or_cis(*args)) }
|
||||
end
|
||||
|
||||
# methods defined here are going to extend the class, not the instance of it
|
||||
class_methods do
|
||||
|
||||
# Builds a case insenstive OR SQL grouping. This comes in handy for join queries.
|
||||
# For direct WHERE queries prefer .where_or_cis scope.
|
||||
#
|
||||
# @param [Array] attributes the attributes that should get queried case insensitive.
|
||||
# @param [String] query the SQL query that should be used for each given attribute.
|
||||
#
|
||||
# @example
|
||||
# Organization.joins(:users).where(User.or_cis(%i[firstname lastname email], "%#{query}%"))
|
||||
#
|
||||
# @return [Arel::Nodes::Grouping] can be passed to ActiveRecord queries
|
||||
def or_cis(attributes, query)
|
||||
# use Arel to create an Array of case insenstive
|
||||
# LIKE queries based on the current DB adapter
|
||||
cis_matches = attributes.map do |attribute|
|
||||
arel_table[attribute].matches(query)
|
||||
end
|
||||
|
||||
# return the by OR joined Arel queries
|
||||
cis_matches.inject(:or)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -77,9 +77,11 @@ returns
|
|||
# fallback do sql query
|
||||
# - stip out * we already search for *query* -
|
||||
query.delete! '*'
|
||||
organizations = Organization.where(
|
||||
'name LIKE ? OR note LIKE ?', "%#{query}%", "%#{query}%"
|
||||
).order('name').offset(offset).limit(limit).to_a
|
||||
organizations = Organization.where_or_cis(%i[name note], "%#{query}%")
|
||||
.order('name')
|
||||
.offset(offset)
|
||||
.limit(limit)
|
||||
.to_a
|
||||
|
||||
# use result independent of size if an explicit offset is given
|
||||
# this is the case for e.g. paginated searches
|
||||
|
@ -87,9 +89,11 @@ returns
|
|||
return organizations if organizations.length > 3
|
||||
|
||||
# if only a few organizations are found, search for names of users
|
||||
organizations_by_user = Organization.select('DISTINCT(organizations.id), organizations.name').joins('LEFT OUTER JOIN users ON users.organization_id = organizations.id').where(
|
||||
'users.firstname LIKE ? or users.lastname LIKE ? or users.email LIKE ?', "%#{query}%", "%#{query}%", "%#{query}%"
|
||||
).order('organizations.name').limit(limit)
|
||||
organizations_by_user = Organization.select('DISTINCT(organizations.id), organizations.name')
|
||||
.joins('LEFT OUTER JOIN users ON users.organization_id = organizations.id')
|
||||
.where(User.or_cis(%i[firstname lastname email], "%#{query}%"))
|
||||
.order('organizations.name')
|
||||
.limit(limit)
|
||||
|
||||
organizations_by_user.each do |organization_by_user|
|
||||
|
||||
|
|
13
spec/models/organization_spec.rb
Normal file
13
spec/models/organization_spec.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Organization do
|
||||
|
||||
context '.where_or_cis' do
|
||||
|
||||
it 'finds instance by querying multiple attributes case insensitive' do
|
||||
# search for Zammad Foundation
|
||||
organizations = described_class.where_or_cis(%i[name note], '%zammad%')
|
||||
expect(organizations).not_to be_blank
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue