I have a small API that I am writing in rails 3. This is not a restful application so I use a controller called api that has some methods such as:
def users
#users = User.all
respond_to do |format|
format.any do
render :xml => #users.to_xml
end
end
end
end
My routes (with comments etc removed) file looks like this:
resources :shows
resources :users
resources :comments
devise_scope :user do
get "/login" => "devise/sessions#new"
get "/logout" => "devise/sessions#destroy"
get "/register" => "devise/registrations#new"
end
root :to => 'home#index'
match ':controller(/:action(/:id(.:format)))'
When I call api/users I get the XML wrapped in HTML tags (in the body actually) but if I call api/users.xml I get a 406 error?
Do I need to change my routes to accommodate the XML call?
Thanks,
s
I added a new route to routes.rb and it worked:
match 'api/users.:format' => 'api#users', :constraints => {:format => /(xml)/}
j
Related
So I keep getting the error:
No route matches {:action=>"create", :controller=>"xaaron/api_keys"}
Which is thrown in the test:
it "should not create an api key for those not logged in" do
post :create
expect(response).to redirect_to xaaron.login_path
end
when I go to spec/dummy and run the rake routes command I see:
api_keys GET /api_keys(.:format) xaaron/api_keys#index
POST /api_keys(.:format) xaaron/api_keys#create
new_api_key GET /api_keys/new(.:format) xaaron/api_keys#new
edit_api_key GET /api_keys/:id/edit(.:format) xaaron/api_keys#edit
api_key GET /api_keys/:id(.:format) xaaron/api_keys#show
PATCH /api_keys/:id(.:format) xaaron/api_keys#update
PUT /api_keys/:id(.:format) xaaron/api_keys#update
DELETE /api_keys/:id(.:format) xaaron/api_keys#destroy
Which shows that yes this route does exist. My routes file for this engine looks like:
Xaaron::Engine.routes.draw do
get 'login' => 'sessions#new', :as => 'login'
get 'logout' => 'sessions#destroy', :as => 'logout'
get 'signup' => 'users#new', :as => 'signup'
get 'permission_denied' => 'error#denied', :as => 'permission_denied'
get 'record_not_found' => 'error#error', :as => 'record_not_found'
get 'password_reset' => 'password_resets#edit', :as => 'rest_user_password'
resource :error, controller: 'error'
resources :users
resources :api_keys
resources :sessions
resources :roles
resources :password_resets
end
What am I missing?
update
For those of you curious how I am getting these routes, its because the dummy app's routes file is set up (by default) as such:
Rails.application.routes.draw do
mount Xaaron::Engine => "/xaaron"
end
Update II
I have been reading this api docs on how routing is done in engines and I believe the way I have done this is correct, how ever the controller is defined as such:
module Xaaron
class ApiKeysController < ActionController::Base
before_action :authenticate_user!
def index
#api_key = Xaaron::ApiKey.where(:user_id => current_user.id)
end
def create
#api_key = Xaaron::ApiKey.new(:user_id => current_user.id, :api_key => SecureRandom.hex(16))
create_api_key(#api_key)
end
def destroy
Xaaron::ApiKey.find(params[:id]).destroy
flash[:notice] = 'Api Key has been deleted.'
redirect_to xarron.api_keys_path
end
end
end
You need to tell your spec you are using the engine routes:
describe ApiKeysController do
routes { Xaaron::Engine.routes }
it "should not create an api key for those not logged in" do
post :create
expect(response).to redirect_to xaaron.login_path
end
end
I am trying to force SSL only on specific URLs (user account settings in this case), and I saw this: Rails 3 SSL Deprecation . This is my original routes:
resources :users do
collection do
get :thanks
get :change_password
get :settings
end
end
I changed it to this after reading that answer;
resources :users do
scope :constraints => { :protocol => 'https' } do
collection do
get :thanks
get :change_password
get :settings
end
end
end
But now lets say when I try to go on the settings page, I get an error for The action 'show' could not be found for UsersController when it's actually supposed to be processed by User#settings. What am I doing wrong?
scope :constraints => { :protocol => 'https' } do
resources :users do
collection do
get :thanks
get :change_password
get :settings
end
end
end
scope first. I think...
I have been trying to implement a vanity url for user profiles, based on the example here: Rails 3: Permalink public profile. I have replaced the 'id' with username:
def to_param
username
end
However this has caused issues with my other routes. I have set them so that they match the default sets of routes exactly, when running 'rake routes'.
get '/users/' => 'users#index', :as => :users
post '/users' => 'users#create'
get '/users/new' => 'users#new', :as => :new_user
get '/users/:id/edit' => 'users#edit', :as => :edit_user
patch '/users/:id' => 'users#update'
put '/users/:id' => 'users#update'
delete '/users/:id' => 'users#destroy'
# for vanity url
get '/:id' => 'users#show', :as => :user
With this setup, trying to access delete and update routes give me 'no route matches' error. What is the proper way to specify these, and / or should I be doing this a different way? Any help is appreciated.
I think it's interresting and more readable to keep the resources syntax in the routes.rb, except for the show, which you can rewrite to customize user_path :
resources :users, :except => [:show]
# 2 possibilities for the show url
get '/users/:id' => 'users#show' # can be removed if you don't want to keep /users/:id url
get '/:id' => 'users#show', :as => :user
But change the controller to find user by username instead of id, for example
def show
#post = Post.find_by_username(params[:id]) # instead of Post.find(params[:id])
# ...
end
In my routes file, I have a resource called products. The index action of the products resource is also my root path.
resources :products
root :to => "products#index"
When I use the helper method products_path (in a redirect or link), it returns "/products". But what I want is for it to return "/". I know it's the same page, but I want to keep my URL's consistent.
How can I fix this?
Thanks!
root :to => 'products#index', :as => :products
match '', :to => 'products#index', :as => :root # recreate named root_path, if you use it anywhere
This will need to appear below your resources :products as it does in your example above. This will override the products_path and products_url you'd get from resources. Run rake routes before and after to compare.
if you only want to change Index try excluding it first then defining it on its own like so:
resources :products, :except => [:index]
resources :products, :only => [:index], :path => '/'
root_path() should return /
I guess you could redefine the products_path to be the same as root_path (like in a helper file):
def products_path(*params)
root_path *params
end
I got a User model and a About model. The about model is a page where users have more info about them that due its nature is more appropriate to have it on a separate model rather than in the user model.
I want to be able to route it to something like /:username/about and get all the verbs working on that path (GET POST, PUT, DELETE).
/:username/about
/:username/about/edit
/:username/about
This is what I already have
# routes.rb
resources :users do
resources :abouts
end
match ':username/about' => 'abouts#show', :as => :user_about
match ':username/about/add' => 'abouts#new', :as => :user_new_about
match ':username/about/edit' => 'abouts#edit', :as => :user_edit_about
And in the models I have
# about.rb
belongs_to :user
# user.rb
has_one :about
When I'm doing a post or put to /roses/about It's interpreting It as a show
Started POST "/roses/about" for 127.0.0.1 at Sun Feb 27 16:24:18 -0200 2011
Processing by AboutsController#show as HTML
I'm probably missing the declaration in the routes, but doesn't it get messy declaring each verb for a resource when it's different from the default?
What's the simplest and cleaner way to archive this?
When using a has_one, it might make sense to declare it as a singular resource in your routes. Meaning
resources :users do
resource :about # notice "resource" and not "resources"
end
And if you want to override the paths for new/edit, add a :path_names option to the resource/resources-call:
resources :about, :path_names => { :new => 'add', :edit => 'edit' }
The official documentation has lots of other tips and tricks for routing as well.
You can use scope and controller blocks to cut down on the verbiage:
scope "/:username" do
controller :abouts do
get 'about' => :show
post 'about' => :create
get 'about/add' => :new
get 'about/edit' => :edit
end
end
which produces:
about GET /:username/about(.:format) {:action=>"show", :controller=>"abouts"}
POST /:username/about(.:format) {:action=>"create", :controller=>"abouts"}
about_add GET /:username/about/add(.:format) {:controller=>"abouts", :action=>"new"}
about_edit GET /:username/about/edit(.:format) {:controller=>"abouts", :action=>"edit"}