seek_party 0.0.2 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0924852e23e1fe893c17e0bea8305d4c1c1f31d6f73eedd3e2b91c009b9f8809'
4
- data.tar.gz: 8a63dbfc9a23816286856195f820e67d78b1ac2016a20882c645e5b08e575200
3
+ metadata.gz: 3ca3c040d22ecaf44d42c4d94f63bc34795a691ebc3fcf24a201ba346611c560
4
+ data.tar.gz: 884466fbeb0b97fc741e82e21eca594d1611c78407eabb7f44f2606a3f5e8812
5
5
  SHA512:
6
- metadata.gz: 91b7c0211204c18d97c7ae9f81d7d341730b923e39783838f720afc97965441c1fd9a037146ee45df391f7393dad27d9c02cce6aea83a91a9626c5787ccb8dc4
7
- data.tar.gz: 746be003921717ebfc0a2ee4b7a252f039d38103f364b326c1fd8bf06df534aff31e85aae05c2863073c4d15d7efa0ad3fd47fd05cabd2f846bd08a27368a346
6
+ metadata.gz: 65fba3d3ab15003a1a3c781f8101a405f308688c6fcf3cd0ef1349551c13a795146c67d5e5ccd054af6f1fc26f45321d9574dc5ef0eb22bac38481d61daad8f7
7
+ data.tar.gz: 2de6b896f03f992aafa9b6cdaf80165289eeaab1eaae0a79c7b736cd436accee7bd1fdcf31018476270c8348e29e92d51f476a3528f948c60fd1920d648e748a
@@ -0,0 +1,19 @@
1
+ env:
2
+ global:
3
+ - CC_TEST_REPORTER_ID=$CODECLIMATE_REPO_TOKEN
4
+ sudo: false
5
+ language: ruby
6
+ cache: bundler
7
+ rvm:
8
+ - 2.6.3
9
+ before_install:
10
+ - gem install bundler -v 2.0.2
11
+ before_script:
12
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
13
+ - chmod +x ./cc-test-reporter
14
+ - ./cc-test-reporter before-build
15
+ script:
16
+ - bundle
17
+ - bundle exec rspec
18
+ after_success:
19
+ - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- seek_party (0.0.2)
4
+ seek_party (0.0.8)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # SeekParty - Searches made easy
2
2
 
3
+ [![Build Status](https://travis-ci.org/caws/seek_party.svg?branch=master)](https://travis-ci.org/caws/seek_party)
4
+ [![Maintainability](https://api.codeclimate.com/v1/badges/a05e479c6f535645d307/maintainability)](https://codeclimate.com/github/caws/seek_party/maintainability)
5
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/a05e479c6f535645d307/test_coverage)](https://codeclimate.com/github/caws/seek_party/test_coverage)
6
+
3
7
  ### What is this?
4
8
 
5
9
  Have you ever had to write a search functionality for a web application and found yourself
@@ -33,8 +37,6 @@ Below is what's currently doable:
33
37
  PS: The DEFAULT_BLACK_LIST contains the attributes :id, :created_at and :updated_at. You can pass your own
34
38
  DEFAULT_BLACK_LIST when calling the #search method from your model, but I recommend using the WHITE_LIST,
35
39
  as SeekParty will then only generate queries using the column names present there.
36
- You should also keep in mind that when building the queries, seek_party tries to pluralize your table name in order to refer to the table
37
- columns by their full name (ex: 'your_table.your_column_name').
38
40
 
39
41
  ## Getting started
40
42
 
@@ -43,7 +45,7 @@ PS: The DEFAULT_BLACK_LIST contains the attributes :id, :created_at and :updated
43
45
  Add the following to your Gemfile
44
46
 
45
47
  ``` ruby
46
- gem 'seek_party', '~> 0.0.2'
48
+ gem 'seek_party', '~> 0.0.7'
47
49
  ```
48
50
  Then run:
49
51
 
@@ -134,7 +136,7 @@ User.search(params: params)
134
136
  And this would result in the following query being produced:
135
137
 
136
138
  ``` sql
137
- SELECT "users".* FROM "users" WHERE (LOWER(CAST(users.name AS TEXT)) LIKE '%sugoi%' AND LOWER(CAST(users.name AS TEXT)) = 'bilbo' OR LOWER(CAST(users.email AS TEXT)) LIKE '%sugoi%' AND LOWER(CAST(users.name AS TEXT)) = 'bilbo')
139
+ SELECT "users".* FROM "users" WHERE (LOWER(CAST(users.name AS TEXT)) LIKE '%bilbo@theshire.com%' AND LOWER(CAST(users.name AS TEXT)) = 'bilbo' OR LOWER(CAST(users.email AS TEXT)) LIKE '%bilbo@theshire.com%' AND LOWER(CAST(users.name AS TEXT)) = 'bilbo')
138
140
  ```
139
141
 
140
142
  ### TO DO
@@ -1,7 +1,9 @@
1
1
  require 'active_record' unless defined? ActiveRecord
2
+ require_relative 'seek_party/models/sp_attribute'
3
+ require_relative 'seek_party/models/sp_query'
2
4
  require_relative 'seek_party/seek_party_attribute'
3
5
  require_relative 'seek_party/seek_party_engine'
4
- require_relative 'seek_party/seek_party_query'
6
+ require_relative 'seek_party/seek_party_query_builder'
5
7
  require_relative 'seek_party/version'
6
8
 
7
9
  module SeekParty
@@ -12,9 +14,6 @@ module SeekParty
12
14
  black_list: DEFAULT_BLACK_LIST,
13
15
  white_list: nil,
14
16
  scopes: [])
15
- # If there are params to work with, use SeekParty.
16
- # Otherwise, just return an empty instance of ActiveRecord_Relation.
17
- return none if params.empty?
18
17
 
19
18
  SeekPartyEngine
20
19
  .new(self,
@@ -0,0 +1,20 @@
1
+ class SPAttribute
2
+ attr_accessor :attributes, :table_name
3
+
4
+ def initialize(attributes: [], table_name: nil)
5
+ @attributes = attributes
6
+ @table_name = table_name
7
+ end
8
+
9
+ def add_attribute(attribute)
10
+ @attributes << attribute
11
+ end
12
+
13
+ def get_full_column_name(attribute)
14
+ if @attributes.include? attribute
15
+ "#{@table_name}.#{attribute}"
16
+ else
17
+ raise 'Attribute not present in the attribute list.'
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,31 @@
1
+ class SPQuery
2
+ attr_accessor :queries, :params
3
+
4
+ def initialize(queries: {}, params: nil)
5
+ @queries = queries
6
+ @params = params
7
+ end
8
+
9
+ def add_attribute_query(attribute, query)
10
+ @queries[attribute] << query
11
+ end
12
+
13
+ def set_attribute_query(attribute, query)
14
+ @queries[attribute] = query
15
+ end
16
+
17
+ def build_final_query
18
+ return if @queries.blank?
19
+
20
+ @queries.map { |key, value|
21
+ if key == @queries.keys.first
22
+ value
23
+ else
24
+ or_and(value)
25
+ end }.sum
26
+ end
27
+
28
+ def or_and(value)
29
+ @params[:search].present? ? " OR #{value}" : " AND #{value}"
30
+ end
31
+ end
@@ -5,17 +5,17 @@ module SeekParty
5
5
  :black_list
6
6
 
7
7
  def initialize(inspected_class, white_list, black_list)
8
- self.inspected_class = inspected_class
9
- self.white_list = white_list
10
- self.black_list = black_list
8
+ @inspected_class = inspected_class
9
+ @white_list = white_list
10
+ @black_list = black_list
11
11
  end
12
12
 
13
13
  # Compare attributes to params passed
14
14
  # If only search is present, query against all params
15
- # If both search and other attributes match agains the
15
+ # If both search and other attributes match against the
16
16
  # params hash, query against them too.
17
17
  def discover_attributes
18
- check_attributes inspected_class.new
18
+ check_attributes @inspected_class.new
19
19
  end
20
20
 
21
21
  private
@@ -23,31 +23,30 @@ module SeekParty
23
23
  def check_attributes(another_model)
24
24
  return nil if another_model.nil?
25
25
 
26
- attributes = []
26
+ sp_attribute = SPAttribute.new(table_name: get_table_name)
27
+
27
28
  another_model.attributes.keys.each do |attribute|
28
29
  next unless another_model.has_attribute? attribute
29
30
  next if black_listed? attribute
30
31
 
31
- if white_listed? attribute
32
- attributes << "#{pluralize_and_snake_case_class_name}.#{attribute}"
33
- end
32
+ sp_attribute.add_attribute(attribute) if white_listed? attribute
34
33
  end
35
34
 
36
- attributes
35
+ sp_attribute
37
36
  end
38
37
 
39
38
  def white_listed?(attribute_name)
40
- return true if white_list.nil?
39
+ return true if @white_list.nil?
41
40
 
42
- white_list.include? attribute_name
41
+ @white_list.include? attribute_name
43
42
  end
44
43
 
45
44
  def black_listed?(attribute_name)
46
- black_list.include? attribute_name
45
+ @black_list.include? attribute_name
47
46
  end
48
47
 
49
- def pluralize_and_snake_case_class_name
50
- inspected_class.name.pluralize.underscore
48
+ def get_table_name
49
+ @inspected_class.table_name.underscore
51
50
  end
52
51
  end
53
52
  end
@@ -4,16 +4,22 @@ module SeekParty
4
4
  :seek_party_query,
5
5
  :inspected_class
6
6
 
7
- def initialize(inspected_class, params: {}, white_list: nil, black_list: nil, scopes: {})
8
- @seek_party_attribute = SeekPartyAttribute.new(inspected_class, white_list, black_list)
9
- @seek_party_query = SeekPartyQuery.new(params)
7
+ def initialize(inspected_class,
8
+ params: {},
9
+ white_list: nil,
10
+ black_list: nil,
11
+ scopes: {})
12
+ @seek_party_attribute = SeekPartyAttribute.new(inspected_class,
13
+ white_list,
14
+ black_list)
15
+ @seek_party_query = SeekPartyQueryBuilder.new(params)
10
16
  @inspected_class = inspected_class
11
17
  @scopes = scopes
12
18
  end
13
19
 
14
20
  def search
15
- attributes = seek_party_attribute.discover_attributes
16
- final_query = seek_party_query.build_query(attributes)
21
+ spa_attribute = seek_party_attribute.discover_attributes
22
+ final_query = seek_party_query.build_query(spa_attribute)
17
23
  run_search(final_query)
18
24
  end
19
25
 
@@ -33,8 +39,22 @@ module SeekParty
33
39
  # else, as the returned object from run_search is an
34
40
  # ActiveRecord_Relation object that would accept
35
41
  # method chaining
36
- @scopes.each do |key, value|
37
- @inspected_class = @inspected_class.method(key).call(value)
42
+ @scopes.each do |scope|
43
+ if scope.respond_to?(:keys)
44
+ scope.keys.each do |key|
45
+ scope_call(key, scope[key])
46
+ end
47
+ else
48
+ scope_call(scope, nil)
49
+ end
50
+ end
51
+ end
52
+
53
+ def scope_call(key, value)
54
+ if value.present?
55
+ @inspected_class = @inspected_class.method(key).call(*value)
56
+ else
57
+ @inspected_class = @inspected_class.method(key).call
38
58
  end
39
59
  end
40
60
  end
@@ -1,44 +1,45 @@
1
1
  module SeekParty
2
- class SeekPartyQuery
2
+ class SeekPartyQueryBuilder
3
3
 
4
4
  attr_accessor :params,
5
- :queries
5
+ :sp_query
6
6
 
7
7
  def initialize(params)
8
- self.params = params
9
- self.queries = ({})
8
+ @params = params
9
+ @sp_query = SPQuery.new(params: params)
10
10
  end
11
11
 
12
- def build_query(attributes)
12
+ def build_query(sp_attributes)
13
13
  return unless params
14
14
 
15
- build_base_queries(attributes)
16
- build_final_query
15
+ build_base_queries(sp_attributes)
16
+
17
+ @sp_query.build_final_query
17
18
  end
18
19
 
19
20
  private
20
21
 
21
22
  def build_subquery_string(attribute, attribute_deep)
22
23
  if params[:search].present?
23
- queries[attribute] << " AND #{cast_according_to_adapter(attribute_deep)} = "\
24
- "'#{params[attribute_deep.to_sym].to_s.downcase}'"
24
+ @sp_query.add_attribute_query(attribute, " AND #{build_equals_query(attribute_deep)}")
25
25
  else
26
- queries[attribute_deep] = "#{cast_according_to_adapter(attribute_deep)} = "\
27
- "'#{params[attribute_deep.to_sym].to_s.downcase}'"
26
+ @sp_query.set_attribute_query(attribute_deep, build_equals_query(attribute_deep))
28
27
  end
29
28
  end
30
29
 
31
- def build_base_queries(attributes)
32
- attributes.each do |attribute|
30
+ def build_base_queries(spattribute)
31
+ spattribute.attributes.each do |attribute|
33
32
  if params[:search].present?
34
- queries[attribute] = "#{cast_according_to_adapter(attribute)} LIKE "\
35
- "'%#{params[:search].downcase}%'"
33
+ full_column_name = spattribute.get_full_column_name(attribute)
34
+ cast_column_name = cast_according_to_adapter(full_column_name)
35
+ @sp_query.set_attribute_query(attribute, "#{cast_column_name} LIKE "\
36
+ "'%#{params[:search].downcase}%'")
36
37
  end
37
38
 
38
39
  # If there are other params being used other than :search
39
40
  # it means a where clause is needed.
40
41
  # TODO: Figure out a way to work with date intervals, too.
41
- attributes.each do |attribute_deep|
42
+ spattribute.attributes.each do |attribute_deep|
42
43
  next unless params[attribute_deep.to_sym]
43
44
 
44
45
  build_subquery_string(attribute, attribute_deep)
@@ -46,31 +47,21 @@ module SeekParty
46
47
  end
47
48
  end
48
49
 
49
- def build_final_query
50
- final_query = ''
51
- queries.each do |_key, value|
52
- next unless value
53
-
54
- final_query << if value == queries[queries.keys.first]
55
- value
56
- else
57
- params[:search].present? ? " OR #{value}" : " AND #{value}"
58
- end
59
- end
60
-
61
- final_query
62
- end
63
-
64
50
  def cast_according_to_adapter(column_name)
65
51
  if db_sqlite3?
66
52
  "LOWER(CAST(#{column_name} AS TEXT))"
67
53
  elsif db_postgresql?
68
54
  "LOWER(#{column_name}::VARCHAR)"
69
55
  else
70
- raise "SeekParty does not support #{ActiveRecord::Base.connection.class}"
56
+ raise "SeekParty does not support #{ActiveRecord::Base.connection.class}."
71
57
  end
72
58
  end
73
59
 
60
+ def build_equals_query(attribute)
61
+ "#{cast_according_to_adapter(attribute)} = "\
62
+ "'#{@params[attribute.to_sym].to_s.downcase}'"
63
+ end
64
+
74
65
  def db_sqlite3?
75
66
  ActiveRecord::Base.connection.instance_of? ActiveRecord::ConnectionAdapters::SQLite3Adapter
76
67
  rescue StandardError
@@ -1,3 +1,3 @@
1
1
  module SeekParty
2
- VERSION = '0.0.2'.freeze
2
+ VERSION = '0.0.8'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: seek_party
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charles Washington
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-12-23 00:00:00.000000000 Z
11
+ date: 2020-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -63,6 +63,7 @@ files:
63
63
  - ".gitignore"
64
64
  - ".rakeTasks"
65
65
  - ".rspec"
66
+ - ".travis.yml"
66
67
  - CODE_OF_CONDUCT.md
67
68
  - Gemfile
68
69
  - Gemfile.lock
@@ -72,9 +73,11 @@ files:
72
73
  - bin/console
73
74
  - bin/setup
74
75
  - lib/seek_party.rb
76
+ - lib/seek_party/models/sp_attribute.rb
77
+ - lib/seek_party/models/sp_query.rb
75
78
  - lib/seek_party/seek_party_attribute.rb
76
79
  - lib/seek_party/seek_party_engine.rb
77
- - lib/seek_party/seek_party_query.rb
80
+ - lib/seek_party/seek_party_query_builder.rb
78
81
  - lib/seek_party/version.rb
79
82
  - seek_party.gemspec
80
83
  homepage: https://github.com/caws/seek_party