activerecord_search 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 18917659557593b82d50a5c0fe4eee591a5c8e73
4
+ data.tar.gz: ea6c900b5e0e77c27948ea2e900cd6a14e6230ce
5
+ SHA512:
6
+ metadata.gz: e27dd93a4e7198b35965bcbd21e92eb40c9a3a616fdfc5863f153ad4d4b22aa68d09268715b10a4c1e1f65e8401720056ab36837183f19b1c91741ac3c9ebfcd
7
+ data.tar.gz: c6e1db99ba8ddd9305fb895a7aacb7cedc765b2931cee9f2c59d3ab8d53b3712c8b4136d8228feadb26afe9226d39801f274a63abeb89f4eaa25f70821ceae46
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Amitree
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,29 @@
1
+ activerecord\_search
2
+ ====================
3
+
4
+ This gem extends the ActiveRecord predicate builder to allow writing LIKE/ILIKE queries without writing raw SQL.
5
+
6
+ Usage
7
+ =====
8
+
9
+ Add to your Gemfile:
10
+
11
+ ```ruby
12
+ gem 'activerecord_search'
13
+ ```
14
+
15
+ Then you can write queries like this:
16
+
17
+ ```ruby
18
+ users = User.where(name: Search('ji'))
19
+ # Returns users "Jim" and "Benji"
20
+ users = User.where(name: Search(ends_with: 'ji'))
21
+ # Returns user "Benji"
22
+ users = User.where(name: Search(starts_with: 'ji'))
23
+ # Find user "Jim"
24
+ users = User.where(name: Search(like: 'b%i'))
25
+ # Find users "Benji" and "Banh Mi"
26
+ ```
27
+
28
+ Internally, it uses the Arel `matches` node, which becomes `ILIKE` for Postgres
29
+ and `LIKE` for other databases. In general, this should be case insensitive.
@@ -0,0 +1,42 @@
1
+ module Search
2
+ class Railtie < ::Rails::Railtie
3
+ initializer "PredicateBuilder" do
4
+ ActiveRecord::PredicateBuilder.register_handler(Search::Term, ->(attribute, search_term) { search_term.match(attribute) })
5
+ end
6
+ end
7
+
8
+ class Term
9
+ def initialize(condition)
10
+ @pattern = case condition
11
+ when nil
12
+ nil
13
+ when Hash
14
+ key, value = condition.first if condition.length == 1
15
+ case key.to_sym
16
+ when :starts_with
17
+ "#{value}%"
18
+ when :ends_with
19
+ "%#{value}"
20
+ when :like
21
+ "#{value}"
22
+ else
23
+ raise 'Expected hash to contain exactly one of these keys: "starts_with", "ends_with", or "like"' unless key.in? %i(starts_with ends_with like)
24
+ end
25
+ else
26
+ "%#{condition}%"
27
+ end
28
+ end
29
+
30
+ def match(attribute)
31
+ if @pattern.nil?
32
+ attribute.eq(nil)
33
+ else
34
+ attribute.matches(@pattern)
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ def Search(*args)
41
+ Search::Term.new(*args)
42
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ class User < ActiveRecord::Base
4
+ end
5
+
6
+ describe Search do
7
+ let(:relation) { ActiveRecord::Relation.new(User, Arel::Table.new('users')) }
8
+
9
+ shared_examples_for 'generates the correct query' do |condition, attribute, pattern, expected_arel_class = Arel::Nodes::Matches|
10
+ let(:arel_nodes) { relation.where(condition).where_values }
11
+ let(:arel_node) { arel_nodes.first }
12
+
13
+ it 'returns a Arel::Nodes::Matches node' do
14
+ expect(arel_nodes.length).to eq 1
15
+ expect(arel_node).to be_an expected_arel_class
16
+ end
17
+
18
+ it 'matches on the specified attribute' do
19
+ expect(arel_node.left.name).to eq attribute
20
+ end
21
+
22
+ it 'uses the right pattern' do
23
+ expect(arel_node.right).to eq pattern
24
+ end
25
+ end
26
+
27
+ describe 'searches for substrings' do
28
+ it_should_behave_like 'generates the correct query', { foo: Search('bar') }, 'foo', '%bar%'
29
+ end
30
+
31
+ describe 'ends_with' do
32
+ it_should_behave_like 'generates the correct query', { foo: Search(ends_with: 'bar') }, 'foo', '%bar'
33
+ end
34
+
35
+ describe 'starts_with' do
36
+ it_should_behave_like 'generates the correct query', { foo: Search(ends_with: 'bar') }, 'foo', '%bar'
37
+ end
38
+
39
+ describe 'like' do
40
+ it_should_behave_like 'generates the correct query', { foo: Search(like: '%foo%bar') }, 'foo', '%foo%bar'
41
+ end
42
+
43
+ describe 'nil values' do
44
+ it_should_behave_like 'generates the correct query', { foo: Search(nil) }, 'foo', nil, Arel::Nodes::Equality
45
+ end
46
+
47
+ describe 'exceptions' do
48
+ it 'should raise if an empty hash is passed' do
49
+ expect { Search({}) }.to raise_error
50
+ end
51
+ it 'should raise if multiple hash keys are passed' do
52
+ expect { Search({starts_with: 'a', ends_with: 'b'}) }.to raise_error
53
+ end
54
+ it 'should raise if an invalid hash key is passed' do
55
+ expect { Search({foo: 'bar'}) }.to raise_error
56
+ end
57
+ end
58
+ end
59
+
@@ -0,0 +1,4 @@
1
+ require 'rails/all'
2
+ require 'search'
3
+
4
+ Search::Railtie.run_initializers
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activerecord_search
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ platform: ruby
6
+ authors:
7
+ - Tony Novak
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 4.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 4.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 4.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 4.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec-rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 3.0.0.beta
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 3.0.0.beta
55
+ description: Extends the ActiveRecord predicate builder to allow writing LIKE/ILIKE
56
+ queries without writing raw SQL
57
+ email: tony@amitree.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - Gemfile
63
+ - LICENSE
64
+ - README.md
65
+ - lib/search.rb
66
+ - spec/lib/activerecord_search_spec.rb
67
+ - spec/spec_helper.rb
68
+ homepage: http://rubygems.org/gems/activerecord_search
69
+ licenses:
70
+ - MIT
71
+ metadata: {}
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 2.2.1
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: An easy way to write LIKE / ILIKE queries for Active Record models
92
+ test_files: []