json_apiable 0.3 → 0.4
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 +4 -4
- data/.rubocop.yml +39 -0
- data/Gemfile.lock +1 -1
- data/README.md +75 -3
- data/lib/json_apiable.rb +6 -1
- data/lib/json_apiable/base_filter.rb +24 -0
- data/lib/json_apiable/configuration.rb +3 -1
- data/lib/json_apiable/core_extensions.rb +3 -1
- data/lib/json_apiable/errors.rb +3 -1
- data/lib/json_apiable/filter_matchers.rb +67 -0
- data/lib/json_apiable/filter_parser.rb +72 -0
- data/lib/json_apiable/json_apiable.rb +17 -8
- data/lib/json_apiable/pagination_parser.rb +10 -9
- data/lib/json_apiable/params_parser.rb +7 -3
- data/lib/json_apiable/renderers.rb +3 -1
- data/lib/json_apiable/version.rb +3 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87003258543205a662a1a5963258ad69746fee6b5813a52a35cb604c7481488a
|
4
|
+
data.tar.gz: 13bc1aaeb033f6200a165f3b4d2878fd01a6478b0aa8c4348c455ea912929dfc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b0a0a5be9cf7c2b43cd4a8cdb3a6cb9b68064cc5c97735c620e215a15cde00655243a8442b35d11a72c63664a3dce7e44d89abf444711e5ec5adf80941eaabb
|
7
|
+
data.tar.gz: 9968c847fbabe70821f12dc4ab991ae6ff1d3f1a197a9daae016e427a624a39b5e88ff18f15e8906b78e4d408b466c703103afd7de12acb5aa8548c5f92b77a2
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.4
|
3
|
+
Exclude:
|
4
|
+
- 'db/**/*'
|
5
|
+
- 'bin/**/*'
|
6
|
+
- 'config/**/*'
|
7
|
+
- 'spec/**/*'
|
8
|
+
- 'json_apiable.gemspec'
|
9
|
+
- 'Gemfile'
|
10
|
+
- 'Rakefile'
|
11
|
+
|
12
|
+
Metrics:
|
13
|
+
Enabled: false
|
14
|
+
|
15
|
+
Naming/AccessorMethodName:
|
16
|
+
Enabled: false
|
17
|
+
|
18
|
+
Style/PercentLiteralDelimiters:
|
19
|
+
Enabled: false
|
20
|
+
|
21
|
+
Style/HashSyntax:
|
22
|
+
Enabled: false
|
23
|
+
|
24
|
+
Style/Documentation:
|
25
|
+
Enabled: false
|
26
|
+
|
27
|
+
Style/StringLiterals:
|
28
|
+
Enabled: false
|
29
|
+
|
30
|
+
Style/ClassAndModuleChildren:
|
31
|
+
Enabled: false
|
32
|
+
|
33
|
+
Style/SymbolArray:
|
34
|
+
Enabled: false
|
35
|
+
|
36
|
+
Layout/DotPosition:
|
37
|
+
EnforcedStyle: trailing
|
38
|
+
|
39
|
+
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
# JsonApiable
|
2
|
+
[](https://codeclimate.com/github/mikemarsian/json_apiable/maintainability)
|
3
|
+
[](https://badge.fury.io/rb/json_apiable)
|
2
4
|
|
3
5
|
JsonApiable is a Ruby module that makes it easier for Rails API controllers to handle JSON:API parameter and relationship parsing,
|
4
6
|
strong parameter validation, returning well-structured errors and more - all in a Rails-friendly way.
|
@@ -54,7 +56,7 @@ class API::PostsController < API::BaseController
|
|
54
56
|
# GET /v1/posts
|
55
57
|
def index
|
56
58
|
# pass page and include info to your logic
|
57
|
-
posts = GetPostsService.call(
|
59
|
+
posts = GetPostsService.call(jsonapi_page_hash, jsonapi_include_array)
|
58
60
|
# some other gem, such as fast_jsonapi is assumed to produce the json:api output
|
59
61
|
render json: posts
|
60
62
|
end
|
@@ -97,7 +99,7 @@ class API::PostsController < API::BaseController
|
|
97
99
|
#
|
98
100
|
# }
|
99
101
|
@post.update_attributes!(jsonapi_assign_params)
|
100
|
-
render json: @
|
102
|
+
render json: @post
|
101
103
|
end
|
102
104
|
|
103
105
|
def create
|
@@ -111,7 +113,7 @@ class API::PostsController < API::BaseController
|
|
111
113
|
@comments_hash = jsonapi_exclude_relationship(:comments)
|
112
114
|
do_some_logc_with_excluded_params
|
113
115
|
# jsonapi_assign_params wouldn't include 'author' attribute and 'comments' relationship
|
114
|
-
|
116
|
+
Post.create!(jsonapi_assign_params)
|
115
117
|
end
|
116
118
|
|
117
119
|
protected
|
@@ -132,6 +134,76 @@ class API::PostsController < API::BaseController
|
|
132
134
|
|
133
135
|
end
|
134
136
|
````
|
137
|
+
### Filters
|
138
|
+
JsonApiable supports parsing filter requests in the form `example.com/v1/posts?filter[status]=draft` and returning errors
|
139
|
+
in case provided filter keys or values do not adhere to what you define:
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
# Create filter class that inherits from JsonApiable::BaseFilter
|
143
|
+
class API::PostFilter < JsonApiable::BaseFilter
|
144
|
+
# Declare which filter keys are supported
|
145
|
+
def self.jsonapi_allowed_filters
|
146
|
+
{
|
147
|
+
# For each key, declare what values are allowed. The supported value matchers include:
|
148
|
+
# 1) Array of values
|
149
|
+
# example.com/v1/posts?filter[status]=draft,published
|
150
|
+
status: Post.statuses.keys,
|
151
|
+
|
152
|
+
# 2) DateTime matcher - proc that checks that the provided value is a valid DateTime
|
153
|
+
# example.com/v1/posts?filter[published_at]='2001-02-03T04:05:06+03:00'
|
154
|
+
published_at: datetime_matcher,
|
155
|
+
|
156
|
+
# 3) Boolean matcher - proc that checks that the provided value is a boolean (true/t/1 for True, false/f/0 for False)
|
157
|
+
# example.com/v1/posts?filter[subscribers_only]=true
|
158
|
+
subscribers_only: boolean_matcher,
|
159
|
+
|
160
|
+
# 4) ID matcher - proc that checks that the provided ids exist for given model
|
161
|
+
# example.com/v1/posts?filter[ids]=10893,14596
|
162
|
+
ids: ids_matcher(Post),
|
163
|
+
|
164
|
+
# Of course, you can also implement your own matchers. For example:
|
165
|
+
reviewed_at: recent_datetime_matcher
|
166
|
+
}
|
167
|
+
end
|
168
|
+
|
169
|
+
# Example of custom filter value matcher
|
170
|
+
def self.recent_datetime_matcher
|
171
|
+
proc do |value|
|
172
|
+
datetime = Time.zone.parse(value)
|
173
|
+
datetime.present? && datetime > 10.years.ago && datetime < 2.years.from_now
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
```
|
178
|
+
Now set the filter for actions which should support filtering:
|
179
|
+
```ruby
|
180
|
+
class API::PostsController < API::BaseController
|
181
|
+
before_action -> { set_jsonapi_filter(API::PostFilter) }, only: %i[index search]
|
182
|
+
end
|
183
|
+
|
184
|
+
```
|
185
|
+
And you are good to go!
|
186
|
+
|
187
|
+
Incidentally, PostFilter class is also a good place to implement your filter logic:
|
188
|
+
```ruby
|
189
|
+
class API::PostFilter < JsonApiable::BaseFilter
|
190
|
+
# The following methods are available to a filter class instance:
|
191
|
+
# jsonapi_collection - collection on which to execute filtering
|
192
|
+
# jsonapi_filter_hash - a filter query hash, e.g. { 'status' => ['draft', 'published'], 'published_at' => '2001-02-03T04:05:06+03:00' }
|
193
|
+
def call
|
194
|
+
jsonapi_collection.where(status: jsonapi_filter_hash[:status])
|
195
|
+
end
|
196
|
+
end
|
197
|
+
```
|
198
|
+
Now you can call filter posts collection in your controller:
|
199
|
+
```ruby
|
200
|
+
posts = GetPosts.call
|
201
|
+
# jsonapi_filter_class - API::PostFilter in our example
|
202
|
+
# jsonapi_filter_hash - a filter query hash, e.g. { 'status' => ['draft', 'published'] }
|
203
|
+
filtered_posts = jsonapi_filter_class.new(posts, jsonapi_filter_hash).call
|
204
|
+
```
|
205
|
+
|
206
|
+
|
135
207
|
### Configuration
|
136
208
|
Add an initializer to your app with the following config block:
|
137
209
|
```ruby
|
data/lib/json_apiable.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support/all'
|
2
4
|
require "json_apiable/version"
|
3
5
|
require "json_apiable/core_extensions"
|
@@ -6,7 +8,10 @@ require 'json_apiable/renderers'
|
|
6
8
|
require 'json_apiable/errors'
|
7
9
|
require 'json_apiable/params_parser'
|
8
10
|
require 'json_apiable/pagination_parser'
|
11
|
+
require 'json_apiable/filter_parser'
|
12
|
+
require 'json_apiable/filter_matchers'
|
13
|
+
require 'json_apiable/base_filter'
|
9
14
|
require 'json_apiable/json_apiable'
|
10
15
|
|
11
16
|
String.include CoreExtensions::String
|
12
|
-
Mime::Type.register JsonApiable::JSONAPI_CONTENT_TYPE, :json_api
|
17
|
+
Mime::Type.register JsonApiable::JSONAPI_CONTENT_TYPE, :json_api
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JsonApiable
|
4
|
+
# Base class for Filters
|
5
|
+
class BaseFilter
|
6
|
+
extend JsonApiable::FilterMatchers
|
7
|
+
|
8
|
+
attr_reader :jsonapi_collection, :jsonapi_filter_hash, :current_user
|
9
|
+
|
10
|
+
protected
|
11
|
+
|
12
|
+
def initialize(a_collection, a_filter_hash, current_user)
|
13
|
+
@jsonapi_collection = a_collection
|
14
|
+
@jsonapi_filter_hash = a_filter_hash
|
15
|
+
@current_user = current_user
|
16
|
+
end
|
17
|
+
|
18
|
+
class << self
|
19
|
+
def jsonapi_allowed_filters
|
20
|
+
{}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module JsonApiable
|
2
4
|
class Configuration
|
3
5
|
attr_accessor :valid_query_params, :supported_media_type_proc, :not_found_exception_class, :page_size
|
@@ -29,4 +31,4 @@ module JsonApiable
|
|
29
31
|
@not_found_exception_class = klass
|
30
32
|
end
|
31
33
|
end
|
32
|
-
end
|
34
|
+
end
|
data/lib/json_apiable/errors.rb
CHANGED
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JsonApiable
|
4
|
+
module FilterMatchers
|
5
|
+
def matches?(allowed, given)
|
6
|
+
given.all? do |value|
|
7
|
+
allowed.is_a?(Proc) ? allowed.call(value) : allowed.include?(value)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module_function :matches?
|
12
|
+
|
13
|
+
# returns true for boolean values, false for any other
|
14
|
+
def boolean_matcher
|
15
|
+
proc do |value|
|
16
|
+
handle_error(value) do
|
17
|
+
if true_matcher.call(value) || (value == false || value =~ /^(false|f|0)$/i)
|
18
|
+
true
|
19
|
+
else
|
20
|
+
false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# returns true for true values, false for any other
|
27
|
+
def true_matcher
|
28
|
+
proc do |value|
|
29
|
+
handle_error(value) do
|
30
|
+
if value == true || value =~ /^(true|t|1)$/i
|
31
|
+
true
|
32
|
+
else
|
33
|
+
false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# returns true if the value is a valid date or datetime
|
40
|
+
def datetime_matcher
|
41
|
+
proc do |value|
|
42
|
+
handle_error(value) do
|
43
|
+
datetime = value.in_time_zone(Time.zone)
|
44
|
+
datetime.present?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# returns true if the value is a an array of existing ids of the given model
|
50
|
+
def ids_matcher(model)
|
51
|
+
proc do |value|
|
52
|
+
handle_error(value) do
|
53
|
+
given_ids = value.split(',')
|
54
|
+
found_records = model.where(id: given_ids)
|
55
|
+
|
56
|
+
given_ids.count == found_records.count
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def handle_error(value)
|
62
|
+
yield
|
63
|
+
rescue ArgumentError => e
|
64
|
+
raise ArgumentError, "#{value}: #{e.message}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JsonApiable
|
4
|
+
class FilterParser
|
5
|
+
def self.parse_filters!(jsonapi_build_params, filter_class)
|
6
|
+
FilterParser.new(jsonapi_build_params[:filter], filter_class).parse!
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :filter_param, :filter_class
|
10
|
+
|
11
|
+
def initialize(filter_param, filter_class)
|
12
|
+
@filter_param = filter_param
|
13
|
+
@filter_class = filter_class
|
14
|
+
end
|
15
|
+
|
16
|
+
# Support filtering in the form of example.com/v1/posts?filter[status]=draft,published
|
17
|
+
def parse!
|
18
|
+
raise_invalid_filter_class unless valid_filter_class?
|
19
|
+
|
20
|
+
filter_hash = ActiveSupport::HashWithIndifferentAccess.new
|
21
|
+
if valid_filter_query?
|
22
|
+
filter_param.keys.each do |k|
|
23
|
+
if valid_filter_key?(k)
|
24
|
+
# support notation ?filter[param]=value1,value2,value3&...
|
25
|
+
requested = filter_param[k].split(',')
|
26
|
+
allowed_values = allowed_filter_keys[k]
|
27
|
+
raise_invalid_filter_value(k) unless FilterMatchers.matches?(allowed_values, requested)
|
28
|
+
|
29
|
+
filter_hash[k] = requested
|
30
|
+
else
|
31
|
+
raise_invalid_filter_value(k)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
elsif filter_param.present?
|
35
|
+
raise ArgumentError, 'filter'
|
36
|
+
end
|
37
|
+
filter_hash
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def raise_argument_error(message)
|
43
|
+
raise ArgumentError, message
|
44
|
+
end
|
45
|
+
|
46
|
+
def raise_invalid_filter_value(k)
|
47
|
+
prefix = "filter[#{k}]"
|
48
|
+
msg = filter_param[k].present? ? "#{prefix}=#{filter_param[k]}" : prefix
|
49
|
+
raise_argument_error(msg)
|
50
|
+
end
|
51
|
+
|
52
|
+
def raise_invalid_filter_class
|
53
|
+
raise_argument_error("#{filter_class} does not specify jsonapi_allowed_filters")
|
54
|
+
end
|
55
|
+
|
56
|
+
def valid_filter_class?
|
57
|
+
filter_class.respond_to?(:jsonapi_allowed_filters)
|
58
|
+
end
|
59
|
+
|
60
|
+
def valid_filter_query?
|
61
|
+
filter_param.present? && (filter_param.is_a?(Hash) || filter_param.is_a?(ActionController::Parameters))
|
62
|
+
end
|
63
|
+
|
64
|
+
def valid_filter_key?(k)
|
65
|
+
allowed_filter_keys.key?(k) && filter_param[k].present?
|
66
|
+
end
|
67
|
+
|
68
|
+
def allowed_filter_keys
|
69
|
+
filter_class.jsonapi_allowed_filters.with_indifferent_access
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module JsonApiable
|
2
4
|
extend ActiveSupport::Concern
|
3
5
|
include Errors
|
@@ -5,8 +7,8 @@ module JsonApiable
|
|
5
7
|
|
6
8
|
JSONAPI_CONTENT_TYPE = 'application/vnd.api+json'
|
7
9
|
|
8
|
-
attr_reader :
|
9
|
-
:jsonapi_exclude_attributes, :jsonapi_exclude_relationships
|
10
|
+
attr_reader :jsonapi_page_hash, :jsonapi_include_array, :jsonapi_filter_hash, :jsonapi_filter_class, :jsonapi_build_params,
|
11
|
+
:jsonapi_assign_params, :jsonapi_default_page_size, :jsonapi_exclude_attributes, :jsonapi_exclude_relationships
|
10
12
|
|
11
13
|
included do
|
12
14
|
before_action :ensure_jsonapi_content_type
|
@@ -25,7 +27,6 @@ module JsonApiable
|
|
25
27
|
rescue_from JsonApiable.configuration.not_found_exception_class, with: :respond_to_not_found
|
26
28
|
end
|
27
29
|
|
28
|
-
|
29
30
|
class << self
|
30
31
|
attr_writer :configuration
|
31
32
|
end
|
@@ -63,8 +64,11 @@ module JsonApiable
|
|
63
64
|
end
|
64
65
|
|
65
66
|
def jsonapi_relationship_attribute(relationship, attribute)
|
66
|
-
[:id, :type].include?(attribute.to_sym)
|
67
|
-
|
67
|
+
if [:id, :type].include?(attribute.to_sym)
|
68
|
+
jsonapi_relationship_data(relationship)&.dig(attribute)
|
69
|
+
else
|
70
|
+
jsonapi_relationship_data(relationship)&.dig(:attributes, attribute)
|
71
|
+
end
|
68
72
|
end
|
69
73
|
|
70
74
|
def jsonapi_assign_params
|
@@ -126,19 +130,24 @@ module JsonApiable
|
|
126
130
|
end
|
127
131
|
end
|
128
132
|
|
133
|
+
def set_jsonapi_filter(filter_class)
|
134
|
+
@jsonapi_filter_class = filter_class
|
135
|
+
@jsonapi_filter_hash = FilterParser.parse_filters!(jsonapi_build_params, filter_class)
|
136
|
+
end
|
137
|
+
|
129
138
|
def set_jsonapi_content_type
|
130
139
|
response.headers['Content-Type'] = JSONAPI_CONTENT_TYPE
|
131
140
|
end
|
132
141
|
|
133
142
|
def parse_jsonapi_pagination
|
134
|
-
@
|
143
|
+
@jsonapi_page_hash = PaginationParser.parse_pagination!(query_params, jsonapi_default_page_size)
|
135
144
|
end
|
136
145
|
|
137
146
|
def parse_jsonapi_include
|
138
|
-
@
|
147
|
+
@jsonapi_include_array = query_params[:include].presence&.gsub(/ /, '')&.split(',')&.map(&:to_sym).to_a
|
139
148
|
end
|
140
149
|
|
141
150
|
def query_params
|
142
151
|
request.query_parameters
|
143
152
|
end
|
144
|
-
end
|
153
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module JsonApiable
|
2
4
|
class PaginationParser
|
3
|
-
|
4
5
|
def self.parse_pagination!(query_params, default_page_size)
|
5
6
|
PaginationParser.new(query_params[:page], query_params[:no_pagination], default_page_size).parse!
|
6
7
|
end
|
@@ -15,7 +16,7 @@ module JsonApiable
|
|
15
16
|
|
16
17
|
def parse!
|
17
18
|
if no_pagination
|
18
|
-
|
19
|
+
jsonapi_page_hash = nil
|
19
20
|
elsif invalid_page_param?
|
20
21
|
raise ArgumentError, 'page'
|
21
22
|
elsif invalid_page_number?
|
@@ -23,14 +24,14 @@ module JsonApiable
|
|
23
24
|
elsif invalid_page_size?
|
24
25
|
raise ArgumentError, 'page[size]'
|
25
26
|
else
|
26
|
-
|
27
|
+
jsonapi_page_hash = page_param.presence.to_h.with_indifferent_access
|
27
28
|
# convert values to integers
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
jsonapi_page_hash = jsonapi_page_hash.merge(jsonapi_page_hash) { |_, v| v.to_i } if jsonapi_page_hash.present?
|
30
|
+
jsonapi_page_hash = { number: Configuration::DEFAULT_PAGE_NUMBER, size: default_page_size } if jsonapi_page_hash.blank?
|
31
|
+
jsonapi_page_hash[:number] = Configuration::DEFAULT_PAGE_NUMBER if jsonapi_page_hash[:number].blank?
|
32
|
+
jsonapi_page_hash[:size] = default_page_size if jsonapi_page_hash[:size].blank?
|
32
33
|
end
|
33
|
-
|
34
|
+
jsonapi_page_hash
|
34
35
|
end
|
35
36
|
|
36
37
|
private
|
@@ -56,4 +57,4 @@ module JsonApiable
|
|
56
57
|
number > Configuration::MAX_PAGE_SIZE || number.zero? || number.negative?
|
57
58
|
end
|
58
59
|
end
|
59
|
-
end
|
60
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module JsonApiable
|
2
4
|
class ParamsParser
|
3
5
|
class DataParams
|
@@ -39,7 +41,9 @@ module JsonApiable
|
|
39
41
|
end
|
40
42
|
|
41
43
|
def self.build_relationships_hash(relationships, excluded_relationships, request)
|
42
|
-
attr_hash = {}
|
44
|
+
attr_hash = {}
|
45
|
+
ids_array = []
|
46
|
+
ids_key = nil
|
43
47
|
|
44
48
|
relationships&.each_pair do |key, data_hash|
|
45
49
|
next if excluded_relationships&.include?(key.to_sym)
|
@@ -72,7 +76,7 @@ module JsonApiable
|
|
72
76
|
end
|
73
77
|
|
74
78
|
def self.hashify(allowed_relationships)
|
75
|
-
allowed_relationships.map{|rel| { rel => {}}}
|
79
|
+
allowed_relationships.map { |rel| { rel => {} } }
|
76
80
|
end
|
77
81
|
end
|
78
|
-
end
|
82
|
+
end
|
data/lib/json_apiable/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json_apiable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.4'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Polischuk
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -201,6 +201,7 @@ extra_rdoc_files: []
|
|
201
201
|
files:
|
202
202
|
- ".gitignore"
|
203
203
|
- ".rspec"
|
204
|
+
- ".rubocop.yml"
|
204
205
|
- ".travis.yml"
|
205
206
|
- Gemfile
|
206
207
|
- Gemfile.lock
|
@@ -211,9 +212,12 @@ files:
|
|
211
212
|
- bin/setup
|
212
213
|
- json_apiable.gemspec
|
213
214
|
- lib/json_apiable.rb
|
215
|
+
- lib/json_apiable/base_filter.rb
|
214
216
|
- lib/json_apiable/configuration.rb
|
215
217
|
- lib/json_apiable/core_extensions.rb
|
216
218
|
- lib/json_apiable/errors.rb
|
219
|
+
- lib/json_apiable/filter_matchers.rb
|
220
|
+
- lib/json_apiable/filter_parser.rb
|
217
221
|
- lib/json_apiable/json_apiable.rb
|
218
222
|
- lib/json_apiable/pagination_parser.rb
|
219
223
|
- lib/json_apiable/params_parser.rb
|