rack-spec 0.0.3 → 0.0.4

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
  SHA1:
3
- metadata.gz: fa1f5b2caa1ab2a81b5a1d16ab2c2c42061ca322
4
- data.tar.gz: 593e35231041acbdb78ede30ef3b6d05a84e31d3
3
+ metadata.gz: 982ed4f72ecd493a91d0c53fb4bf960b2850a303
4
+ data.tar.gz: f012454fe35d8abf802a7c32fa138ddfedd21d50
5
5
  SHA512:
6
- metadata.gz: 58f77db673d54bbe9c01a31094cfaebdceaee8bc0c25720d5f0029576f3f8548f9dcc7ad7f7b5850be6a226914c7b73d142b9771cd2837a6d3c2e7c2c2bccd32
7
- data.tar.gz: 5fcc86a1e6aad44874f912987dca182a5784d93589691a90b407a34ab78f07c322879d8c1012ed5ca14d2a4b89838cf453b0c699fa6c7e6829d999f13a1fb19a
6
+ metadata.gz: 28e45afcf7f5d03cf4bc764f737e846012e8d1d5c63e7936eada092c117385d05e7152533bba5e3044fab6c6d1b3a808fc19802f511ff22aca8b3594bda21d13
7
+ data.tar.gz: 5a8239586bf0f19227a2d1606bc4a220c4655864157d1afaa9ed7faa69fc1f4e18aa021380bab99c0f9e84a43ecb09866db484e560348e405d3bb94b5b65642b
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ ## v0.0.4
2
+ * Add Rack::Spec::Restful, strongly conventional RESTful API Provider
3
+
1
4
  ## v0.0.3
2
5
  * Add a new constraint: required
3
6
  * More DRY way for validator definition
data/README.md CHANGED
@@ -6,13 +6,19 @@ Define specifications of your Rack application.
6
6
  gem install rack-spec
7
7
  ```
8
8
 
9
- ## Usage
9
+ ## Rack::Spec::Validation
10
+ Rack::Spec::Validation is a rack-middleware and works as a validation layer for your rack-application.
11
+ It loads spec definition (= a pure Hash object in specific format) to validate each request.
12
+ If the request is not valid on your definition, it will raise Rack::Spec::Exceptions::ValidationError.
13
+ Rack::Spec::ExceptionHandler is a utility rack-middleware to rescue validation error and return 400.
14
+
10
15
  ```ruby
11
16
  require "rack"
12
17
  require "rack/spec"
13
18
  require "yaml"
14
19
 
15
- use Rack::Spec, spec: YAML.load_file("spec.yml")
20
+ use Rack::Spec::ExceptionHandler
21
+ use Rack::Spec::Validation, spec: YAML.load_file("spec.yml")
16
22
 
17
23
  run ->(env) do
18
24
  [200, {}, ["OK"]]
@@ -50,6 +56,60 @@ endpoints:
50
56
  type: string
51
57
  minimumLength: 3
52
58
  maximumLength: 10
59
+ required: true
60
+ ```
61
+
62
+ ## Custom Validator
63
+ Custom validator can be defined by inheriting Rack::Spec::Validators::Base.
64
+ The following FwordValidator rejects any parameter starting with "F".
65
+ See [lib/rack/spec/validators](https://github.com/r7kamura/rack-spec/tree/master/lib/rack/spec/validators) for more examples.
66
+
67
+ ```ruby
68
+ # Example:
69
+ #
70
+ # parameters:
71
+ # title:
72
+ # fword: false
73
+ #
74
+ class FwordValidator < Rack::Spec::Validators::Base
75
+ register_as "fword"
76
+
77
+ def valid?
78
+ value.nil? || !value.start_with?("F")
79
+ end
80
+ end
81
+ ```
82
+
83
+ ## Exception Handling
84
+ Replace Rack::Spec::ExceptionHandler to customize error behavior.
85
+
86
+ ```ruby
87
+ use MyExceptionHandler # Rack::Spec::ValidationError must be rescued
88
+ use Rack::Spec::Validation, spec: YAML.load_file("spec.yml")
89
+ ```
90
+
91
+ ## Rack::Spec::Restful
92
+ Rack::Spec::Restful provides strongly conventional RESTful APIs as a rack-middleware.
93
+ It recognizes a preferred instruction from the request method & path, then tries to call it.
94
+
95
+ | verb | path | instruction |
96
+ | ---- | ---- | ---- |
97
+ | GET | /recipes/ | Recipe.index(id) |
98
+ | GET | /recipes/{id} | Recipe.show(id, params) |
99
+ | POST | /recipes/ | Recipe.create(id) |
100
+ | PUT | /recipes/{id} | Recipe.update(id, params) |
101
+ | DELETE | /recipes/{id} | Recipe.destroy(id, params) |
102
+
103
+ ```ruby
104
+ class Recipe
105
+ def self.index(params)
106
+ order(params[:order]).page(params[:page])
107
+ end
108
+
109
+ def self.show(id, params)
110
+ find(id)
111
+ end
112
+ end
53
113
  ```
54
114
 
55
115
  ## Development
data/lib/rack/spec.rb CHANGED
@@ -1,8 +1,10 @@
1
1
  require "rack/builder"
2
2
  require "rack/spec/exception_handler"
3
+ require "rack/spec/exceptions/base"
4
+ require "rack/spec/exceptions/validation_error"
5
+ require "rack/spec/restful"
3
6
  require "rack/spec/spec"
4
7
  require "rack/spec/validation"
5
- require "rack/spec/validation_error"
6
8
  require "rack/spec/validators/base"
7
9
  require "rack/spec/validators/null_validator"
8
10
  require "rack/spec/validator_factory"
@@ -23,6 +25,7 @@ module Rack
23
25
  @app = Rack::Builder.app do
24
26
  use Rack::Spec::ExceptionHandler
25
27
  use Rack::Spec::Validation, options
28
+ use Rack::Spec::Restful, options
26
29
  run app
27
30
  end
28
31
  end
@@ -7,7 +7,7 @@ module Rack
7
7
 
8
8
  def call(env)
9
9
  @app.call(env)
10
- rescue ValidationError => exception
10
+ rescue Exceptions::ValidationError => exception
11
11
  exception.to_rack_response
12
12
  end
13
13
  end
@@ -0,0 +1,8 @@
1
+ module Rack
2
+ class Spec
3
+ module Exceptions
4
+ class Base < StandardError
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,43 @@
1
+ require "json"
2
+
3
+ module Rack
4
+ class Spec
5
+ module Exceptions
6
+ class ValidationError < Base
7
+ def initialize(validator)
8
+ @validator = validator
9
+ end
10
+
11
+ def message
12
+ "Invalid #{key} on `#{constraint_name}` constraint"
13
+ end
14
+
15
+ def to_rack_response
16
+ [status, header, body]
17
+ end
18
+
19
+ private
20
+
21
+ def constraint_name
22
+ @validator.class.registered_name
23
+ end
24
+
25
+ def key
26
+ @validator.key
27
+ end
28
+
29
+ def status
30
+ 400
31
+ end
32
+
33
+ def header
34
+ { "Content-Type" => "application/json" }
35
+ end
36
+
37
+ def body
38
+ { message: message }.to_json
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,116 @@
1
+ require "active_support/core_ext/object/try"
2
+ require "active_support/core_ext/string/inflections"
3
+
4
+ module Rack
5
+ class Spec
6
+ class Restful
7
+ def initialize(app, options = {})
8
+ @app = app
9
+ @options = options
10
+ end
11
+
12
+ def call(env)
13
+ Proxy.new(@app, spec, env).call
14
+ end
15
+
16
+ private
17
+
18
+ def spec
19
+ Spec.new(@options[:spec])
20
+ end
21
+
22
+ class Proxy
23
+ def initialize(app, spec, env)
24
+ @app = app
25
+ @spec = spec
26
+ @env = env
27
+ end
28
+
29
+ def call
30
+ if endpoint
31
+ response = handler_class.send(handler_method_name, *handler_args)
32
+ [
33
+ response.try(:status) || default_status,
34
+ default_header.merge(response.try(:header) || {}),
35
+ [(response.try(:body) || response).to_json]
36
+ ]
37
+ else
38
+ @app.call(@env)
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def endpoint
45
+ @endpoint ||= @spec.find_endpoint(@env)
46
+ end
47
+
48
+ def handler_args
49
+ if id
50
+ [id, params]
51
+ else
52
+ [params]
53
+ end
54
+ end
55
+
56
+ def handler_class
57
+ path_segments[1].singularize.camelize.constantize
58
+ end
59
+
60
+ def id
61
+ path_segments[2]
62
+ end
63
+
64
+ def path_segments
65
+ @path_segments ||= path.split("/")
66
+ end
67
+
68
+ def handler_method_name
69
+ case request_method
70
+ when "GET"
71
+ if id
72
+ :show
73
+ else
74
+ :index
75
+ end
76
+ when "POST"
77
+ :create
78
+ when "PUT"
79
+ :update
80
+ when "DELETE"
81
+ :destroy
82
+ end
83
+ end
84
+
85
+ def path
86
+ request.path
87
+ end
88
+
89
+ def request
90
+ @env["rack-spec.request"] ||= Rack::Request.new(@env)
91
+ end
92
+
93
+ def request_method
94
+ @env["REQUEST_METHOD"]
95
+ end
96
+
97
+ def params
98
+ request.params
99
+ end
100
+
101
+ def default_status
102
+ {
103
+ "GET" => 200,
104
+ "POST" => 201,
105
+ "PUT" => 204,
106
+ "DELETE" => 204,
107
+ }[request_method]
108
+ end
109
+
110
+ def default_header
111
+ { "Content-tYpe" => "application/json" }
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -1,3 +1,5 @@
1
+ require "addressable/template"
2
+
1
3
  module Rack
2
4
  class Spec
3
5
  class Spec < Hash
@@ -7,6 +9,16 @@ module Rack
7
9
  end
8
10
  end
9
11
 
12
+ def find_endpoint(env)
13
+ self["endpoints"].find do |path, source|
14
+ if Addressable::Template.new(path).extract(env["PATH_INFO"])
15
+ if endpoint = source[env["REQUEST_METHOD"]]
16
+ break endpoint
17
+ end
18
+ end
19
+ end
20
+ end
21
+
10
22
  def reach(*keys)
11
23
  keys.inject(self) do |hash, key|
12
24
  hash[key] if hash.respond_to?(:[])
@@ -7,7 +7,7 @@ module Rack
7
7
  end
8
8
 
9
9
  def call(env)
10
- parameters_validator.validate!(env)
10
+ Validators::ParametersValidator.new(spec, env).validate!
11
11
  @app.call(env)
12
12
  end
13
13
 
@@ -16,10 +16,6 @@ module Rack
16
16
  def spec
17
17
  Spec.new(@options[:spec])
18
18
  end
19
-
20
- def parameters_validator
21
- @parameters_validator ||= Validators::ParametersValidator.new(spec)
22
- end
23
19
  end
24
20
  end
25
21
  end
@@ -21,19 +21,15 @@ module Rack
21
21
 
22
22
  def validate!
23
23
  unless valid?
24
- raise ValidationError, self
24
+ raise Exceptions::ValidationError, self
25
25
  end
26
26
  end
27
27
 
28
- private
29
-
30
28
  def valid?
31
29
  raise NotImplementedError
32
30
  end
33
31
 
34
- def error_message
35
- raise NotImplementedError
36
- end
32
+ private
37
33
 
38
34
  def value
39
35
  @value ||= request.params[@key]
@@ -4,8 +4,6 @@ module Rack
4
4
  class MaximumLengthValidator < Base
5
5
  register_as "maximumLength"
6
6
 
7
- private
8
-
9
7
  def valid?
10
8
  value.nil? || value.length <= constraint
11
9
  end
@@ -4,8 +4,6 @@ module Rack
4
4
  class MaximumValidator < Base
5
5
  register_as "maximum"
6
6
 
7
- private
8
-
9
7
  def valid?
10
8
  value.nil? || value.to_f <= constraint
11
9
  end
@@ -4,8 +4,6 @@ module Rack
4
4
  class MinimumLengthValidator < Base
5
5
  register_as "minimumLength"
6
6
 
7
- private
8
-
9
7
  def valid?
10
8
  value.nil? || value.length >= constraint
11
9
  end
@@ -4,8 +4,6 @@ module Rack
4
4
  class MinimumValidator < Base
5
5
  register_as "minimum"
6
6
 
7
- private
8
-
9
7
  def valid?
10
8
  value.nil? || value.to_f >= constraint
11
9
  end
@@ -2,7 +2,8 @@ module Rack
2
2
  class Spec
3
3
  module Validators
4
4
  class NullValidator < Base
5
- def validate!
5
+ def valid?
6
+ true
6
7
  end
7
8
  end
8
9
  end
@@ -4,8 +4,6 @@ module Rack
4
4
  class OnlyValidator < Base
5
5
  register_as "only"
6
6
 
7
- private
8
-
9
7
  def valid?
10
8
  value.nil? || constraint.include?(value)
11
9
  end
@@ -2,18 +2,24 @@ module Rack
2
2
  class Spec
3
3
  module Validators
4
4
  class ParametersValidator
5
- def initialize(spec)
5
+ def initialize(spec, env)
6
6
  @spec = spec
7
+ @env = env
7
8
  end
8
9
 
9
- def validate!(env)
10
- parameters = @spec.reach("endpoints", env["PATH_INFO"], env["REQUEST_METHOD"], "parameters") || {}
10
+ def validate!
11
11
  parameters.each do |key, hash|
12
12
  hash.each do |type, constraint|
13
- ValidatorFactory.build(key, type, constraint, env).validate!
13
+ ValidatorFactory.build(key, type, constraint, @env).validate!
14
14
  end
15
15
  end
16
16
  end
17
+
18
+ private
19
+
20
+ def parameters
21
+ @spec.find_endpoint(@env).try(:[], "parameters") || []
22
+ end
17
23
  end
18
24
  end
19
25
  end
@@ -4,8 +4,6 @@ module Rack
4
4
  class RequiredValidator < Base
5
5
  register_as "required"
6
6
 
7
- private
8
-
9
7
  def valid?
10
8
  value.nil? == !constraint
11
9
  end
@@ -21,12 +21,12 @@ module Rack
21
21
  pattern "integer", /\A-?\d+\z/
22
22
  pattern "iso8601", ->(value) { Time.iso8601(value) rescue false }
23
23
 
24
- private
25
-
26
24
  def valid?
27
25
  value.nil? || pattern === value
28
26
  end
29
27
 
28
+ private
29
+
30
30
  def pattern
31
31
  self.class.patterns[constraint]
32
32
  end
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  class Spec
3
- VERSION = "0.0.3"
3
+ VERSION = "0.0.4"
4
4
  end
5
5
  end
data/rack-spec.gemspec CHANGED
@@ -18,8 +18,9 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.add_dependency "activesupport"
22
+ spec.add_dependency "addressable"
21
23
  spec.add_dependency "rack"
22
- spec.add_development_dependency "activesupport", "4.0.2"
23
24
  spec.add_development_dependency "bundler", "~> 1.5"
24
25
  spec.add_development_dependency "pry"
25
26
  spec.add_development_dependency "rack-test"
@@ -0,0 +1,36 @@
1
+ meta:
2
+ baseUri: http://api.example.com/
3
+ endpoints:
4
+ /recipes:
5
+ GET:
6
+ parameters:
7
+ page:
8
+ type: integer
9
+ minimum: 1
10
+ maximum: 10
11
+ private:
12
+ type: boolean
13
+ rank:
14
+ type: float
15
+ time:
16
+ type: iso8601
17
+ kind:
18
+ type: string
19
+ only:
20
+ - mono
21
+ - di
22
+ - tri
23
+ POST:
24
+ parameters:
25
+ title:
26
+ type: string
27
+ minimumLength: 3
28
+ maximumLength: 10
29
+ required: true
30
+ /recipes/{id}:
31
+ GET:
32
+ description: Get the recipe
33
+ PUT:
34
+ description: Update the recipe
35
+ DELETE:
36
+ description: Delete the recipe
@@ -1,44 +1,40 @@
1
1
  require "spec_helper"
2
- require "active_support/core_ext/string/strip"
3
- require "rack/test"
4
- require "yaml"
5
2
 
6
3
  describe Rack::Spec do
7
4
  include Rack::Test::Methods
8
5
 
6
+ before do
7
+ stub_const(
8
+ "Recipe",
9
+ Class.new do
10
+ class << self
11
+ def index(params)
12
+ [
13
+ { name: "test" }
14
+ ]
15
+ end
16
+
17
+ def show(id, params)
18
+ { name: "test#{id}" }
19
+ end
20
+
21
+ def create(params)
22
+ { name: "test" }
23
+ end
24
+
25
+ def update(id, params)
26
+ end
27
+
28
+ def destroy(id, params)
29
+ end
30
+ end
31
+ end
32
+ )
33
+ end
34
+
9
35
  let(:app) do
10
36
  Rack::Builder.app do
11
- use Rack::Spec, spec: YAML.load(<<-EOS.strip_heredoc)
12
- meta:
13
- baseUri: http://api.example.com/
14
- endpoints:
15
- /recipes:
16
- GET:
17
- parameters:
18
- page:
19
- type: integer
20
- minimum: 1
21
- maximum: 10
22
- private:
23
- type: boolean
24
- rank:
25
- type: float
26
- time:
27
- type: iso8601
28
- kind:
29
- type: string
30
- only:
31
- - mono
32
- - di
33
- - tri
34
- POST:
35
- parameters:
36
- title:
37
- type: string
38
- minimumLength: 3
39
- maximumLength: 10
40
- required: true
41
- EOS
37
+ use Rack::Spec, spec: YAML.load_file("spec/fixtures/spec.yml")
42
38
  run ->(env) do
43
39
  [200, {}, ["OK"]]
44
40
  end
@@ -57,12 +53,16 @@ describe Rack::Spec do
57
53
  {}
58
54
  end
59
55
 
56
+ let(:response) do
57
+ last_response
58
+ end
59
+
60
60
  subject do
61
61
  send verb, path, params, env
62
62
  last_response.status
63
63
  end
64
64
 
65
- describe "GET" do
65
+ describe "Validation on GET" do
66
66
  let(:verb) do
67
67
  :get
68
68
  end
@@ -128,7 +128,7 @@ describe Rack::Spec do
128
128
  end
129
129
  end
130
130
 
131
- describe "POST" do
131
+ describe "Validation on POST" do
132
132
  before do
133
133
  params[:title] = "test"
134
134
  end
@@ -138,7 +138,7 @@ describe Rack::Spec do
138
138
  end
139
139
 
140
140
  context "with valid request" do
141
- it { should == 200 }
141
+ it { should == 201 }
142
142
  end
143
143
 
144
144
  context "with request body parameter invalid on minimumLength" do
@@ -162,4 +162,60 @@ describe Rack::Spec do
162
162
  it { should == 400 }
163
163
  end
164
164
  end
165
+
166
+ describe "Restful" do
167
+ context "with GET /recipes" do
168
+ it "calls Recipe.index(params)" do
169
+ get "/recipes"
170
+ response.status.should == 200
171
+ response.body.should be_json_as(
172
+ [
173
+ { name: "test" },
174
+ ]
175
+ )
176
+ end
177
+ end
178
+
179
+ context "with GET /recipes/{id}" do
180
+ it "calls Recipe.show(id, params)" do
181
+ get "/recipes/1"
182
+ response.status.should == 200
183
+ response.body.should be_json_as(name: "test1")
184
+ end
185
+ end
186
+
187
+ context "with POST /recipes" do
188
+ before do
189
+ params[:title] = "test"
190
+ end
191
+
192
+ it "calls Recipe.create(params)" do
193
+ post "/recipes", params
194
+ response.status.should == 201
195
+ response.body.should be_json_as(name: "test")
196
+ end
197
+ end
198
+
199
+ context "with PUT /recipes/{id}" do
200
+ it "calls Recipe.update(id, params)" do
201
+ put "/recipes/1"
202
+ response.status.should == 204
203
+ end
204
+ end
205
+
206
+ context "with DELETE /recipes/{id}" do
207
+ it "calls Recipe.update(id, params)" do
208
+ delete "/recipes/1"
209
+ response.status.should == 204
210
+ end
211
+ end
212
+
213
+ context "with undefined endpoint" do
214
+ it "falls back to the inner rack app" do
215
+ get "/undefined"
216
+ response.status.should == 200
217
+ response.body.should == "OK"
218
+ end
219
+ end
220
+ end
165
221
  end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
2
2
  require "rack/spec"
3
+ require "rack/test"
3
4
  require "rspec/json_matcher"
5
+ require "yaml"
4
6
 
5
7
  RSpec.configure do |config|
6
8
  config.treat_symbols_as_metadata_keys_with_true_values = true
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-spec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryo Nakamura
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-22 00:00:00.000000000 Z
11
+ date: 2014-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rack
14
+ name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - '>='
@@ -25,19 +25,33 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: activesupport
28
+ name: addressable
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '='
31
+ - - '>='
32
32
  - !ruby/object:Gem::Version
33
- version: 4.0.2
34
- type: :development
33
+ version: '0'
34
+ type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '='
38
+ - - '>='
39
39
  - !ruby/object:Gem::Version
40
- version: 4.0.2
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rack
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -138,9 +152,11 @@ files:
138
152
  - lib/rack-spec.rb
139
153
  - lib/rack/spec.rb
140
154
  - lib/rack/spec/exception_handler.rb
155
+ - lib/rack/spec/exceptions/base.rb
156
+ - lib/rack/spec/exceptions/validation_error.rb
157
+ - lib/rack/spec/restful.rb
141
158
  - lib/rack/spec/spec.rb
142
159
  - lib/rack/spec/validation.rb
143
- - lib/rack/spec/validation_error.rb
144
160
  - lib/rack/spec/validator_factory.rb
145
161
  - lib/rack/spec/validators/base.rb
146
162
  - lib/rack/spec/validators/maximum_length_validator.rb
@@ -154,6 +170,7 @@ files:
154
170
  - lib/rack/spec/validators/type_validator.rb
155
171
  - lib/rack/spec/version.rb
156
172
  - rack-spec.gemspec
173
+ - spec/fixtures/spec.yml
157
174
  - spec/rack/spec_spec.rb
158
175
  - spec/spec_helper.rb
159
176
  homepage: https://github.com/r7kamura/rack-spec
@@ -181,6 +198,7 @@ signing_key:
181
198
  specification_version: 4
182
199
  summary: Define specifications of your Rack application.
183
200
  test_files:
201
+ - spec/fixtures/spec.yml
184
202
  - spec/rack/spec_spec.rb
185
203
  - spec/spec_helper.rb
186
204
  has_rdoc:
@@ -1,41 +0,0 @@
1
- require "json"
2
-
3
- module Rack
4
- class Spec
5
- class ValidationError < StandardError
6
- def initialize(validator)
7
- @validator = validator
8
- end
9
-
10
- def message
11
- "Invalid #{key} on `#{constraint_name}` constraint"
12
- end
13
-
14
- def to_rack_response
15
- [status, header, body]
16
- end
17
-
18
- private
19
-
20
- def constraint_name
21
- @validator.class.registered_name
22
- end
23
-
24
- def key
25
- @validator.key
26
- end
27
-
28
- def status
29
- 400
30
- end
31
-
32
- def header
33
- { "Content-Type" => "application/json" }
34
- end
35
-
36
- def body
37
- { message: message }.to_json
38
- end
39
- end
40
- end
41
- end