No route matches [GET] "/products" - api

i follow this How To but i have No route matches error...
i have this routes.rb:
# config/routes.rb
require 'api_constraints'
Rails.application.routes.draw do
namespace :api, defaults: { format: :json }, constraints: { subdomain: 'api' }, path: '/' do
scope module: :v1, constraints: ApiConstraints.new(version: 1, default: true) do
resources :products, only: [:index, :show, :create, :destroy]
end
end
end
Rake Routes:
api_products GET /products(.:format) api/v1/products#index {:format=>:json, :subdomain=>"api"}
POST /products(.:format) api/v1/products#create {:format=>:json, :subdomain=>"api"}
api_product GET /products/:id(.:format) api/v1/products#show {:format=>:json, :subdomain=>"api"}
DELETE /products/:id(.:format) api/v1/products#destroy {:format=>:json, :subdomain=>"api"}
This is the error:
ActionController::RoutingError (No route matches [GET] "/products")

I presume that the request is getting rejected at subdomain constraint. I think you make request to http://localhost:3000/produtcts, but you need some url like http://api.****/products. There is a guide how to do it locally http://shapeshed.com/developing-subdomain-rails-sites-locally/

Related

Devise custom user root is not working

After a user signs in, I want them to be redirected to /users/2 or users/44, like a normal resource. (That way an admin can easily view any user's profile page just by knowing their id.)
I have no idea what is going on in my routes file. When a user logs in, I can see in the logs that it authenticates properly, and that my application_controller's after_sign_in_path_for is called.
But this is the error that I am getting when I try to redirect_to user_path(current_user).
No route matches {:action=>"show", :controller=>"users", :user_id=>11}
My config/routes.rb
devise_for :users, :path_names => {:sign_in => 'signin', :sign_out => 'signout', :sign_up => 'signup' }
devise_scope :user do
get "signin", :to => "devise/sessions#new"
get "signout", :to => "devise/sessions#destroy", via: :delete
get "signup", :to => "devise/registrations#new"
end
resources :users do
member do
get 'settings', to: 'users#edit'
end
end
My application_controller.rb
class ApplicationController < ActionController::Base
...
def after_sign_in_path_for(resource)
redirect_to user_path(:user_id=>current_user.id)
end
end
Shouldn't the resource :users block take care of creating a user show path? I do have a show method in my users_controller.rb. Please help, I've been trying to get this working for 2 days now.
My problem was that I was redirecting in the after_sign_in_path(resource) method instead of just returning the path:
def after_sign_in_path_for(resource)
return user_path(:user_id=>current_user.id)
end
is the correct way to do this.

Rails testing, how to specify path for post? (No route matches error)

I try to test one of my REST api controllers which is placed at "controllers/api/v1/bookings_controller.rb". The controller only responds_to json at the moment as you can see here:
class Api::V1::BookingsController < ApplicationController
respond_to :json
before_filter :authenticate_user!
before_filter :get_user
def create
...
end
end
My functional test is located at "test/functional/api/v1/bookings_controller_test.rb" and looks like following:
require 'test_helper'
class Api::V1::BookingsControllerTest < ActionController::TestCase
include Devise::TestHelpers
setup do
#booking = bookings(:one)
#user = users(:one)
sign_in #user
end
test "should return a bad request" do
post :create, :booking => { }, :format => 'json'
assert_response :bad_request
end
end
The post path for creating a booking looks like this (and works, tested with HTTP Client):
api_v1_user_bookings
GET /api/v1/users/:user_id/bookings(.:format) api/v1/bookings#index
POST /api/v1/users/:user_id/bookings(.:format) api/v1/bookings#create
However when I run the test it seems that it uses some default route (see error message below), how can i specify the correct route in my test? Or is there some other mistake I do not see here?
test_should_return_a_bad_request(Api::V1::BookingsControllerTest):
ActionController::RoutingError: No route matches {:booking=>{}, :format=>"js
on", :controller=>"api/v1/bookings", :action=>"create"}
Your route expects a user_id parameter. Add it to your post:
post :create, :user_id => #user.id, :booking => {}, :format => :json
Ok, I think I figured it out now. I just had to add the user-id, otherwise it seems that rails does not select the right route. So the correct test method looks like this:
test "should return a bad request" do
post :create, :user_id => #user.id, :booking => { }, :format => 'json'
assert_response :bad_request
end

Rails route for api on subdomain

I want to make the API of my Rails app accessible through a subdomain (https://api.domain.com). I have the following routes defined:
constraints :subdomain => 'api' do
namespace :api, defaults: {format: 'json'} do
scope module: :v1, constraints: ApiConstraints.new(version: 1, default: true) do
resources :posts
end
end
end
This works but results in the following url:
https://api.domain.com/api/posts
I would like it to be:
https://api.domain.com/posts
The API controllers are in app/controllers/api/v1 where they should stay.
I tried mapping the route but without any success. Does somebody know how to fix this?
Change
namespace :api, defaults: {format: 'json'} do
to
namespace :api, path: nil, defaults: {format: 'json'} do

Rails assert_routing on root route raises ActionController::RoutingError

I'm trying to test that requesting the root path (/) routes to my beta controller's :new action. When I do this manually (in my browser), it works fine. But my automated test is failing with No route matches "/".
In config/routes.rb I have
MyRailsApp::Application.routes.draw do
root to: 'beta#new' # Previously: `redirect('/beta/join')`
end
In my spec/routing/root_route_spec.rb I have tried
require 'spec_helper'
describe "the root route" do
it "should route to beta signups" do
get('/').should route_to(controller: :beta, action: :new)
end
end
and have also tried
require 'spec_helper'
describe "the root route" do
it "should route to beta signups" do
assert_routing({ method: :get, path: '/' }, { controller: :beta, action: :new })
end
end
but both complain that No route matches "/"
1) the root route should route to the beta signups
Failure/Error: get('/').should route_to "beta#new"
No route matches "/"
# ./spec/routing/root_route_spec.rb:5:in `block (2 levels) in <top (required)>'
When I go, in my browser, to localhost:3000, I'm correctly routed to the BetaController::new action.
What explains the No route matches "/" error?
I'm using Rails 3.1.3 and RSpec-2.10.
Thanks!
You should test that / redirects to /beta/join and then as a separate issue test that /beta/join routes to the :new action of the :beta controller.
Redirection is tested in requests, not routing.
# spec/requests/foobar_spec.rb
describe 'root' do
it "redirects to /beta/join" do
get "/"
response.should redirect_to("/beta/join");
end
end
and
# spec/routing/beta_spec.rb
...
it 'routes /beta/join to the new action'
get('beta/join').should route_to(:controller => 'beta', :action => 'new')
end

Rails3 RSpec testing custom redirect route in routes.rb

I have a custom redirection in my routes.rb which works fine at the ui:
match ':hash' => redirect { |params| begin url = Sharing.find_by_short_url(params[:hash]); "/#{url.shareable_type}/#{url.shareable_id}/" rescue '/' end }, :constraints => { :hash => /[a-zA-Z0-9]{7}/ }
What is does is takes a shortened url and looks up the actual url path.
However my test is failing:
it "routes GET 'STU1VWX' to stations/1" do
{ :get => "STU1VWX" }.should redirect_to(
:controller => "stations",
:action => "show",
:params => {:id => 1}
)
end
With:
1) Shorter URL redirect routes GET 'STU1VWX' to stations/1
Failure/Error: { :get => "STU1VWX" }.should route_to(
ActionController::RoutingError:
No route matches "/STU1VWX"
# ./spec/routing_spec.rb:12:in `block (2 levels) in <top (required)>'
So the problem is isolated at the test level. I know I could test this in a controller test but given that the code is in routes.rb I should not have to. Is there inherently a reason that using should route_to not to work in the case of redirection?
Looks like you're saying here that if you can't find the page belonging to the hash, then redirect to "/"
There's something really stinky about performing an ActiveRecord find in your routes.
If you have to redirect to a specific controller depending on the sharable type, then I'd put this as a separate controller with a redirect:
match "/:hash" => 'SharableController#redirect':constraints => { :hash => /[a-zA-Z0-9]{7}/ }
and then deal with finding the record and redirecting to the correct controller action from there:
class SharableController < ApplicationController
def redirect
#sharable = Sharable.find_by_sharable_type(params[:hash])
redirect_to controller: #sharable.sharable_type, action: 'show', id: #sharable.id
end
end
OR... depending on how similar the show actions are:
class SharableController < ApplicationController
def redirect
#sharable = Sharable.find_by_sharable_type(params[:hash])
render template: "#{#sharable.sharable_type.pluralize}/show"
end
end
If you're only dealing with GET requests, better to swap out match for get by the way:
get "/:hash" => 'SharableController#redirect', :constraints => { :hash => /[a-zA-Z0-9]{7}/ }