pursuit 0.2.0 → 0.3.0

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: 2b49ae3ec2734b8b67fef2fb0686b85af3a694745db4654de863942d4a598d53
4
- data.tar.gz: 8d8a6e71f23b31d0ebf33a1c2554a9875c0c189786954574c3d5f58ced5fe304
3
+ metadata.gz: 9584065901bd2b27fce1df13ee13586151c96be3e04f222b81c6ee93d8f078a4
4
+ data.tar.gz: 81f233b5d39526129b8bdf7c7bba997e9a5b964b9bd5024bc3e3351f1105c927
5
5
  SHA512:
6
- metadata.gz: faebb7031e643b0fe4011cee2fda71a916dd12aa2819845a26bf79ef6ca0f0411bcd3e8b5ea1f092624909933639d97d0e59cc2b80ba38ea10f2dcbf0254c154
7
- data.tar.gz: 0c06093eb83369d20f5e64a843483e98a019a5facb594f75b845949cfdcc0b7027da78ccb8be92d6a739cc76720e1d28165019aaaf7220718deb550c2816440a
6
+ metadata.gz: 83fcec1d5657de087a5a5fdf71b131e34632fc02328cd66d2a551c438201f9125fd8d0861d239a96a4b6b36c6ac3bde342efaa4b610a1689646540229fe456bd
7
+ data.tar.gz: 47d981997a463f5203b3316410d6f5e2395fc1aa448329a86a625a732c2751a3e281b4581973cb9893f3c76d68f6999f38a0fbe0020c56ecc608f99b968101b0
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pursuit (0.2.0)
4
+ pursuit (0.3.0)
5
5
  activerecord (>= 5.2.0, < 6.2.0)
6
6
  activesupport (>= 5.2.0, < 6.2.0)
7
7
 
data/README.md CHANGED
@@ -23,19 +23,18 @@ class Product < ActiveRecord::Base
23
23
  searchable do |o|
24
24
  o.relation :variations, :title, :stock_status
25
25
 
26
- o.keyed :title
27
- o.keyed :description
28
- o.keyed :rating
26
+ # Attributes can be used for both keyed and unkeyed searching by default, but you can pass either `keyed: false` or
27
+ # `unkeyed: false` to restrict when the attribute is searched.
28
+ o.attribute :title
29
+ o.attribute :description
30
+ o.attribute :rating, unkeyed: false
29
31
 
30
32
  # You can also create virtual attributes to search by passing in a block that returns an arel node.
31
- o.keyed :title_length do
33
+ o.attribute :title_length, unkeyed: false do
32
34
  Arel::Nodes::NamedFunction.new('LENGTH', [
33
35
  arel_table[:title]
34
36
  ])
35
37
  end
36
-
37
- o.unkeyed :title
38
- o.unkeyed :description
39
38
  end
40
39
  end
41
40
  ```
@@ -3,5 +3,5 @@
3
3
  module Pursuit
4
4
  # @return [String] The gem's semantic version number.
5
5
  #
6
- VERSION = '0.2.0'
6
+ VERSION = '0.3.0'
7
7
  end
@@ -2,40 +2,55 @@
2
2
 
3
3
  module Pursuit
4
4
  class SearchOptions
5
+ # @return [Struct] The structure which holds the search options for a single attribute.
6
+ #
7
+ AttributeOptions = Struct.new(:keyed, :unkeyed, :block)
8
+
5
9
  # @return [Class<ActiveRecord::Base>] The `ActiveRecord::Base` child class to search.
6
10
  #
7
11
  attr_reader :record_class
8
12
 
9
- # @return [Hash<Symbol, Array<Symbol>>] The record's relatives and the attribute names that can be searched.
13
+ # @return [Hash<Symbol, Array<Symbol>>] The attribute names of the record's relatives which can be searched.
10
14
  #
11
15
  attr_reader :relations
12
16
 
13
- # @return [Hash<Symbol, Proc>] The attribute names which can be searched with a keyed term (e.g. 'last_name:*herb').
14
- #
15
- attr_reader :keyed_attributes
16
-
17
- # @return [Hash<Symbol, Proc>] The attribute names which can be searched with an unkeyed term (e.g. 'herb').
17
+ # @return [Hash<Symbol, AttributeOptions>] The attributes which can be searched.
18
18
  #
19
- attr_reader :unkeyed_attributes
19
+ attr_reader :attributes
20
20
 
21
- # Create a new `SearchOptions` ready for adding options.
21
+ # Create a new `SearchOptions` and call the passed block to setup the options.
22
22
  #
23
23
  # @params record_class [Class<ActiveRecord::Base>]
24
- # @params block [Proc]
24
+ # @params block [Proc]
25
25
  #
26
26
  def initialize(record_class, &block)
27
27
  @record_class = record_class
28
28
  @relations = {}
29
- @keyed_attributes = {}
30
- @unkeyed_attributes = {}
29
+ @attributes = {}
31
30
 
32
31
  block.call(self) if block
33
32
  end
34
33
 
34
+ # @return [Hash<Symbol, Proc>] The attributes which can be queried using a keyed term.
35
+ #
36
+ def keyed_attributes
37
+ attributes.each_with_object({}) do |(name, options), keyed_attributes|
38
+ keyed_attributes[name] = options.block if options.keyed
39
+ end
40
+ end
41
+
42
+ # @return [Hash<Symbol, Proc>] The attributes which can be queried using an unkeyed term.
43
+ #
44
+ def unkeyed_attributes
45
+ attributes.each_with_object({}) do |(name, options), unkeyed_attributes|
46
+ unkeyed_attributes[name] = options.block if options.unkeyed
47
+ end
48
+ end
49
+
35
50
  # @return [Array<String>] The collection of all possible attributes which can be used as a keyed term.
36
51
  #
37
52
  def keys
38
- keys = relations.keys + keyed_attributes.keys
53
+ keys = relations.keys + attributes.select { |_, a| a.keyed }.keys
39
54
  keys.map(&:to_s).uniq
40
55
  end
41
56
 
@@ -51,21 +66,13 @@ module Pursuit
51
66
 
52
67
  # Add a keyed attribute to search.
53
68
  #
54
- # @param name [Symbol] The name of the attribute.
55
- # @param block [Proc] A block which returns an arel node to query against instead of a real attribute.
56
- #
57
- def keyed(name, &block)
58
- keyed_attributes[name] = block || -> { record_class.arel_table[name] }
59
- nil
60
- end
61
-
62
- # Add an unkeyed attribute to search.
63
- #
64
- # @param name [Symbol] The name of the attribute.
65
- # @param block [Proc] A block which returns an arel node to query against instead of a real attribute.
69
+ # @param name [Symbol] The name of the attribute.
70
+ # @param keyed [Boolean] `true` when the attribute should be searchable using a keyed term, `false` otherwise.
71
+ # @param unkeyed [Boolean] `true` when the attribute should be searchable using an unkeyed term, `false` otherwise.
72
+ # @param block [Proc] A block which returns an Arel node to query, instead of the matching table column.
66
73
  #
67
- def unkeyed(name, &block)
68
- unkeyed_attributes[name] = block || -> { record_class.arel_table[name] }
74
+ def attribute(name, keyed: true, unkeyed: true, &block)
75
+ attributes[name] = AttributeOptions.new(keyed, unkeyed, block || -> { record_class.arel_table[name] })
69
76
  nil
70
77
  end
71
78
  end
@@ -8,17 +8,13 @@ class Product < ActiveRecord::Base
8
8
  searchable do |o|
9
9
  o.relation :variations, :title, :stock_status
10
10
 
11
- o.keyed :title
12
- o.keyed :description
13
- o.keyed :rating
14
-
15
- o.keyed :title_length do
11
+ o.attribute :title
12
+ o.attribute :description
13
+ o.attribute :rating, unkeyed: false
14
+ o.attribute :title_length, unkeyed: false do
16
15
  Arel::Nodes::NamedFunction.new('LENGTH', [
17
16
  arel_table[:title]
18
17
  ])
19
18
  end
20
-
21
- o.unkeyed :title
22
- o.unkeyed :description
23
19
  end
24
20
  end
@@ -11,19 +11,6 @@ RSpec.describe Pursuit::SearchOptions do
11
11
  end
12
12
  end
13
13
 
14
- before do
15
- search_options.relation :variations, :title, :stock_status
16
-
17
- search_options.keyed :title
18
- search_options.keyed :title_length, &title_length_node_builder
19
- search_options.keyed :description
20
- search_options.keyed :rating
21
-
22
- search_options.unkeyed :title
23
- search_options.unkeyed :title_length, &title_length_node_builder
24
- search_options.unkeyed :description
25
- end
26
-
27
14
  describe '#record_class' do
28
15
  subject(:record_class) { search_options.record_class }
29
16
 
@@ -35,6 +22,10 @@ RSpec.describe Pursuit::SearchOptions do
35
22
  describe '#relations' do
36
23
  subject(:relations) { search_options.relations }
37
24
 
25
+ before do
26
+ search_options.relation :variations, :title, :stock_status
27
+ end
28
+
38
29
  it 'is expected to contain the correct relations' do
39
30
  expect(relations).to eq(variations: %i[title stock_status])
40
31
  end
@@ -43,12 +34,19 @@ RSpec.describe Pursuit::SearchOptions do
43
34
  describe '#keyed_attributes' do
44
35
  subject(:keyed_attributes) { search_options.keyed_attributes }
45
36
 
37
+ before do
38
+ search_options.attribute :title, keyed: false
39
+ search_options.attribute :title_length, &title_length_node_builder
40
+ search_options.attribute :description
41
+ search_options.attribute :rating, unkeyed: false
42
+ end
43
+
46
44
  it 'is expected to contain the correct keyed attributes' do
47
- expect(keyed_attributes.keys).to contain_exactly(:title, :title_length, :description, :rating)
45
+ expect(keyed_attributes.keys).to contain_exactly(:title_length, :description, :rating)
48
46
  end
49
47
 
50
48
  it 'is expected to set a default node builder for attributes declared without a block' do
51
- expect(keyed_attributes[:title].call).to eq(Product.arel_table[:title])
49
+ expect(keyed_attributes[:description].call).to eq(Product.arel_table[:description])
52
50
  end
53
51
 
54
52
  it 'is expected to set a custom node builder for attributes declared with a block' do
@@ -59,6 +57,13 @@ RSpec.describe Pursuit::SearchOptions do
59
57
  describe '#unkeyed_attributes' do
60
58
  subject(:unkeyed_attributes) { search_options.unkeyed_attributes }
61
59
 
60
+ before do
61
+ search_options.attribute :title, keyed: false
62
+ search_options.attribute :title_length, &title_length_node_builder
63
+ search_options.attribute :description
64
+ search_options.attribute :rating, unkeyed: false
65
+ end
66
+
62
67
  it 'is expected to contain the correct unkeyed attributes' do
63
68
  expect(unkeyed_attributes.keys).to contain_exactly(:title, :title_length, :description)
64
69
  end
@@ -71,4 +76,64 @@ RSpec.describe Pursuit::SearchOptions do
71
76
  expect(unkeyed_attributes[:title_length]).to eq(title_length_node_builder)
72
77
  end
73
78
  end
79
+
80
+ describe '#relation' do
81
+ subject(:relation) { search_options.relation(:variations, :title, :stock_status) }
82
+
83
+ it 'is expected to add the relation to #relations' do
84
+ expect { relation }.to change(search_options, :relations).from({}).to(variations: %i[title stock_status])
85
+ end
86
+ end
87
+
88
+ describe '#attribute' do
89
+ subject(:attribute) { search_options.attribute(:description) }
90
+
91
+ it { is_expected.to eq(nil) }
92
+
93
+ it 'is expected to add the attribute to #attributes' do
94
+ expect { attribute }.to change(search_options.attributes, :keys).from([]).to(%i[description])
95
+ end
96
+
97
+ it 'is expected to allow keyed searching by default' do
98
+ attribute
99
+ expect(search_options.attributes[:description].keyed).to eq(true)
100
+ end
101
+
102
+ it 'is expected to allow unkeyed searching by default' do
103
+ attribute
104
+ expect(search_options.attributes[:description].unkeyed).to eq(true)
105
+ end
106
+
107
+ it 'is expected to use the matching table column node builder by default' do
108
+ attribute
109
+ expect(search_options.attributes[:description].block.call).to eq(Product.arel_table[:description])
110
+ end
111
+
112
+ context 'when passing :keyed eq false' do
113
+ subject(:attribute) { search_options.attribute(:description, keyed: false) }
114
+
115
+ it 'is expected to disallow keyed searching' do
116
+ attribute
117
+ expect(search_options.attributes[:description].keyed).to eq(false)
118
+ end
119
+ end
120
+
121
+ context 'when passing :unkeyed eq false' do
122
+ subject(:attribute) { search_options.attribute(:description, unkeyed: false) }
123
+
124
+ it 'is expected to disallow unkeyed searching' do
125
+ attribute
126
+ expect(search_options.attributes[:description].unkeyed).to eq(false)
127
+ end
128
+ end
129
+
130
+ context 'when passing a block' do
131
+ subject(:attribute) { search_options.attribute(:description, &title_length_node_builder) }
132
+
133
+ it 'is expected to use the custom node builder' do
134
+ attribute
135
+ expect(search_options.attributes[:description].block).to eq(title_length_node_builder)
136
+ end
137
+ end
138
+ end
74
139
  end
@@ -7,18 +7,14 @@ RSpec.describe Pursuit::Search do
7
7
  Pursuit::SearchOptions.new(Product) do |o|
8
8
  o.relation :variations, :title, :stock_status
9
9
 
10
- o.keyed :title
11
- o.keyed :description
12
- o.keyed :rating
13
-
14
- o.keyed :title_length do
10
+ o.attribute :title
11
+ o.attribute :description
12
+ o.attribute :rating, unkeyed: false
13
+ o.attribute :title_length, unkeyed: false do
15
14
  Arel::Nodes::NamedFunction.new('LENGTH', [
16
15
  Product.arel_table[:title]
17
16
  ])
18
17
  end
19
-
20
- o.unkeyed :title
21
- o.unkeyed :description
22
18
  end
23
19
  end
24
20
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pursuit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nialto Services
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-18 00:00:00.000000000 Z
11
+ date: 2021-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord