munson 0.2.0 → 0.3.0
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/README.md +234 -246
- data/bin/console +2 -10
- data/lib/munson/agent.rb +35 -69
- data/lib/munson/attribute.rb +76 -0
- data/lib/munson/client.rb +43 -0
- data/lib/munson/collection.rb +19 -1
- data/lib/munson/connection.rb +61 -14
- data/lib/munson/document.rb +140 -0
- data/lib/munson/key_formatter.rb +87 -0
- data/lib/munson/middleware/encode_json_api.rb +10 -2
- data/lib/munson/middleware/json_parser.rb +11 -5
- data/lib/munson/query.rb +218 -0
- data/lib/munson/resource.rb +174 -20
- data/lib/munson/response_mapper.rb +92 -32
- data/lib/munson/version.rb +1 -1
- data/lib/munson.rb +30 -22
- metadata +7 -7
- data/lib/munson/model.rb +0 -15
- data/lib/munson/paginator/offset_paginator.rb +0 -45
- data/lib/munson/paginator/paged_paginator.rb +0 -47
- data/lib/munson/paginator.rb +0 -6
- data/lib/munson/query_builder.rb +0 -226
data/lib/munson.rb
CHANGED
@@ -2,25 +2,46 @@ require 'json'
|
|
2
2
|
require 'cgi'
|
3
3
|
require 'faraday'
|
4
4
|
require 'faraday_middleware'
|
5
|
+
require 'bigdecimal'
|
5
6
|
|
6
7
|
require "munson/version"
|
7
|
-
|
8
|
-
require
|
9
|
-
require "munson/
|
10
|
-
|
8
|
+
require 'munson/agent'
|
9
|
+
require 'munson/attribute'
|
10
|
+
require "munson/client"
|
11
11
|
require 'munson/collection'
|
12
|
-
require 'munson/paginator'
|
13
|
-
require 'munson/response_mapper'
|
14
|
-
require 'munson/query_builder'
|
15
12
|
require 'munson/connection'
|
16
|
-
require 'munson/
|
13
|
+
require 'munson/document'
|
14
|
+
require 'munson/key_formatter'
|
15
|
+
require "munson/middleware/encode_json_api"
|
16
|
+
require "munson/middleware/json_parser"
|
17
17
|
require 'munson/resource'
|
18
|
+
require 'munson/response_mapper'
|
19
|
+
require 'munson/query'
|
18
20
|
|
19
21
|
module Munson
|
22
|
+
class Error < StandardError; end;
|
23
|
+
class UnsupportedSortDirectionError < Munson::Error; end;
|
24
|
+
class UnrecognizedKeyFormatter < Munson::Error; end;
|
25
|
+
class RelationshipNotIncludedError < Munson::Error; end;
|
26
|
+
class RelationshipNotFound < Munson::Error; end;
|
27
|
+
class ClientNotSet < Munson::Error; end;
|
20
28
|
@registered_types = {}
|
21
|
-
@registered_paginators = {}
|
22
29
|
|
23
30
|
class << self
|
31
|
+
# Transforms a JSONAPI hash into a Munson::Document, Munson::Resource, or arbitrary class
|
32
|
+
# @param [Munson::Document,Hash] document to transform
|
33
|
+
# @return [Munson::Document,~Munson::Resource]
|
34
|
+
def factory(document)
|
35
|
+
document = Munson::Document.new(document) if document.is_a?(Hash)
|
36
|
+
klass = Munson.lookup_type(document.type)
|
37
|
+
|
38
|
+
if klass && klass.respond_to?(:munson_initializer)
|
39
|
+
klass.munson_initializer(document)
|
40
|
+
else
|
41
|
+
document
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
24
45
|
# Configure the default connection.
|
25
46
|
#
|
26
47
|
# @param [Hash] opts {Munson::Connection} configuration options
|
@@ -52,14 +73,6 @@ module Munson
|
|
52
73
|
@registered_types[type.to_sym] = klass
|
53
74
|
end
|
54
75
|
|
55
|
-
def register_paginator(name, klass)
|
56
|
-
@registered_paginators[name.to_sym] = klass
|
57
|
-
end
|
58
|
-
|
59
|
-
def lookup_paginator(name)
|
60
|
-
@registered_paginators[name.to_sym]
|
61
|
-
end
|
62
|
-
|
63
76
|
# Lookup a class by JSON Spec type name
|
64
77
|
#
|
65
78
|
# @param [#to_sym] type JSON Spec type
|
@@ -67,10 +80,5 @@ module Munson
|
|
67
80
|
def lookup_type(type)
|
68
81
|
@registered_types[type.to_sym]
|
69
82
|
end
|
70
|
-
|
71
|
-
# @private
|
72
|
-
def flush_types!
|
73
|
-
@registered_types = {}
|
74
|
-
end
|
75
83
|
end
|
76
84
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: munson
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cory O'Daniel
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-07-
|
11
|
+
date: 2016-07-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -182,15 +182,15 @@ files:
|
|
182
182
|
- bin/setup
|
183
183
|
- lib/munson.rb
|
184
184
|
- lib/munson/agent.rb
|
185
|
+
- lib/munson/attribute.rb
|
186
|
+
- lib/munson/client.rb
|
185
187
|
- lib/munson/collection.rb
|
186
188
|
- lib/munson/connection.rb
|
189
|
+
- lib/munson/document.rb
|
190
|
+
- lib/munson/key_formatter.rb
|
187
191
|
- lib/munson/middleware/encode_json_api.rb
|
188
192
|
- lib/munson/middleware/json_parser.rb
|
189
|
-
- lib/munson/
|
190
|
-
- lib/munson/paginator.rb
|
191
|
-
- lib/munson/paginator/offset_paginator.rb
|
192
|
-
- lib/munson/paginator/paged_paginator.rb
|
193
|
-
- lib/munson/query_builder.rb
|
193
|
+
- lib/munson/query.rb
|
194
194
|
- lib/munson/resource.rb
|
195
195
|
- lib/munson/response_mapper.rb
|
196
196
|
- lib/munson/version.rb
|
data/lib/munson/model.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# module Munson
|
2
|
-
# module Model
|
3
|
-
# extend ActiveSupport::Concern
|
4
|
-
#
|
5
|
-
# included do
|
6
|
-
# self.include Munson::Resource
|
7
|
-
# end
|
8
|
-
#
|
9
|
-
# class_methods do
|
10
|
-
# def has_many(*);end;
|
11
|
-
# def has_one(*);end;
|
12
|
-
# def belongs_to(*);end;
|
13
|
-
# end
|
14
|
-
# end
|
15
|
-
# end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
module Munson
|
2
|
-
module Paginator
|
3
|
-
class OffsetPaginator
|
4
|
-
def initialize(options={})
|
5
|
-
@max_limit = options[:max]
|
6
|
-
@default_limit = options[:default]
|
7
|
-
end
|
8
|
-
|
9
|
-
def set(opts={})
|
10
|
-
limit(opts[:limit]) if opts[:limit]
|
11
|
-
offset(opts[:offset]) if opts[:offset]
|
12
|
-
end
|
13
|
-
|
14
|
-
def to_params
|
15
|
-
{
|
16
|
-
page: {
|
17
|
-
limit: @limit || @default_limit || 10,
|
18
|
-
offset: @offset
|
19
|
-
}.select { |_, value| !value.nil? }
|
20
|
-
}
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
# Set limit of resources per page
|
26
|
-
#
|
27
|
-
# @param [Fixnum] num number of resources per page
|
28
|
-
def limit(num)
|
29
|
-
if @max_limit && num > @max_limit
|
30
|
-
@limit = @max_limit
|
31
|
-
else
|
32
|
-
@limit = num
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# Set offset
|
37
|
-
#
|
38
|
-
# @param [Fixnum] num pages to offset
|
39
|
-
def offset(num)
|
40
|
-
@offset = num
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
Munson.register_paginator(:offset, Munson::Paginator::OffsetPaginator)
|
@@ -1,47 +0,0 @@
|
|
1
|
-
module Munson
|
2
|
-
module Paginator
|
3
|
-
class PagedPaginator
|
4
|
-
def initialize(options={})
|
5
|
-
@max_size = options[:max]
|
6
|
-
@default_size = options[:default]
|
7
|
-
end
|
8
|
-
|
9
|
-
def set(opts={})
|
10
|
-
number(opts[:number]) if opts[:number]
|
11
|
-
size(opts[:size]) if opts[:size]
|
12
|
-
end
|
13
|
-
|
14
|
-
def to_params
|
15
|
-
{
|
16
|
-
page: {
|
17
|
-
size: @size || @default_size || 10,
|
18
|
-
number: @number
|
19
|
-
}.select { |_, value| !value.nil? }
|
20
|
-
}
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
# Set number of resources per page
|
26
|
-
#
|
27
|
-
# @param [Fixnum] num number of resources per page
|
28
|
-
def size(num)
|
29
|
-
if @max_size && num > @max_size
|
30
|
-
@size = @max_size
|
31
|
-
else
|
32
|
-
@size = num
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# Set page number
|
37
|
-
#
|
38
|
-
# @param [Fixnum] num page number
|
39
|
-
def number(num)
|
40
|
-
@number = num
|
41
|
-
end
|
42
|
-
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
Munson.register_paginator(:paged, Munson::Paginator::PagedPaginator)
|
data/lib/munson/paginator.rb
DELETED
data/lib/munson/query_builder.rb
DELETED
@@ -1,226 +0,0 @@
|
|
1
|
-
module Munson
|
2
|
-
class QueryBuilder
|
3
|
-
attr_reader :query
|
4
|
-
attr_reader :paginator
|
5
|
-
attr_reader :agent
|
6
|
-
class UnsupportedSortDirectionError < StandardError; end;
|
7
|
-
class PaginatorNotSet < StandardError; end;
|
8
|
-
class AgentNotSet < StandardError; end;
|
9
|
-
|
10
|
-
# Description of method
|
11
|
-
#
|
12
|
-
# @param [Class] paginator: nil instantiated paginator
|
13
|
-
# @param [Class] agent: nil instantiated agent to use for fetching results
|
14
|
-
# @return [Type] description of returned object
|
15
|
-
def initialize(paginator: nil, agent: nil)
|
16
|
-
@paginator = paginator
|
17
|
-
@agent = agent
|
18
|
-
|
19
|
-
@query = {
|
20
|
-
include: [],
|
21
|
-
fields: [],
|
22
|
-
filter: [],
|
23
|
-
sort: []
|
24
|
-
}
|
25
|
-
end
|
26
|
-
|
27
|
-
# @return [String] query as a query string
|
28
|
-
def to_query_string
|
29
|
-
Faraday::Utils.build_nested_query(to_params)
|
30
|
-
end
|
31
|
-
|
32
|
-
def to_s
|
33
|
-
to_query_string
|
34
|
-
end
|
35
|
-
|
36
|
-
def to_params
|
37
|
-
str = {}
|
38
|
-
str[:filter] = filter_to_query_value unless @query[:filter].empty?
|
39
|
-
str[:fields] = fields_to_query_value unless @query[:fields].empty?
|
40
|
-
str[:include] = includes_to_query_value unless @query[:include].empty?
|
41
|
-
str[:sort] = sort_to_query_value unless @query[:sort].empty?
|
42
|
-
|
43
|
-
str.merge!(paginator.to_params) if paginator
|
44
|
-
|
45
|
-
str
|
46
|
-
end
|
47
|
-
|
48
|
-
# Fetches resources using {Munson::Agent}
|
49
|
-
#
|
50
|
-
# @return [Array] Array of resources
|
51
|
-
def fetch
|
52
|
-
if @agent
|
53
|
-
response = @agent.get(params: to_params)
|
54
|
-
resources = ResponseMapper.new(response).resources
|
55
|
-
Collection.new(resources)
|
56
|
-
else
|
57
|
-
raise AgentNotSet, "Agent was not set. QueryBuilder#new(agent:)"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def paging?
|
62
|
-
!!paginator
|
63
|
-
end
|
64
|
-
|
65
|
-
# Paginator proxy
|
66
|
-
#
|
67
|
-
# @return [Class,nil] paginator if set
|
68
|
-
def page(opts={})
|
69
|
-
if paging?
|
70
|
-
paginator.set(opts)
|
71
|
-
self
|
72
|
-
else
|
73
|
-
raise PaginatorNotSet, "Paginator was not set. QueryBuilder#new(paginator:)"
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
# Chainably include related resources.
|
78
|
-
#
|
79
|
-
# @example including a resource
|
80
|
-
# Munson::QueryBuilder.new.includes(:user)
|
81
|
-
#
|
82
|
-
# @example including a related resource
|
83
|
-
# Munson::QueryBuilder.new.includes("user.addresses")
|
84
|
-
#
|
85
|
-
# @example including multiple resources
|
86
|
-
# Munson::QueryBuilder.new.includes("user.addresses", "user.images")
|
87
|
-
#
|
88
|
-
# @param [Array<String,Symbol>] *args relationships to include
|
89
|
-
# @return [Munson::QueryBuilder] self for chaining queries
|
90
|
-
#
|
91
|
-
# @see http://jsonapi.org/format/#fetching-includes JSON API Including Relationships
|
92
|
-
def includes(*args)
|
93
|
-
@query[:include] += args
|
94
|
-
self
|
95
|
-
end
|
96
|
-
|
97
|
-
# Chainably sort results
|
98
|
-
# @note Default order is ascending
|
99
|
-
#
|
100
|
-
# @example sorting by a single field
|
101
|
-
# Munsun::QueryBuilder.new.sort(:created_at)
|
102
|
-
#
|
103
|
-
# @example sorting by a multiple fields
|
104
|
-
# Munsun::QueryBuilder.new.sort(:created_at, :age)
|
105
|
-
#
|
106
|
-
# @example specifying sort direction
|
107
|
-
# Munsun::QueryBuilder.new.sort(:created_at, age: :desc)
|
108
|
-
#
|
109
|
-
# @example specifying sort direction
|
110
|
-
# Munsun::QueryBuilder.new.sort(score: :desc, :created_at)
|
111
|
-
#
|
112
|
-
# @param [Hash<Symbol,Symbol>, Symbol] *args fields to sort by
|
113
|
-
# @return [Munson::QueryBuilder] self for chaining queries
|
114
|
-
#
|
115
|
-
# @see http://jsonapi.org/format/#fetching-sorting JSON API Sorting Spec
|
116
|
-
def sort(*args)
|
117
|
-
validate_sort_args(args.select{|arg| arg.is_a?(Hash)})
|
118
|
-
@query[:sort] += args
|
119
|
-
self
|
120
|
-
end
|
121
|
-
|
122
|
-
# Hash resouce_name: [array of attribs]
|
123
|
-
def fields(*args)
|
124
|
-
@query[:fields] += args
|
125
|
-
self
|
126
|
-
end
|
127
|
-
|
128
|
-
def filter(*args)
|
129
|
-
@query[:filter] += args
|
130
|
-
self
|
131
|
-
end
|
132
|
-
|
133
|
-
def self.includes(*args)
|
134
|
-
new.includes(*args)
|
135
|
-
end
|
136
|
-
|
137
|
-
def self.sort(*args)
|
138
|
-
new.sort(*args)
|
139
|
-
end
|
140
|
-
|
141
|
-
def self.fields(*args)
|
142
|
-
new.fields(*args)
|
143
|
-
end
|
144
|
-
|
145
|
-
def self.filter(*args)
|
146
|
-
new.filter(*args)
|
147
|
-
end
|
148
|
-
|
149
|
-
protected
|
150
|
-
|
151
|
-
def sort_to_query_value
|
152
|
-
@query[:sort].map{|item|
|
153
|
-
if item.is_a?(Hash)
|
154
|
-
item.to_a.map{|name,dir|
|
155
|
-
dir.to_sym == :desc ? "-#{name}" : name.to_s
|
156
|
-
}
|
157
|
-
else
|
158
|
-
item.to_s
|
159
|
-
end
|
160
|
-
}.join(',')
|
161
|
-
end
|
162
|
-
|
163
|
-
def fields_to_query_value
|
164
|
-
@query[:fields].inject({}) do |acc, hash_arg|
|
165
|
-
hash_arg.each do |k,v|
|
166
|
-
acc[k] ||= []
|
167
|
-
v.is_a?(Array) ?
|
168
|
-
acc[k] += v :
|
169
|
-
acc[k] << v
|
170
|
-
|
171
|
-
acc[k].map(&:to_s).uniq!
|
172
|
-
end
|
173
|
-
|
174
|
-
acc
|
175
|
-
end.map { |k, v| [k, v.join(',')] }.to_h
|
176
|
-
end
|
177
|
-
|
178
|
-
def includes_to_query_value
|
179
|
-
@query[:include].map(&:to_s).sort.join(',')
|
180
|
-
end
|
181
|
-
|
182
|
-
# Since the filter query param's format isn't specified in the [spec](http://jsonapi.org/format/#fetching-filtering)
|
183
|
-
# this implemenation uses (JSONAPI::Resource's implementation](https://github.com/cerebris/jsonapi-resources#filters)
|
184
|
-
#
|
185
|
-
# To override, implement your own CustomQueryBuilder inheriting from {Munson::QueryBuilder}
|
186
|
-
# {Munson::Agent} takes a QueryBuilder class to use. This method could be overriden in your custom class
|
187
|
-
#
|
188
|
-
# @example Custom Query Builder
|
189
|
-
# class MyBuilder < Munson::QueryBuilder
|
190
|
-
# def filter_to_query_value
|
191
|
-
# # ... your fancier logic
|
192
|
-
# end
|
193
|
-
# end
|
194
|
-
#
|
195
|
-
# class Article
|
196
|
-
# def self.munson
|
197
|
-
# return @munson if @munson
|
198
|
-
# @munson = Munson::Agent.new(
|
199
|
-
# query_builder: MyBuilder
|
200
|
-
# path: 'products'
|
201
|
-
# )
|
202
|
-
# end
|
203
|
-
# end
|
204
|
-
#
|
205
|
-
def filter_to_query_value
|
206
|
-
@query[:filter].reduce({}) do |acc, hash_arg|
|
207
|
-
hash_arg.each do |k,v|
|
208
|
-
acc[k] ||= []
|
209
|
-
v.is_a?(Array) ? acc[k] += v : acc[k] << v
|
210
|
-
acc[k].uniq!
|
211
|
-
end
|
212
|
-
acc
|
213
|
-
end.map { |k, v| [k, v.join(',')] }.to_h
|
214
|
-
end
|
215
|
-
|
216
|
-
def validate_sort_args(hashes)
|
217
|
-
hashes.each do |hash|
|
218
|
-
hash.each do |k,v|
|
219
|
-
if !%i(desc asc).include?(v.to_sym)
|
220
|
-
raise UnsupportedSortDirectionError, "Unknown direction '#{v}'. Use :asc or :desc"
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|