No route matches [POST] "/users" - ruby-on-rails

I'm new to rails, and I'm trying to build API following Code School tutorial.
I get this error while trying to post to '/users' path.
routes file code :
Rails.application.routes.draw do
namespace :api,constraints: {subdomain: 'api'}, path: '/' do
resources :users, except: :delete
end
end
and the test code is :
require 'test_helper'
class CreatingUsersTest < ActionDispatch::IntegrationTest
test 'create users' do
post api_users_path,
{user: {name: 'test', email:'test#test.com'}}.to_json,
{'Accept' => Mime::JSON, 'Content-Type': Mime::JSON.to_s}
assert_equal response.status, 201
assert_equal response.content_type, Mime::JSON
user = json(response.body)
assert_equal api_user_url(user[:id]), response.location
end
end
And when I use rake routes :
api_users GET /users(.:format) api/users#index {:subdomain=>"api"}
POST /users(.:format) api/users#create {:subdomain=>"api"}
....

In the route you constraint the subdomain to be api
namespace :api,constraints: {subdomain: 'api'}, path: '/' do
but then in the test you call api_user_path
post api_users_path
that uses a generic hostname (test.host), and not the api hostname. The solution is to pass a specific host to the helper that satisfies the requirement.
post api_users_path(host: "api.test.host")

Related

How to access devise token auth registration controller?

I am using Devise auth token gem for authenticating some parts of my rails app. But when I try to create a new user with the registration path, it is giving me the following error{"errors":["Authorized users only."]}.
Here is the rspec code that I am using for the test,
it 'creates a user using email/password combo' do
post api_user_registration_path, { email: 'xxx', password: 'yyy',password_confirmation: 'yyy'}
puts last_response.body
expect(last_response.body).not_to have_content('error')
end
Additional info: the model name is 'User' and the routes looks like,
namespace :api do
scope :v1 do
mount_devise_token_auth_for 'User', at: 'auth'
end
end
I understand that the devise is expecting the user to be authenticated before accessing this path, but this being the user registration, it needs to be outside the authentication. Can you suggest a solution for this? Is there any configuration that I am missing here?
Try with:
namespace :api do
namespace :v1 do
mount_devise_token_auth_for 'User', at: '/auth'
end
end
This will create the following routes:
new_api_v1_user_session GET /api/v1/auth/sign_in(.:format) devise_token_auth/sessions#new
api_v1_user_session POST /api/v1/auth/sign_in(.:format) devise_token_auth/sessions#create
destroy_api_v1_user_session DELETE /api/v1/auth/sign_out(.:format) devise_token_auth/sessions#destroy
api_v1_user_password POST /api/v1/auth/password(.:format) devise_token_auth/passwords#create
new_api_v1_user_password GET /api/v1/auth/password/new(.:format) devise_token_auth/passwords#new
edit_api_v1_user_password GET /api/v1/auth/password/edit(.:format) devise_token_auth/passwords#edit
PATCH /api/v1/auth/password(.:format) devise_token_auth/passwords#update
PUT /api/v1/auth/password(.:format) devise_token_auth/passwords#update
cancel_api_v1_user_registration GET /api/v1/auth/cancel(.:format) devise_token_auth/registrations#cancel
api_v1_user_registration POST /api/v1/auth(.:format) devise_token_auth/registrations#create
new_api_v1_user_registration GET /api/v1/auth/sign_up(.:format) devise_token_auth/registrations#new
edit_api_v1_user_registration GET /api/v1/auth/edit(.:format) devise_token_auth/registrations#edit
PATCH /api/v1/auth(.:format) devise_token_auth/registrations#update
PUT /api/v1/auth(.:format) devise_token_auth/registrations#update
DELETE /api/v1/auth(.:format) devise_token_auth/registrations#destroy
api_v1_auth_validate_token GET /api/v1/auth/validate_token(.:format) devise_token_auth/token_validations#validate_token
Also create an controller in app/controllers/api/v1/api_base_controller.rb
class Api::V1::BaseApiController < ActionController::Base
include DeviseTokenAuth::Concerns::SetUserByToken
end
Also add to your file app/controllers/application_controller.rb
before_action :configure_permitted_parameters, if: :devise_controller?

Rspec test to post as json

I am having problems trying to post as JSON to my controller action within my rspec test
RSpec.describe RegistrationsController, type: :controller do
context 'Adding a Valid User' do
it 'Returns Success Code and User object' do
#params = { :user => {username: 'name', school: 'school'} }.to_json
post :create, #params
end
end
end
At the moment I want to get a successful post request firing but am getting this error back all the time
Failure/Error: post :create, #params
AbstractController::ActionNotFound:
Could not find devise mapping for path "/lnf".
My routes are setup like so
Rails.application.routes.draw do
constraints(subdomain: 'api') do
devise_for :users, path: 'lnf', controllers: { registrations: "registrations" }
devise_scope :user do
post "/lnf" => 'registrations#create'
end
end
end
Rake routes outputs the following
Prefix Verb URI Pattern Controller#Action
user_registration POST /lnf(.:format) registrations#create {:subdomain=>"api"}
lnf POST /lnf(.:format) registrations#create {:subdomain=>"api"}
So i have 2 declarations for the same action?
Could anyone shed some light on this please
Thanks
Ok so after a painstaking few hours i have got my tests passing correctly and posting as json by doing the following
require 'rails_helper'
RSpec.describe RegistrationsController, type: :controller do
before :each do
request.env['devise.mapping'] = Devise.mappings[:user]
end
context 'Adding a Valid User' do
it 'Returns Success Code and User object' do
json = { user: { username: "richlewis14", school: "Baden Powell", email: "richlewis14#gmail.com", password: "Password1", password_confirmation: "Password1"}}.to_json
post :create, json
expect(response.code).to eq('201')
end
end
end
My Routes are back to normal
Rails.application.routes.draw do
constraints(subdomain: 'api') do
devise_for :users, path: 'lnf', controllers: { registrations: "registrations" }
end
end
And in my test environment I had to add
config.action_mailer.default_url_options = { host: 'localhost' }
The key here was
request.env['devise.mapping'] = Devise.mappings[:user]
Not fully sure as yet to what it does, its next on my list to find out, but my tests are starting to run and pass

Rspec testing API versioning

I'm working with a web api in rails 4.1.8 and i'm doing some testing but always is returning me
Failure/Error: post '/v1/users', subdomain: 'api', user: #user.to_json, format: :json
ActionController::UrlGenerationError:
No route matches {:action=>"/v1/users", :controller=>"api/v1/users", :format=>:json, :subdomain=>"api", :user=>"JSON_OBJ"}
but if i test it in the browser with Advance Rest Console it works, i don't know what i'm doing wrong
here is me code
routes.rb
namespace :api, path: '/', constraints: {subdomain: 'api'}, defaults: { format: :json } do
namespace :v1 do
with_options except: [:edit, :new] do |except|
except.resources :users do
collection do
post 'login'
post 'showme'
end
end
except.resources :products
except.resources :locations
end
end
end
and my controller spec
module API
module V1
describe UsersController do
before do
request.host = "api.example.com"
expect({:post => "http://#{request.host}/v1/users"}).to(
route_to( controller: "api/v1/users",
action: "create",
subdomain: 'api',
format: :json
)
) # => PASS
# token expectations
#auth_token = allow(JWT::AuthToken).to(
receive(:make_token).and_return("mysecretkey")
)
expect(JWT::AuthToken.make_token({}, 3600)).to eq("mysecretkey")
end
describe "Create User" do
before(:each) do
#user = FactoryGirl.attributes_for :user
end
it 'should return a token' do
post '/v1/users', subdomain: 'api', user: #user.to_json, format: :json # Error
response_body = JSON.parse(response.body, symbolize_names: true)
expect(response_body['token']).to eql "mysecretkey"
end
end
end
end
end
rake routes
login_api_v1_users POST /v1/users/login(.:format) api/v1/users#login {:format=>:json, :subdomain=>"api"}
showme_api_v1_users POST /v1/users/showme(.:format) api/v1/users#showme {:format=>:json, :subdomain=>"api"}
api_v1_users GET /v1/users(.:format) api/v1/users#index {:format=>:json, :subdomain=>"api"}
POST /v1/users(.:format) api/v1/users#create {:format=>:json, :subdomain=>"api"}
api_v1_user GET /v1/users/:id(.:format) api/v1/users#show {:format=>:json, :subdomain=>"api"}
PATCH /v1/users/:id(.:format) api/v1/users#update {:format=>:json, :subdomain=>"api"}
PUT /v1/users/:id(.:format) api/v1/users#update {:format=>:json, :subdomain=>"api"}
DELETE /v1/users/:id(.:format) api/v1/users#destroy {:format=>:json, :subdomain=>"api"}
As described in http://api.rubyonrails.org/classes/ActionController/TestCase/Behavior.html which is referenced in https://www.relishapp.com/rspec/rspec-rails/docs/controller-specs, the first argument to post in your RSpec example is the name of the controller method to be called (i.e. :create in your case), not the route to that method.

Routing Test Fails with Matched Route

I have this line of code in my routes
namespace :api, defaults: {format: 'json'} do
namespace :v1 do
match '/auth/:provider/callback', to: 'sign_in#authenticate'
end
end
And my test as
require 'spec_helper'
describe "Routing" do
it "should route to sign_in#authenticate" do
expect(post: 'api/v1/auth/:provider/callback').to route_to({ controller: 'api/v1/sign_in', action: 'authenticate', format: 'json' })
end
end
However, no matter what I do I keep getting the error
No route matches "/api/v1/auth/:provider/callback"
What am I missing here in order to make this test pass?
I believe the error you're getting is because match defaults to a GET request, but you are testing a POST request in your spec. You should be able to fix the issue by changing the route to:
match '/auth/:provider/callback', to: 'sign_in#authenticate', via: :post
My personal preference is to use the post method instead of match, it just reads better to me:
post '/auth/:provider/callback' => 'sign_in#authenticate'

Rspec "No route matches" error

I am attempting to test my sessions_controller in Rails 3 app with rspec, but keep coming across this error when I run rspec on my sessions_controller_spec.rb:
ActionController::RoutingError:
No route matches {:controller=>"sessions", :action=>"create"}
Here are all the relevant files:
routes.rb
match 'event' => 'event#create', via: [:post]
match 'event/agenda' => 'event#agenda', via: [:get]
match 'testLogin' => 'application#test_login', via: [:get]
post 'session' => 'session#create'
sessions_controller.rb
class SessionsController < ApplicationController
def create
#MY CODE HERE
end
end
sessions_controller_spec.rb
require 'spec_helper'
describe SessionsController, :type => :controller do
describe "POST #create" do
context "invalid params" do
it "returns a response with status failed if all required parameters are not passed in" do
post "create"
response.body.status.should eq("failed")
end
end
end
end
If there's any other info I can provide to help let me know. Thanks a lot!
post 'session' => 'session#create'
Your route definition is looking for a SessionController, but you have defined a SessionsController. Fix your route.
post 'session' => 'sessions#create'

Resources