Неверный URI Ошибка в пост-запросе Синатры
Я работаю над демонстрационным приложением Sinatra в рамках учебного курса по RSpec ( официальное репо). Приложение использует установку ActiveRecord по меню - без Rails. Когда я пытаюсь опубликовать объект Book на сервере при запуске спецификации, я получаю InvalidURIError.
Failures:
1) App creates a book
Failure/Error: post :books, book: { name: "My first book" }
URI::InvalidURIError:
bad URI(is not URI?): books
# /Users/andrekibbe/.rvm/gems/ruby-2.2.1/gems/rack-test-0.6.3/lib/rack/test.rb:193:in `env_for'
# /Users/andrekibbe/.rvm/gems/ruby-2.2.1/gems/rack-test-0.6.3/lib/rack/test.rb:66:in `post'
# ./spec/rack_spec.rb:10:in `block (2 levels) in <top (required)>'
rack_spec.rb:
require "environment"
require "rack_app"
fdescribe App do
include Rack::Test::Methods
let(:app) { App }
it "creates a book" do
post :books, book: { name: "My first book" }
expect(last_response.status).to eq 201
end
end
rack_app.rb:
class App < Sinatra::Base
post '/books' do
book = Book.new params[:book]
if book.save
status 201
else
status 502
end
end
end
spec_helper.rb:
require "environment"
require "factory_girl"
require "database_cleaner"
require "rack/test"
require_relative "./factories.rb"
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
config.include Rack::Test::Methods
config.before(:suite) do
begin
DatabaseCleaner.start
ensure
DatabaseCleaner.clean
end
end
end
book.rb:
class Book < ActiveRecord::Base
validates_presence_of :name
end
environment.rb:
require "sinatra"
require "active_record"
ActiveRecord::Base.establish_connection(
adapter: :sqlite3,
database: File.expand_path("../../db/test.sqlite3", __FILE__)
)
О чем это post :books, book: { name: "My first book" }
что заставляет Rack рассматривать запрос как плохой URI?
1 ответ
Ваш код работает для меня, если вы вносите изменения, которые я рекомендовал в комментарии, однако, если вы буквально использовали следующее в своем коде:
post '/books', book: {...}
или же:
post :'/books', ...
... тогда, конечно, эти строки не будут работать. ...
означает "так же, как ваш исходный код, потому что это напрасная трата моего времени, чтобы напечатать это". Вот как должно выглядеть рекомендуемое изменение:
rack_app.rb:
require "environment"
require "rack_app"
fdescribe App do
let(:app) { App }
it "creates a book" do
post '/books', book: { name: "My brand new book" }
expect(last_response.status).to eq 201
end
end
Единственный маршрут, который определил ваше приложение, находится здесь:
class App < Sinatra::Base
# +--------This is the only url your App responds to
# | and ONLY if it is contained in a post request
# V
post '/books' do
book = Book.new params[:book]
if book.save
status 201
else
status 502
end
end
end
Даже использование символа в качестве URL не работает:
it "creates a book" do
post :'/books', book: { name: "My brand new book" }
И поскольку Symbol не будет работать для URL в вашем тесте rspec, это означает, что Sinatra принимает первый аргумент, данный для post(), например :'/books'
и сравнивает его с маршрутами, которые вы определили в своем классе приложения:
defined_route = '/books'
requested_route = :'/books'
if requested_route != defined_route
puts "URI ERROR"
end
--output:--
URI ERROR