pliny 0.28.0 → 0.31.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 +2 -1
- data/lib/pliny/db_support.rb +26 -8
- data/lib/pliny/helpers/params.rb +6 -2
- data/lib/pliny/helpers/serialize.rb +28 -29
- data/lib/pliny/log.rb +12 -9
- data/lib/pliny/middleware/canonical_log_line.rb +2 -2
- data/lib/pliny/tasks/db.rake +7 -0
- data/lib/pliny/version.rb +1 -1
- data/lib/template/Gemfile +1 -1
- data/lib/template/lib/endpoints/base.rb +1 -1
- data/spec/db_support_spec.rb +27 -1
- data/spec/helpers/params_spec.rb +8 -0
- data/spec/helpers/serialize_spec.rb +2 -2
- data/spec/log_spec.rb +6 -0
- metadata +34 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03b6f9bac86953d6bef8858e6c4c1f6f94f06073fac8175b9572728ffed5a276
|
4
|
+
data.tar.gz: c20333f978e5f8e908b13f6eaf9d37a3dbdb0f10204c1db9a8b5f83b02fbac11
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e851ccdd1fb0a3d548fa672d209829e9cd8ecf69023d1c7a2fb6ad0fb84ee1616d2d3b2a761d11ba9c13a989d2fb5176c31d3eb6acf9a02e20c6e7bc4b01386f
|
7
|
+
data.tar.gz: aefb3c02dc44ba282595bb9b2e85dc52e2891cb16ac6395693ab63bd79c603b7c68e9b93dea4c494c1b574e8be308b26a34e40040d4e71e0a74cb9a9f828a207
|
data/README.md
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# Pliny
|
2
2
|
|
3
3
|
[](https://rubygems.org/gems/pliny)
|
4
|
-
[](https://github.com/interagent/pliny/actions)
|
5
|
+
|
5
6
|
|
6
7
|
Pliny helps Ruby developers write and maintain excellent APIs.
|
7
8
|
|
data/lib/pliny/db_support.rb
CHANGED
@@ -46,25 +46,43 @@ module Pliny
|
|
46
46
|
db.run(%{CREATE DATABASE "#{name}"})
|
47
47
|
end
|
48
48
|
|
49
|
-
def migrate(target=nil)
|
50
|
-
Sequel::Migrator.apply(db,
|
49
|
+
def migrate(target = nil)
|
50
|
+
Sequel::Migrator.apply(db, MIGRATION_DIR, target)
|
51
|
+
end
|
52
|
+
|
53
|
+
def version
|
54
|
+
return 0 unless db.table_exists?(:schema_migrations)
|
55
|
+
|
56
|
+
current = db[:schema_migrations].order(Sequel.desc(:filename)).first
|
57
|
+
|
58
|
+
return 0 unless current
|
59
|
+
|
60
|
+
version = current[:filename].match(Sequel::Migrator::MIGRATION_FILE_PATTERN).captures.first
|
61
|
+
version ||= 0
|
62
|
+
Integer(version)
|
51
63
|
end
|
52
64
|
|
53
65
|
def rollback
|
54
|
-
|
55
|
-
return
|
66
|
+
current_version = version
|
67
|
+
return if current_version.zero?
|
68
|
+
|
69
|
+
migrations = Dir["#{MIGRATION_DIR}/*.rb"].map { |f| File.basename(f).to_i }.sort
|
56
70
|
|
57
|
-
|
58
|
-
|
59
|
-
index = migrations.index(current[:filename].to_i)
|
71
|
+
target = 0 # by default, rollback everything
|
72
|
+
index = migrations.index(current_version)
|
60
73
|
if index > 0
|
61
74
|
target = migrations[index - 1]
|
62
75
|
end
|
63
|
-
Sequel::Migrator.apply(db,
|
76
|
+
Sequel::Migrator.apply(db, MIGRATION_DIR, target)
|
64
77
|
end
|
65
78
|
|
66
79
|
def disconnect
|
67
80
|
@db.disconnect
|
68
81
|
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
MIGRATION_DIR = "./db/migrate".freeze
|
86
|
+
private_constant :MIGRATION_DIR
|
69
87
|
end
|
70
88
|
end
|
data/lib/pliny/helpers/params.rb
CHANGED
@@ -8,9 +8,13 @@ module Pliny::Helpers
|
|
8
8
|
|
9
9
|
def parse_body_params
|
10
10
|
if request.media_type == "application/json"
|
11
|
-
|
11
|
+
begin
|
12
|
+
decoded = MultiJson.decode(request.body.read)
|
13
|
+
rescue MultiJson::ParseError => e
|
14
|
+
raise Pliny::Errors::BadRequest, e.message
|
15
|
+
end
|
12
16
|
request.body.rewind
|
13
|
-
|
17
|
+
load_params(decoded)
|
14
18
|
elsif request.form_data?
|
15
19
|
load_params(request.POST)
|
16
20
|
else
|
@@ -1,42 +1,41 @@
|
|
1
1
|
module Pliny::Helpers
|
2
2
|
module Serialize
|
3
|
-
def self.
|
4
|
-
base.
|
3
|
+
def self.registered(base)
|
4
|
+
base.helpers Helpers
|
5
|
+
base.set :serializer_class, nil
|
5
6
|
end
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
module Helpers
|
9
|
+
def serialize(data, structure = :default)
|
10
|
+
serializer_class = settings.serializer_class
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
No serializer has been specified for this endpoint. Please specify one with
|
13
|
-
`serializer Serializers::ModelName` in the endpoint.
|
14
|
-
|
15
|
-
|
12
|
+
if serializer_class.nil?
|
13
|
+
raise <<~eos.strip
|
14
|
+
No serializer has been specified for this endpoint. Please specify one with
|
15
|
+
`serializer Serializers::ModelName` in the endpoint.
|
16
|
+
eos
|
17
|
+
end
|
16
18
|
|
17
|
-
|
19
|
+
env['pliny.serializer_arity'] = data.respond_to?(:size) ? data.size : 1
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
start = Time.now
|
22
|
+
serializer_class.new(structure).serialize(data).tap do
|
23
|
+
env['pliny.serializer_timing'] = (Time.now - start).to_f
|
24
|
+
end
|
22
25
|
end
|
23
26
|
end
|
24
27
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
@serializer_class = serializer_class
|
37
|
-
end
|
38
|
-
|
39
|
-
attr_reader :serializer_class
|
28
|
+
# Provide a way to specify endpoint serializer class.
|
29
|
+
#
|
30
|
+
# class Endpoints::User < Base
|
31
|
+
# serializer Serializers::User
|
32
|
+
#
|
33
|
+
# get do
|
34
|
+
# encode serialize(User.all)
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
def serializer(serializer_class)
|
38
|
+
set :serializer_class, serializer_class
|
40
39
|
end
|
41
40
|
end
|
42
41
|
end
|
data/lib/pliny/log.rb
CHANGED
@@ -123,13 +123,17 @@ module Pliny
|
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
|
-
def
|
126
|
+
def replace_newlines(v)
|
127
|
+
v.gsub("\n", "\\n")
|
128
|
+
end
|
129
|
+
|
130
|
+
def quote_string(v)
|
127
131
|
if !v.include?('"')
|
128
|
-
%{
|
132
|
+
%{"#{v}"}
|
129
133
|
elsif !v.include?("'")
|
130
|
-
%{
|
134
|
+
%{'#{v}'}
|
131
135
|
else
|
132
|
-
%{
|
136
|
+
%{"#{v.gsub(/"/, '\\"')}"}
|
133
137
|
end
|
134
138
|
end
|
135
139
|
|
@@ -150,11 +154,10 @@ module Pliny
|
|
150
154
|
"#{k}=#{v.iso8601}"
|
151
155
|
else
|
152
156
|
v = "#{v}"
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
end
|
157
|
+
v = replace_newlines(v)
|
158
|
+
v = quote_string(v) if v =~ /\s/
|
159
|
+
|
160
|
+
"#{k}=#{v}"
|
158
161
|
end
|
159
162
|
end
|
160
163
|
end
|
data/lib/pliny/tasks/db.rake
CHANGED
@@ -8,6 +8,13 @@ begin
|
|
8
8
|
require "pliny/db_support"
|
9
9
|
|
10
10
|
namespace :db do
|
11
|
+
desc "Get current schema version"
|
12
|
+
task :version do
|
13
|
+
Pliny::DbSupport.run(database_urls.first, $stdout) do |helper|
|
14
|
+
puts "Current version: #{helper.version}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
11
18
|
desc "Run database migrations"
|
12
19
|
task :migrate do
|
13
20
|
next if Dir["./db/migrate/*.rb"].empty?
|
data/lib/pliny/version.rb
CHANGED
data/lib/template/Gemfile
CHANGED
data/spec/db_support_spec.rb
CHANGED
@@ -2,9 +2,9 @@ require "spec_helper"
|
|
2
2
|
require "pliny/db_support"
|
3
3
|
|
4
4
|
describe Pliny::DbSupport do
|
5
|
+
subject(:support) { Pliny::DbSupport.new(url, logger) }
|
5
6
|
let(:url) { ENV["TEST_DATABASE_URL"] }
|
6
7
|
let(:logger) { Logger.new(StringIO.new) }
|
7
|
-
let(:support) { Pliny::DbSupport.new(url, logger) }
|
8
8
|
|
9
9
|
around do |example|
|
10
10
|
Dir.mktmpdir("plinytest-") do |dir|
|
@@ -88,4 +88,30 @@ describe Pliny::DbSupport do
|
|
88
88
|
support.rollback # should noop
|
89
89
|
end
|
90
90
|
end
|
91
|
+
|
92
|
+
describe "#version" do
|
93
|
+
it "is zero if the migrations table doesn't exist" do
|
94
|
+
assert_equal 0, support.version
|
95
|
+
end
|
96
|
+
|
97
|
+
context "with migrations table" do
|
98
|
+
before do
|
99
|
+
DB.create_table(:schema_migrations) do
|
100
|
+
text :filename
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it "is zero if the migrations table is empty" do
|
105
|
+
assert_equal 0, support.version
|
106
|
+
end
|
107
|
+
|
108
|
+
it "is the highest timestamp from a filename in the migrations table" do
|
109
|
+
migrations = DB[:schema_migrations]
|
110
|
+
migrations.insert(filename: "1630551344_latest_change.rb")
|
111
|
+
migrations.insert(filename: "1524000760_earlier_change.rb")
|
112
|
+
|
113
|
+
assert_equal 1630551344, support.version
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
91
117
|
end
|
data/spec/helpers/params_spec.rb
CHANGED
@@ -34,4 +34,12 @@ describe Pliny::Helpers::Params do
|
|
34
34
|
post "/", "<hello>world</hello>", {"CONTENT_TYPE" => "application/xml"}
|
35
35
|
assert_equal "{}", last_response.body
|
36
36
|
end
|
37
|
+
|
38
|
+
it "should throw bad request when receiving invalid json via post" do
|
39
|
+
err = assert_raises(Pliny::Errors::BadRequest) do
|
40
|
+
post "/", "{\"foo\"}", {"CONTENT_TYPE" => "application/json"}
|
41
|
+
end
|
42
|
+
|
43
|
+
assert_match /unexpected token/, err.message
|
44
|
+
end
|
37
45
|
end
|
@@ -4,7 +4,7 @@ describe Pliny::Helpers::Serialize do
|
|
4
4
|
context "without a serializer" do
|
5
5
|
def app
|
6
6
|
Sinatra.new do
|
7
|
-
|
7
|
+
register Pliny::Helpers::Serialize
|
8
8
|
|
9
9
|
get "/" do
|
10
10
|
MultiJson.encode(serialize([]))
|
@@ -29,7 +29,7 @@ describe Pliny::Helpers::Serialize do
|
|
29
29
|
|
30
30
|
def app
|
31
31
|
Sinatra.new do
|
32
|
-
|
32
|
+
register Pliny::Helpers::Serialize
|
33
33
|
|
34
34
|
serializer Serializer
|
35
35
|
|
data/spec/log_spec.rb
CHANGED
@@ -161,6 +161,12 @@ describe Pliny::Log do
|
|
161
161
|
Pliny.log(foo: "string with spaces")
|
162
162
|
end
|
163
163
|
|
164
|
+
it "replaces newlines in strings" do
|
165
|
+
expect(@io).to receive(:print).with("foo=\"string\\nwith newlines\\n\"\n")
|
166
|
+
|
167
|
+
Pliny.log(foo: "string\nwith newlines\n")
|
168
|
+
end
|
169
|
+
|
164
170
|
it "by default interpolates objects into strings" do
|
165
171
|
expect(@io).to receive(:print).with("foo=message\n")
|
166
172
|
expect(@io).to receive(:print).with("foo=42\n")
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pliny
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.31.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandur Leach
|
8
8
|
- Pedro Belo
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2021-09-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -135,22 +135,22 @@ dependencies:
|
|
135
135
|
name: thor
|
136
136
|
requirement: !ruby/object:Gem::Requirement
|
137
137
|
requirements:
|
138
|
-
- - "
|
138
|
+
- - ">="
|
139
139
|
- !ruby/object:Gem::Version
|
140
140
|
version: '0.19'
|
141
|
-
- - "
|
141
|
+
- - "<"
|
142
142
|
- !ruby/object:Gem::Version
|
143
|
-
version: 0
|
143
|
+
version: '2.0'
|
144
144
|
type: :runtime
|
145
145
|
prerelease: false
|
146
146
|
version_requirements: !ruby/object:Gem::Requirement
|
147
147
|
requirements:
|
148
|
-
- - "
|
148
|
+
- - ">="
|
149
149
|
- !ruby/object:Gem::Version
|
150
150
|
version: '0.19'
|
151
|
-
- - "
|
151
|
+
- - "<"
|
152
152
|
- !ruby/object:Gem::Version
|
153
|
-
version: 0
|
153
|
+
version: '2.0'
|
154
154
|
- !ruby/object:Gem::Dependency
|
155
155
|
name: rake
|
156
156
|
requirement: !ruby/object:Gem::Requirement
|
@@ -183,22 +183,22 @@ dependencies:
|
|
183
183
|
name: rspec
|
184
184
|
requirement: !ruby/object:Gem::Requirement
|
185
185
|
requirements:
|
186
|
-
- - ">="
|
187
|
-
- !ruby/object:Gem::Version
|
188
|
-
version: 3.1.0
|
189
186
|
- - "~>"
|
190
187
|
- !ruby/object:Gem::Version
|
191
188
|
version: '3.1'
|
189
|
+
- - ">="
|
190
|
+
- !ruby/object:Gem::Version
|
191
|
+
version: 3.1.0
|
192
192
|
type: :development
|
193
193
|
prerelease: false
|
194
194
|
version_requirements: !ruby/object:Gem::Requirement
|
195
195
|
requirements:
|
196
|
-
- - ">="
|
197
|
-
- !ruby/object:Gem::Version
|
198
|
-
version: 3.1.0
|
199
196
|
- - "~>"
|
200
197
|
- !ruby/object:Gem::Version
|
201
198
|
version: '3.1'
|
199
|
+
- - ">="
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: 3.1.0
|
202
202
|
- !ruby/object:Gem::Dependency
|
203
203
|
name: sinatra-contrib
|
204
204
|
requirement: !ruby/object:Gem::Requirement
|
@@ -273,60 +273,54 @@ dependencies:
|
|
273
273
|
requirements:
|
274
274
|
- - "~>"
|
275
275
|
- !ruby/object:Gem::Version
|
276
|
-
version: '0
|
277
|
-
- - "
|
276
|
+
version: '1.0'
|
277
|
+
- - "<"
|
278
278
|
- !ruby/object:Gem::Version
|
279
|
-
version: 0
|
279
|
+
version: '2.0'
|
280
280
|
type: :development
|
281
281
|
prerelease: false
|
282
282
|
version_requirements: !ruby/object:Gem::Requirement
|
283
283
|
requirements:
|
284
284
|
- - "~>"
|
285
285
|
- !ruby/object:Gem::Version
|
286
|
-
version: '0
|
287
|
-
- - "
|
286
|
+
version: '1.0'
|
287
|
+
- - "<"
|
288
288
|
- !ruby/object:Gem::Version
|
289
|
-
version: 0
|
289
|
+
version: '2.0'
|
290
290
|
- !ruby/object:Gem::Dependency
|
291
291
|
name: rollbar
|
292
292
|
requirement: !ruby/object:Gem::Requirement
|
293
293
|
requirements:
|
294
|
-
- - ">="
|
295
|
-
- !ruby/object:Gem::Version
|
296
|
-
version: 2.11.0
|
297
294
|
- - "~>"
|
298
295
|
- !ruby/object:Gem::Version
|
299
|
-
version: '2
|
296
|
+
version: '3.2'
|
300
297
|
type: :development
|
301
298
|
prerelease: false
|
302
299
|
version_requirements: !ruby/object:Gem::Requirement
|
303
300
|
requirements:
|
304
|
-
- - ">="
|
305
|
-
- !ruby/object:Gem::Version
|
306
|
-
version: 2.11.0
|
307
301
|
- - "~>"
|
308
302
|
- !ruby/object:Gem::Version
|
309
|
-
version: '2
|
303
|
+
version: '3.2'
|
310
304
|
- !ruby/object:Gem::Dependency
|
311
305
|
name: sequel
|
312
306
|
requirement: !ruby/object:Gem::Requirement
|
313
307
|
requirements:
|
314
|
-
- - ">="
|
315
|
-
- !ruby/object:Gem::Version
|
316
|
-
version: 4.9.0
|
317
308
|
- - "~>"
|
318
309
|
- !ruby/object:Gem::Version
|
319
|
-
version: '4
|
310
|
+
version: '5.4'
|
311
|
+
- - "<"
|
312
|
+
- !ruby/object:Gem::Version
|
313
|
+
version: '6.0'
|
320
314
|
type: :development
|
321
315
|
prerelease: false
|
322
316
|
version_requirements: !ruby/object:Gem::Requirement
|
323
317
|
requirements:
|
324
|
-
- - ">="
|
325
|
-
- !ruby/object:Gem::Version
|
326
|
-
version: 4.9.0
|
327
318
|
- - "~>"
|
328
319
|
- !ruby/object:Gem::Version
|
329
|
-
version: '4
|
320
|
+
version: '5.4'
|
321
|
+
- - "<"
|
322
|
+
- !ruby/object:Gem::Version
|
323
|
+
version: '6.0'
|
330
324
|
- !ruby/object:Gem::Dependency
|
331
325
|
name: rubocop
|
332
326
|
requirement: !ruby/object:Gem::Requirement
|
@@ -503,7 +497,7 @@ homepage: https://github.com/interagent/pliny
|
|
503
497
|
licenses:
|
504
498
|
- MIT
|
505
499
|
metadata: {}
|
506
|
-
post_install_message:
|
500
|
+
post_install_message:
|
507
501
|
rdoc_options: []
|
508
502
|
require_paths:
|
509
503
|
- lib
|
@@ -518,8 +512,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
518
512
|
- !ruby/object:Gem::Version
|
519
513
|
version: '0'
|
520
514
|
requirements: []
|
521
|
-
rubygems_version: 3.
|
522
|
-
signing_key:
|
515
|
+
rubygems_version: 3.1.6
|
516
|
+
signing_key:
|
523
517
|
specification_version: 4
|
524
518
|
summary: Basic tooling to support API apps in Sinatra
|
525
519
|
test_files: []
|