pliny 0.28.0 → 0.31.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem version](http://img.shields.io/gem/v/pliny.svg)](https://rubygems.org/gems/pliny)
|
4
|
-
[![
|
4
|
+
[![Github Actions CI](https://github.com/interagent/pliny/actions/workflows/ruby.yml/badge.svg)](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: []
|