search_object 1.1.1 → 1.1.2

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
  SHA1:
3
- metadata.gz: f8e073aa014abee0b28d16becee73863464fd881
4
- data.tar.gz: 3bc4009abae195732fc8d20e77e4c42b8f080c13
3
+ metadata.gz: dfd3ff677d11a1e11bed9b477960df1e286a162d
4
+ data.tar.gz: 60cabe41c79f8596ce290c52cfe88317fb28fd00
5
5
  SHA512:
6
- metadata.gz: b39a094a23b0721756303b3988e12acded95e775bd649b15ea9a7a0f0941d79cf0362d78a46ba56154273ed93c7bb8c1a18788255313a5ed290abf9505346a52
7
- data.tar.gz: 7ae9c659722f908b487d44fd099a5e4aca80465624cf5849412384cef82c3a2632d930480fac40814c5b3c2c911ee129bf88b03302e3908acf9184b2d371cd2b
6
+ metadata.gz: 331c98690d13135b9a3fb0427c9a6df1139785af9df0c53755fddd1c30db4b93c48a38f094156829f4d6a419eea9ba1b381f9fcd105dabcb06f04a6a936acaf4
7
+ data.tar.gz: c9d14a709fd31ad3cdafdda6ce8028edd80da3549ae6e0c0e96e4f9afa64384cf3805a258f46776a684ed19c605f7d69e472e96864d4ac30cb874ebad03f7c92
data/.rubocop.yml CHANGED
@@ -26,6 +26,14 @@ Style/EachWithObject:
26
26
  Style/CollectionMethods:
27
27
  Enabled: false
28
28
 
29
- # Disables "Example has too many lines"
29
+ # Disables "Block has too many lines."
30
+ Metrics/BlockLength:
31
+ Enabled: false
32
+
33
+ # Disables "Example has too many lines."
30
34
  RSpec/ExampleLength:
31
35
  Enabled: false
36
+
37
+ # Disables "Too many expectations."
38
+ RSpec/MultipleExpectations:
39
+ Enabled: false
data/.travis.yml CHANGED
@@ -1,8 +1,7 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.0
4
- - 2.1
5
3
  - 2.2
4
+ - 2.3
6
5
  script:
7
6
  - bundle exec rubocop
8
7
  - bundle exec rspec spec
data/CHANGELOG.md CHANGED
@@ -1,12 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## Version 1.1.2
4
+
5
+ * __[fix]__ Fix a warning due to Rails 5 `ActionController::Parameters` not being a Hash (@rstankov)
6
+ * __[fix]__ Ensure `sort_by` prefixes with table_name. (@andreasklinger)
7
+
3
8
  ## Version 1.1.1
4
9
 
5
- * Fix a bug in inheriting search objects
10
+ * __[fix]__ Fix a bug in inheriting search objects (@avlazarov)
6
11
 
7
12
  ## Version 1.1
8
13
 
9
- * Search objects now can be inherited
14
+ * __[feature]__ Search objects now can be inherited (@rstankov)
10
15
 
11
16
  ```ruby
12
17
  class BaseSearch
@@ -20,7 +25,7 @@
20
25
  end
21
26
  ```
22
27
 
23
- * Using instance method for straight dispatch
28
+ * __[feature]__ Use instance method for straight dispatch (@gsamokovarov)
24
29
 
25
30
  ```ruby
26
31
  class ProductSearch
@@ -28,31 +33,25 @@
28
33
 
29
34
  scope { Product.all }
30
35
 
31
- option :name
32
- option :category_name
36
+ option :date, with: :parse_dates
33
37
 
34
- attr_reader :page
35
-
36
- def initialize(filters = {}, page = 0)
37
- super filters
38
- @page = page.to_i.abc
39
- end
38
+ private
40
39
 
41
- def fetch_results
42
- super.paginate page: @page
40
+ def parse_dates(scope, value)
41
+ # some "magic" method to parse dates
43
42
  end
44
43
  end
45
44
  ```
46
45
 
47
46
  ## Version 1.0
48
47
 
49
- * Added min_per_page and max_per_page to paging plugin
48
+ * __[feature]__ Added min_per_page and max_per_page to paging plugin (@rstankov)
50
49
 
51
- * Default paging behaves more like 'kaminari' and 'will_paginate' by treating 1 page as 0 index (__backward incompatible__)
50
+ * __[change]__ Default paging behaves more like 'kaminari' and 'will_paginate' by treating 1 page as 0 index (__backward incompatible__) (@rstankov)
52
51
 
53
- * Raise `SearchObject::MissingScopeError` when no scope is provided
52
+ * __[feature]__ Raise `SearchObject::MissingScopeError` when no scope is provided (@rstankov)
54
53
 
55
- * Replace position arguments with Hash of options (__backward incompatible__)
54
+ * __[change]__ Replace position arguments with Hash of options (__backward incompatible__) (@rstankov)
56
55
 
57
56
  ```diff
58
57
  - Search.new params[:f], params[:page]
@@ -61,10 +60,10 @@
61
60
 
62
61
  ## Version 0.2
63
62
 
64
- * Added `.results` shortcut for `new(*arg).results`
63
+ * __[feature]__ Added `.results` shortcut for `new(*arg).results` (@rstankov)
65
64
 
66
- * Fix wrong limit and offset in default paging
65
+ * __[fix]__ Fix wrong limit and offset in default paging (@rstankov)
67
66
 
68
67
  ## Version 0.1
69
68
 
70
- * Initial release
69
+ * Initial release (@rstankov)
data/README.md CHANGED
@@ -293,7 +293,7 @@ class ProductSearch
293
293
 
294
294
  def initialize(filters = {}, page = 0)
295
295
  super filters
296
- @page = page.to_i.abc
296
+ @page = page.to_i.abs
297
297
  end
298
298
 
299
299
  def fetch_results
data/example/Gemfile CHANGED
@@ -1,11 +1,12 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'rails', '4.2.0'
4
- gem 'sqlite3'
3
+ gem 'rails', '5.0.1'
4
+
5
+ gem 'bootstrap-sass'
6
+ gem 'jquery-rails'
7
+ gem 'rspec-rails'
5
8
  gem 'sass-rails', '~> 5.0.0'
6
9
  gem 'slim'
7
- gem 'jquery-rails'
8
- gem 'bootstrap-sass'
10
+ gem 'sqlite3'
9
11
  gem 'will_paginate'
10
12
  gem 'will_paginate-bootstrap'
11
- gem 'rspec-rails'
@@ -13,8 +13,8 @@ Example::Application.configure do
13
13
  config.eager_load = false
14
14
 
15
15
  # Configure static asset server for tests with Cache-Control for performance.
16
- config.serve_static_files = true
17
- config.static_cache_control = "public, max-age=3600"
16
+ config.public_file_server.enabled = true
17
+ config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' }
18
18
 
19
19
  # Show full error reports and disable caching.
20
20
  config.consider_all_requests_local = true
@@ -74,10 +74,10 @@ describe PostSearch do
74
74
  end
75
75
 
76
76
  it 'can sort by views count' do
77
- post_3 = create views_count: 3
78
- post_2 = create views_count: 2
79
- post_1 = create views_count: 1
77
+ post3 = create views_count: 3
78
+ post2 = create views_count: 2
79
+ post1 = create views_count: 1
80
80
 
81
- expect_search(sort: 'views_count').to eq [post_3, post_2, post_1]
81
+ expect_search(sort: 'views_count').to eq [post3, post2, post1]
82
82
  end
83
83
  end
@@ -1,11 +1,15 @@
1
1
  module SearchObject
2
+ # :api: private
2
3
  module Helper
3
4
  class << self
4
5
  def stringify_keys(hash)
6
+ # Note(rstankov): From Rails 5+ ActionController::Parameters aren't Hash
7
+ # In a lot of cases `stringify_keys` is used on action params
8
+ hash = hash.to_unsafe_h if hash.respond_to? :to_unsafe_h
5
9
  Hash[(hash || {}).map { |k, v| [k.to_s, v] }]
6
10
  end
7
11
 
8
- def select_keys(hash, keys)
12
+ def slice_keys(hash, keys)
9
13
  keys.inject({}) do |memo, key|
10
14
  memo[key] = hash[key] if hash.key? key
11
15
  memo
@@ -5,7 +5,7 @@ module SearchObject
5
5
  base.extend ClassMethods
6
6
  base.instance_eval do
7
7
  option :sort do |scope, _|
8
- scope.order "#{sort_attribute} #{sort_direction}"
8
+ scope.order sort_attribute => sort_direction
9
9
  end
10
10
  end
11
11
  end
@@ -10,7 +10,7 @@ module SearchObject
10
10
  private
11
11
 
12
12
  def apply_paging(scope)
13
- scope.paginate per_page: per_page, page: page == 0 ? nil : page
13
+ scope.paginate per_page: per_page, page: page.zero? ? nil : page
14
14
  end
15
15
  end
16
16
  end
@@ -6,7 +6,7 @@ module SearchObject
6
6
  def build_for(config, options)
7
7
  scope = options.fetch(:scope) { config[:scope] && config[:scope].call }
8
8
  filters = Helper.stringify_keys(options.fetch(:filters, {}))
9
- params = config[:defaults].merge Helper.select_keys(filters, config[:actions].keys)
9
+ params = config[:defaults].merge Helper.slice_keys(filters, config[:actions].keys)
10
10
 
11
11
  raise MissingScopeError unless scope
12
12
 
@@ -1,3 +1,3 @@
1
1
  module SearchObject
2
- VERSION = '1.1.1'.freeze
2
+ VERSION = '1.1.2'.freeze
3
3
  end
@@ -18,15 +18,16 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.3"
21
+ spec.add_development_dependency "bundler", "~> 1.13"
22
22
  spec.add_development_dependency "rake"
23
- spec.add_development_dependency 'rspec', '~> 2.14'
24
- spec.add_development_dependency 'rspec-mocks', '>= 2.12.3'
25
- spec.add_development_dependency 'activerecord', '>= 3.0.0'
23
+ spec.add_development_dependency 'rspec', '~> 3.5'
24
+ spec.add_development_dependency 'rspec-mocks', '~> 3.5'
25
+ spec.add_development_dependency 'activerecord', '~> 5.0'
26
+ spec.add_development_dependency 'actionpack', '~> 5.0'
26
27
  spec.add_development_dependency 'sqlite3'
27
28
  spec.add_development_dependency 'coveralls'
28
29
  spec.add_development_dependency 'will_paginate'
29
30
  spec.add_development_dependency 'kaminari'
30
- spec.add_development_dependency 'rubocop', '0.40.0'
31
- spec.add_development_dependency 'rubocop-rspec', '1.5.0'
31
+ spec.add_development_dependency 'rubocop', '0.46.0'
32
+ spec.add_development_dependency 'rubocop-rspec', '1.8.0'
32
33
  end
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'action_controller'
2
3
 
3
4
  module SearchObject
4
5
  describe Helper do
@@ -7,16 +8,22 @@ module SearchObject
7
8
  hash = Helper.stringify_keys a: 1, b: nil, c: false
8
9
  expect(hash).to eq 'a' => 1, 'b' => nil, 'c' => false
9
10
  end
11
+
12
+ it 'converts ActionController::Parameters to hash' do
13
+ params = ::ActionController::Parameters.new a: 1, b: nil, c: false
14
+ hash = Helper.stringify_keys params
15
+ expect(hash).to eq 'a' => 1, 'b' => nil, 'c' => false
16
+ end
10
17
  end
11
18
 
12
- describe '.select_keys' do
19
+ describe '.slice_keys' do
13
20
  it 'selects only given keys' do
14
- hash = Helper.select_keys({ a: 1, b: 2, c: 3 }, [:a, :b])
21
+ hash = Helper.slice_keys({ a: 1, b: 2, c: 3 }, [:a, :b])
15
22
  expect(hash).to eq a: 1, b: 2
16
23
  end
17
24
 
18
25
  it 'ignores not existing keys' do
19
- hash = Helper.select_keys({}, [:a, :b])
26
+ hash = Helper.slice_keys({}, [:a, :b])
20
27
  expect(hash).to eq({})
21
28
  end
22
29
  end
@@ -25,9 +25,7 @@ module SearchObject
25
25
  describe ExtendedModel do
26
26
  include ActiveModel::Lint::Tests
27
27
 
28
- before do
29
- @model = subject
30
- end
28
+ let(:model) { subject }
31
29
 
32
30
  def assert(condition, message = nil)
33
31
  expect(condition).to be_truthy, message
@@ -9,10 +9,11 @@ module SearchObject
9
9
 
10
10
  scope { Product.all }
11
11
 
12
- sort_by :name, :price
12
+ sort_by :name, :price, :created_at
13
13
 
14
14
  option :name
15
15
  option :price
16
+ option(:category) { |scope, _| scope.joins(:category) }
16
17
  end
17
18
  end
18
19
 
@@ -48,6 +49,18 @@ module SearchObject
48
49
  search = search_with_sort 'invalid attribute'
49
50
  expect { search.results.to_a }.not_to raise_error
50
51
  end
52
+
53
+ it 'can handle renames of sorting in joins' do
54
+ older_category = Category.create! name: 'older'
55
+ newer_category = Category.create! name: 'newer'
56
+
57
+ product_of_newer_category = Product.create! name: 'older product', category: newer_category
58
+ product_of_older_category = Product.create! name: 'newer product', category: older_category
59
+
60
+ search = search_with_sort 'created_at desc', category: ''
61
+
62
+ expect(search.results.map(&:name)).to eq [product_of_older_category.name, product_of_newer_category.name]
63
+ end
51
64
  end
52
65
 
53
66
  describe '#sort?' do
@@ -9,12 +9,22 @@ ActiveRecord::Schema.define do
9
9
 
10
10
  create_table :products, force: true do |t|
11
11
  t.string :name
12
- t.string :category_name
12
+ t.integer :category_id
13
13
  t.integer :price
14
14
 
15
15
  t.timestamps null: true
16
16
  end
17
+
18
+ create_table :categories, force: true do |t|
19
+ t.string :name
20
+
21
+ t.timestamps null: true
22
+ end
17
23
  end
18
24
 
19
25
  class Product < ActiveRecord::Base
26
+ belongs_to :category
27
+ end
28
+
29
+ class Category < ActiveRecord::Base
20
30
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: search_object
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Radoslav Stankov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-26 00:00:00.000000000 Z
11
+ date: 2016-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.3'
19
+ version: '1.13'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.3'
26
+ version: '1.13'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,42 +44,56 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '2.14'
47
+ version: '3.5'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '2.14'
54
+ version: '3.5'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec-mocks
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 2.12.3
61
+ version: '3.5'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 2.12.3
68
+ version: '3.5'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: activerecord
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 3.0.0
75
+ version: '5.0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '5.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: actionpack
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '5.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
81
95
  - !ruby/object:Gem::Version
82
- version: 3.0.0
96
+ version: '5.0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: sqlite3
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -142,28 +156,28 @@ dependencies:
142
156
  requirements:
143
157
  - - '='
144
158
  - !ruby/object:Gem::Version
145
- version: 0.40.0
159
+ version: 0.46.0
146
160
  type: :development
147
161
  prerelease: false
148
162
  version_requirements: !ruby/object:Gem::Requirement
149
163
  requirements:
150
164
  - - '='
151
165
  - !ruby/object:Gem::Version
152
- version: 0.40.0
166
+ version: 0.46.0
153
167
  - !ruby/object:Gem::Dependency
154
168
  name: rubocop-rspec
155
169
  requirement: !ruby/object:Gem::Requirement
156
170
  requirements:
157
171
  - - '='
158
172
  - !ruby/object:Gem::Version
159
- version: 1.5.0
173
+ version: 1.8.0
160
174
  type: :development
161
175
  prerelease: false
162
176
  version_requirements: !ruby/object:Gem::Requirement
163
177
  requirements:
164
178
  - - '='
165
179
  - !ruby/object:Gem::Version
166
- version: 1.5.0
180
+ version: 1.8.0
167
181
  description: Search object DSL
168
182
  email:
169
183
  - rstankov@gmail.com