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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4fdeb50812c8474db1b462be06a13943d901cc06c51044c39fffe9533c2d67d4
4
- data.tar.gz: b70639846466fc0efa37a62fc55551ec4386ccfd0ac3141e041bef88744f4610
3
+ metadata.gz: 03b6f9bac86953d6bef8858e6c4c1f6f94f06073fac8175b9572728ffed5a276
4
+ data.tar.gz: c20333f978e5f8e908b13f6eaf9d37a3dbdb0f10204c1db9a8b5f83b02fbac11
5
5
  SHA512:
6
- metadata.gz: f9e248f7961808f6d862d6b77c8065afc7716cf7861ecb0c508d470819ba012a0a0cd2454352b4854bbaad4cb23f18166ace07cca14035eb514ec71fdf908a96
7
- data.tar.gz: 7b7120d718e286d1ecb7cead9ed19db8a823b4aefe66f1601d824cfc172b46c89c2cbbe2ebdccfaf0e113b8afb862bd2c85d76bf55438ca1dbd5ea89bfc3f28d
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
- [![Build Status](https://travis-ci.org/interagent/pliny.svg?branch=master)](https://travis-ci.org/interagent/pliny)
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
 
@@ -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, "./db/migrate", target)
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
- return unless db.tables.include?(:schema_migrations)
55
- return unless current = db[:schema_migrations].order(Sequel.desc(:filename)).first
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
- migrations = Dir["./db/migrate/*.rb"].map { |f| File.basename(f).to_i }.sort
58
- target = 0 # by default, rollback everything
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, "./db/migrate", target)
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
@@ -8,9 +8,13 @@ module Pliny::Helpers
8
8
 
9
9
  def parse_body_params
10
10
  if request.media_type == "application/json"
11
- p = load_params(MultiJson.decode(request.body.read))
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
- p
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.included(base)
4
- base.send :extend, ClassMethods
3
+ def self.registered(base)
4
+ base.helpers Helpers
5
+ base.set :serializer_class, nil
5
6
  end
6
7
 
7
- def serialize(data, structure = :default)
8
- serializer_class = self.class.serializer_class
8
+ module Helpers
9
+ def serialize(data, structure = :default)
10
+ serializer_class = settings.serializer_class
9
11
 
10
- if serializer_class.nil?
11
- raise <<-eos.strip
12
- No serializer has been specified for this endpoint. Please specify one with
13
- `serializer Serializers::ModelName` in the endpoint.
14
- eos
15
- end
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
- env['pliny.serializer_arity'] = data.respond_to?(:size) ? data.size : 1
19
+ env['pliny.serializer_arity'] = data.respond_to?(:size) ? data.size : 1
18
20
 
19
- start = Time.now
20
- serializer_class.new(structure).serialize(data).tap do
21
- env['pliny.serializer_timing'] = (Time.now - start).to_f
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
- module ClassMethods
26
- # Provide a way to specify endpoint serializer class.
27
- #
28
- # class Endpoints::User < Base
29
- # serializer Serializers::User
30
- #
31
- # get do
32
- # encode serialize(User.all)
33
- # end
34
- # end
35
- def serializer(serializer_class)
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 quote_string(k, v)
126
+ def replace_newlines(v)
127
+ v.gsub("\n", "\\n")
128
+ end
129
+
130
+ def quote_string(v)
127
131
  if !v.include?('"')
128
- %{#{k}="#{v}"}
132
+ %{"#{v}"}
129
133
  elsif !v.include?("'")
130
- %{#{k}='#{v}'}
134
+ %{'#{v}'}
131
135
  else
132
- %{#{k}="#{v.gsub(/"/, '\\"')}"}
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
- if v =~ /\s/
154
- quote_string(k, v)
155
- else
156
- "#{k}=#{v}"
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
@@ -58,9 +58,9 @@ module Pliny::Middleware
58
58
  log_field :timing_serializer, Float
59
59
  end
60
60
 
61
- def initialize(app, emitter:)
61
+ def initialize(app, options)
62
62
  @app = app
63
- @emitter = emitter
63
+ @emitter = options.fetch(:emitter)
64
64
  end
65
65
 
66
66
  def call(env)
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Pliny
2
- VERSION = "0.28.0"
2
+ VERSION = "0.31.0"
3
3
  end
data/lib/template/Gemfile CHANGED
@@ -4,7 +4,7 @@ ruby "2.4.0"
4
4
  gem "multi_json"
5
5
  gem "oj"
6
6
  gem "pg"
7
- gem "pliny", "~> 0.28"
7
+ gem "pliny", "~> 0.31"
8
8
  gem "pry"
9
9
  gem "puma", "~> 3"
10
10
  gem "rack-ssl"
@@ -5,7 +5,7 @@ module Endpoints
5
5
 
6
6
  helpers Pliny::Helpers::Encode
7
7
  helpers Pliny::Helpers::Params
8
- helpers Pliny::Helpers::Serialize
8
+ register Pliny::Helpers::Serialize
9
9
 
10
10
  set :dump_errors, false
11
11
  set :raise_errors, true
@@ -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
@@ -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
- helpers Pliny::Helpers::Serialize
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
- helpers Pliny::Helpers::Serialize
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.28.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: 2020-05-08 00:00:00.000000000 Z
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.19.1
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.19.1
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.17'
277
- - - ">="
276
+ version: '1.0'
277
+ - - "<"
278
278
  - !ruby/object:Gem::Version
279
- version: 0.17.1
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.17'
287
- - - ">="
286
+ version: '1.0'
287
+ - - "<"
288
288
  - !ruby/object:Gem::Version
289
- version: 0.17.1
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.11'
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.11'
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.9'
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.9'
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.0.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: []