searchable-by 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '008edf75bb0e4b27410f7e889cbfd26eda27d0391dd7e70be3e984a962ddd756'
4
- data.tar.gz: 9b2fbbc4cc13b2cfe6e23998616ec48e49617bfb67db3143f800c5d35134b2df
3
+ metadata.gz: 8c1c5cfdea465a6a9ff73159a062558c5475889d27e0119e81212bb8bb37bbc1
4
+ data.tar.gz: c77c158c890b37b67d1243c93b4d5c982731b55fb48d284ecc404de58142da26
5
5
  SHA512:
6
- metadata.gz: 0fa58611207ecef62a12c698be927aa34659e0b19f5c5a4ce6c8c2c87b77df49349fb72a4356683f406a80110727442e854448f4b1dc20bc04527e1981af03a2
7
- data.tar.gz: b9dbbde8350310301567ed1ba6cf8a45d80813e7f99415a6e0a6dc6d1a69b4dbd0f340a39851b8db4e291b503f21c2f4f9e8d74311cdaa5fe705a3a06a9201e1
6
+ metadata.gz: 1ba79022ae7056fc1cd6f6ef7af109ed6e0a7228601241ac2bc8f501818b6f487a6fd929f77bc3ce0dba9956b879def3dc705159c3696246d4653e3197f3d71f
7
+ data.tar.gz: c023dff5eb1bb4685dcfe7d10b7164242a090a930189ccc1b336c6de3437ab05d1de0dc90d13f52412e8e15b16a0a1386d5dacb289b208e00eefca5eab0cc2f7
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- searchable-by (0.5.0)
4
+ searchable-by (0.5.1)
5
5
  activerecord
6
6
  activesupport
7
7
 
data/lib/searchable_by.rb CHANGED
@@ -3,24 +3,42 @@ require 'shellwords'
3
3
 
4
4
  module ActiveRecord
5
5
  module SearchableBy
6
- class Config < Hash
6
+ class Column
7
+ attr_reader :attr, :type
8
+ attr_accessor :node
9
+
10
+ def initialize(attr, type: :string)
11
+ @attr = attr
12
+ @type = type.to_sym
13
+ end
14
+ end
15
+
16
+ class Config
17
+ attr_reader :columns, :scoping
18
+ attr_accessor :max_terms
19
+
7
20
  def initialize
8
- update columns: [], max_terms: 5
21
+ @columns = []
22
+ @max_terms = 5
9
23
  scope { all }
10
24
  end
11
25
 
26
+ def initialize_copy(other)
27
+ @columns = other.columns.dup
28
+ super
29
+ end
30
+
12
31
  def column(*attrs, &block)
13
32
  opts = attrs.extract_options!
14
- cols = self[:columns]
15
33
  attrs.each do |attr|
16
- cols.push(opts.merge(column: attr))
34
+ columns.push Column.new(attr, opts)
17
35
  end
18
- cols.push(opts.merge(column: block)) if block
19
- cols
36
+ columns.push Column.new(block, opts) if block
37
+ columns
20
38
  end
21
39
 
22
40
  def scope(&block)
23
- self[:scope] = block
41
+ @scoping = block
24
42
  end
25
43
  end
26
44
 
@@ -32,27 +50,30 @@ module ActiveRecord
32
50
  values
33
51
  end
34
52
 
35
- def self.build_clauses(relations, values)
53
+ def self.build_clauses(columns, values)
36
54
  clauses = values.map do |value|
37
55
  negate = value[0] == '-'
38
56
  value.slice!(0) if negate || value[0] == '+'
39
57
 
40
- c0, *cn = relations.map do |opts|
41
- build_condition(opts, value)
42
- end.compact
43
- next unless c0
58
+ grouping = columns.map do |column|
59
+ build_condition(column, value)
60
+ end
61
+ grouping.compact!
62
+ next if grouping.empty?
44
63
 
45
- [cn.inject(c0) {|x, part| x.or(part) }, negate]
64
+ clause = grouping.inject(&:or)
65
+ clause = clause.not if negate
66
+ clause
46
67
  end
47
68
  clauses.compact!
48
69
  clauses
49
70
  end
50
71
 
51
- def self.build_condition(opts, value)
52
- case opts[:type]
72
+ def self.build_condition(column, value)
73
+ case column.type
53
74
  when :int, :integer
54
75
  begin
55
- opts[:rel].eq(Integer(value))
76
+ column.node.eq(Integer(value))
56
77
  rescue ArgumentError
57
78
  nil
58
79
  end
@@ -60,7 +81,7 @@ module ActiveRecord
60
81
  value = value.dup
61
82
  value.gsub!('%', '\%')
62
83
  value.gsub!('_', '\_')
63
- opts[:rel].matches("%#{value}%")
84
+ column.node.matches("%#{value}%")
64
85
  end
65
86
  end
66
87
 
@@ -72,35 +93,35 @@ module ActiveRecord
72
93
  end
73
94
 
74
95
  def inherited(base) # :nodoc:
75
- base._searchable_by_config = _searchable_by_config.deep_dup
96
+ base._searchable_by_config = _searchable_by_config.dup
76
97
  super
77
98
  end
78
99
 
79
100
  def searchable_by(max_terms: 5, &block)
80
101
  _searchable_by_config.instance_eval(&block)
81
- _searchable_by_config[:max_terms] = max_terms if max_terms
102
+ _searchable_by_config.max_terms = max_terms if max_terms
82
103
  end
83
104
 
84
105
  # @param [String] query the search query
85
106
  # @return [ActiveRecord::Relation] the scoped relation
86
107
  def search_by(query)
87
- columns = _searchable_by_config[:columns]
108
+ columns = _searchable_by_config.columns
88
109
  return all if columns.empty?
89
110
 
90
- values = SearchableBy.norm_values(query).first(_searchable_by_config[:max_terms])
111
+ values = SearchableBy.norm_values(query).first(_searchable_by_config.max_terms)
91
112
  return all if values.empty?
92
113
 
93
- relations = columns.map do |opts|
94
- rel = opts[:column].is_a?(Proc) ? opts[:column].call : arel_table[opts[:column]]
95
- opts.merge(rel: rel)
114
+ columns.each do |col|
115
+ col.node ||= col.attr.is_a?(Proc) ? col.attr.call : arel_table[col.attr]
96
116
  end
97
- clauses = SearchableBy.build_clauses(relations, values)
117
+ clauses = SearchableBy.build_clauses(columns, values)
98
118
  return all if clauses.empty?
99
119
 
100
- scope = instance_exec(&_searchable_by_config[:scope])
101
- clauses.inject(scope) do |x, (clause, negate)|
102
- negate ? x.where.not(clause) : x.where(clause)
120
+ scope = instance_exec(&_searchable_by_config.scoping)
121
+ clauses.each do |clause|
122
+ scope = scope.where(clause)
103
123
  end
124
+ scope
104
125
  end
105
126
  end
106
127
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'searchable-by'
3
- s.version = '0.5.0'
3
+ s.version = '0.5.1'
4
4
  s.authors = ['Dimitrij Denissenko']
5
5
  s.email = ['dimitrij@blacksquaremedia.com']
6
6
  s.summary = 'Generate search scopes'
@@ -1,11 +1,17 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ActiveRecord::SearchableBy do
4
+
4
5
  it 'should ignore bad inputs' do
5
6
  expect(Post.search_by(nil).count).to eq(4)
6
7
  expect(Post.search_by('').count).to eq(4)
7
8
  end
8
9
 
10
+ it 'should configure correctly' do
11
+ expect(AbstractModel._searchable_by_config.columns.size).to eq(1)
12
+ expect(Post._searchable_by_config.columns.size).to eq(4)
13
+ end
14
+
9
15
  it 'should generate SQL' do
10
16
  sql = Post.search_by('123').to_sql
11
17
  expect(sql).to include(%("posts"."id" = 123))
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: searchable-by
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitrij Denissenko