jsonapi-scopes 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d0e74cff9d6b5917c86fc154f8046fd388a843c451fa66b22d09332c6cc67a53
4
+ data.tar.gz: 76f8158ff9f126a0ef1ab84ee4bec8f82716ebf1c9dd5ec43894891db3be472e
5
+ SHA512:
6
+ metadata.gz: 5555c208f5518bc0a8502e50eacf248f6f16844414838d6b43bcf156dabcdd3fe98d5600cea66b8bc1dbf794c6a194ff4052fd04932a85f244a989ee6598ffaa
7
+ data.tar.gz: dc3a47eedd3fcb472b702172f297a850156bd4e1e912fc4cb6d2db6b518397e39ee90ce26c5e8322c2a26b0bbb60487304f84b009523ce069f273c36daa9ec6c
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+
2
+ MIT License
3
+
4
+ Copyright (c) 2019 Guillaume Briday
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,96 @@
1
+ [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/guillaumebriday)
2
+
3
+ # Jsonapi::Scopes
4
+ This gem provides an easy way to use a filter query parameter from the [jsonapi specification](https://jsonapi.org/recommendations/#filtering).
5
+
6
+ ## Installation
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'jsonapi-scopes', git: 'https://github.com/guillaumebriday/jsonapi-scopes.git'
11
+ ```
12
+
13
+ And then execute:
14
+ ```bash
15
+ $ bundle
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ ### Filter
21
+ The gem add a `filter` method to define public scopes.
22
+ It acts as a regular scope.
23
+
24
+ ```ruby
25
+ class Contact < ActiveRecord::Base
26
+ include Jsonapi::Filter
27
+
28
+ # Respond to `apply_filter`
29
+ filter :first_name, ->(value) {
30
+ where(first_name: value)
31
+ }
32
+
33
+ # Do NOT respond to `apply_filter`
34
+ scope :last_name, ->(value) {
35
+ where(last_name: value)
36
+ }
37
+ end
38
+ ```
39
+
40
+ You can use `apply_filter` in your controller to use the scopes defined with the previous `filter` method :
41
+
42
+ ```ruby
43
+ class ContactsController < ApplicationController
44
+ def index
45
+ @contacts = Contact.apply_filter(params)
46
+ end
47
+ end
48
+ ```
49
+
50
+ Then you can hit `/contacts?filter[first_name]=Bruce` to filter contacts where the last name exactly match `Bruce`.
51
+
52
+ But `/contacts?filter[last_name]=Wayne` will be completely ignored.
53
+
54
+ ### Sorting
55
+ The gem add `default_sort` and `sortable_fields` methods to control sort options. **Both are optional** and can be overriding in controllers.
56
+
57
+ ```ruby
58
+ class Contact < ActiveRecord::Base
59
+ include Jsonapi::Sort
60
+
61
+ sortable_fields :lastname, :firstname # List of allowed attributes
62
+ default_sort lastname: :desc, firstname: :asc # default hash with attributes and directions
63
+ end
64
+ ```
65
+
66
+ You can use `apply_sort` in your controller :
67
+
68
+ ```ruby
69
+ class ContactsController < ApplicationController
70
+ def index
71
+ @contacts = Contact.apply_sort(params)
72
+ end
73
+ end
74
+ ```
75
+
76
+ `apply_sort` accepts a second parameter to override data set with `sortable_fields` and `default_sort` for a specific controller.
77
+ ```ruby
78
+ class ContactsController < ApplicationController
79
+ def index
80
+ @contacts = Contact.apply_sort(params, allowed: :full_name, default: { full_name: :desc })
81
+ # Or @contacts = Contact.apply_sort(params, allowed: [:lastname, :full_name], default: { full_name: :desc })
82
+ end
83
+ end
84
+ ```
85
+
86
+ Then you can hit `/contacts?sort=lastname` to sort contacts by lastname.
87
+
88
+ Or use negative sort `/contacts?sort=-firstname` to sort by firstname in `desc` direction.
89
+
90
+ You can even combine multiple sort `/contacts?sort=lastname,-firstname`
91
+
92
+ ## Contributing
93
+ Do not hesitate to contribute to the project by adapting or adding features ! Bug reports or pull requests are welcome.
94
+
95
+ ## License
96
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError
6
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ require 'rdoc/task'
10
+
11
+ RDoc::Task.new(:rdoc) do |rdoc|
12
+ rdoc.rdoc_dir = 'rdoc'
13
+ rdoc.title = 'Jsonapi::Scopes'
14
+ rdoc.options << '--line-numbers'
15
+ rdoc.rdoc_files.include('README.md')
16
+ rdoc.rdoc_files.include('lib/**/*.rb')
17
+ end
18
+
19
+ require 'bundler/gem_tasks'
20
+
21
+ require 'rake/testtask'
22
+
23
+ Rake::TestTask.new(:test) do |t|
24
+ t.libs << 'test'
25
+ t.pattern = 'test/**/*_test.rb'
26
+ t.verbose = false
27
+ end
28
+
29
+ task default: :test
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jsonapi/scopes/filters'
4
+ require 'jsonapi/scopes/sorts'
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jsonapi
4
+ module Filter
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ @filters ||= []
9
+ end
10
+
11
+ module ClassMethods
12
+ attr_reader :filters
13
+
14
+ def filter(name, *args)
15
+ scope(name, *args)
16
+ @filters << name
17
+ end
18
+
19
+ def apply_filter(params)
20
+ records = self
21
+ filtering_params = params.dig(:filter) || {}
22
+
23
+ filtering_params.each do |key, value|
24
+ records = records.public_send(key, value) if @filters.include?(key.to_sym)
25
+ end
26
+
27
+ records
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jsonapi
4
+ module Sort
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ @sortable_fields ||= []
9
+ @default_sort ||= {}
10
+ end
11
+
12
+ module ClassMethods
13
+ def default_sort(sort)
14
+ @default_sort = sort
15
+ end
16
+
17
+ def sortable_fields(*fields)
18
+ @sortable_fields = fields
19
+ end
20
+
21
+ def apply_sort(params, options = { allowed: [], default: {} })
22
+ fields = params.dig(:sort)
23
+
24
+ allowed_fields = [options[:allowed]].flatten.presence || @sortable_fields
25
+ allowed_fields = allowed_fields.map(&:to_sym)
26
+
27
+ default_order = options[:default].presence || @default_sort
28
+ default_order = default_order.transform_keys(&:to_sym)
29
+
30
+ ordered_fields = convert_to_ordered_hash(fields)
31
+ filtered_fields = ordered_fields.select { |key, _| allowed_fields.include?(key) }
32
+
33
+ order = filtered_fields.presence || default_order
34
+
35
+ self.order(order)
36
+ end
37
+
38
+ private
39
+
40
+ def convert_to_ordered_hash(fields)
41
+ fields = fields.to_s.split(',').map(&:squish)
42
+
43
+ fields.each_with_object({}) do |field, hash|
44
+ if field.start_with?('-')
45
+ field = field[1..-1]
46
+ hash[field] = :desc
47
+ else
48
+ hash[field] = :asc
49
+ end
50
+ end.transform_keys(&:to_sym)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jsonapi
4
+ module Scopes
5
+ VERSION = '0.1.0'
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jsonapi-scopes
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Guillaume Briday
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-05-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sqlite3
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description:
42
+ email:
43
+ - guillaumebriday@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - LICENSE
49
+ - README.md
50
+ - Rakefile
51
+ - lib/jsonapi/scopes.rb
52
+ - lib/jsonapi/scopes/filters.rb
53
+ - lib/jsonapi/scopes/sorts.rb
54
+ - lib/jsonapi/scopes/version.rb
55
+ homepage: https://github.com/guillaumebriday/jsonapi-scopes
56
+ licenses:
57
+ - MIT
58
+ metadata: {}
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubygems_version: 3.0.3
75
+ signing_key:
76
+ specification_version: 4
77
+ summary: A gem to use filters and scopes for JSON:API.
78
+ test_files: []