I am using Rocket_Pants gem to provide API access for my existing Rails app. I have two of controllers with the same name but stored in different locations:
I store the controller that handles HTTP requests in app/controllers, and the controller that handles API calls in sub-directory API of app/controllers.
I have the following in my Routes:
# HTTP routing
resources :posts do
collection do
get 'search'
end
end
# API routing
api :version => 1 do
resources :posts, :only => [:index, :show]
resources :posts do
collection do
get 'search'
end
end
end
However, when I rake routes, I got:
GET /:version/posts/search(.:format) posts#search {:version=>/(1)/, :format=>"json"}
GET /:version/posts(.:format) posts#index {:version=>/(1)/, :format=>"json"}
GET /:version/posts/:id(.:format) posts#show {:version=>/(1)/, :format=>"json"}
This means that my API routes are actually pointing to http controller and not API controller. How can I point my API routes to API/posts#search instead?
Given this is your 2nd question tonight on the basics of Rails routing, I strongly recommend reading the Rails Guide on the topic.
For this issue, you're looking for a scope. This is explained in the guide above.
api version: 1 do
scope module: "api" do
resources :posts, only: [:index, :show] do
collection do
get 'search'
end
end
end
end
Also
Your directory should be named app/controllers/api, not app/controllers/API
Your controller should be at app/controllers/api/posts_controller.rb with class name like class Api::PostsController < ApplicationController
I should also mention, I don't know or use rocket_pants, but their README suggests namespacing controllers for different versions in modules as well (another level of scoping above).
Better "pants rockety" answer.
routes.rb
api :version => 1, module: "api" do
resources :foobars
folder structure
-controllers
-api
foobars_controller.rb
etc
api_controller.rb
class ApiController < RocketPants::Base
foobars_controller.rb
class Api::EventsController < ApiController
version 1
etc
Related
I'm working on creating a wiki app from scratch with the following organization:
Main Controller: Wiki
Nested Controller: WikiCategories
Nested Controller: WikiArticles
In my config/routes.rb I have:
resource :wiki do
resources :wiki_categories, :as => :categories
resources :wiki_articles, :as => :articles
end
I've chosen to name the categories and articles controllers as WikiCategories and WikiArticles to differentiate from other category and article controllers that I want to make in the future under a blog nesting.
This gives me the following routes:
/wiki/wiki_categories/new
/wiki/wiki_articles/new
Is there any way to rewrite the routes to be:
/wiki/categories/new
/wiki/articles/new
... while still using the WikiCategories and WikiArticles controller names?
I've chosen to name the categories and articles controllers as WikiCategories and WikiArticles to differentiate from other category and article controllers that I want to make in the future under a blog nesting.
IMO, it seems like you're bucking convention a bit. As discussed in Controller Namespaces and Routing, why not do:
namespace :wiki do
resources :categories, :articles
end
Which will give you:
wiki_categories GET /wiki/categories(.:format) wiki/categories#index
POST /wiki/categories(.:format) wiki/categories#create
new_wiki_category GET /wiki/categories/new(.:format) wiki/categories#new
edit_wiki_category GET /wiki/categories/:id/edit(.:format) wiki/categories#edit
wiki_category GET /wiki/categories/:id(.:format) wiki/categories#show
PATCH /wiki/categories/:id(.:format) wiki/categories#update
PUT /wiki/categories/:id(.:format) wiki/categories#update
DELETE /wiki/categories/:id(.:format) wiki/categories#destroy
wiki_articles GET /wiki/articles(.:format) wiki/articles#index
POST /wiki/articles(.:format) wiki/articles#create
new_wiki_article GET /wiki/articles/new(.:format) wiki/articles#new
edit_wiki_article GET /wiki/articles/:id/edit(.:format) wiki/articles#edit
wiki_article GET /wiki/articles/:id(.:format) wiki/articles#show
PATCH /wiki/articles/:id(.:format) wiki/articles#update
PUT /wiki/articles/:id(.:format) wiki/articles#update
DELETE /wiki/articles/:id(.:format) wiki/articles#destroy
Then, create namespaced controllers, something like:
app/controllers/wiki/categories.rb
class Wiki::CategoriesController < ApplicationController
...
end
and
app/controllers/wiki/articles.rb
class Wiki::ArticlesController < ApplicationController
...
end
Yes it is by specifying the controller, the resource can then be named whichever way you like.
resource :wiki do
resources :categories, controller: 'wiki_categories'
resources :articles, controller: 'wiki_articles'
end
Please see the guide for further information.
You can use the path: option as follows:
resource :wiki do
resources :wiki_categories, path: 'categories', :as => :categories
resources :wiki_articles, path: 'articles', :as => :articles
end
Which will give you:
/wiki/categories/...
/wiki/articles/...
See Translated Paths section of the guides for further details.
When you use the namespace method to create an admin area, you are presented with these routes:
resources :stories
namespace :control_panel do
resources :stories
end
gives me:
control_panel_stories GET /control_panel/stories(.:format) control_panel/stories#index
POST /control_panel/stories(.:format) control_panel/stories#create
new_control_panel_story GET /control_panel/stories/new(.:format) control_panel/stories#new
edit_control_panel_story GET /control_panel/stories/:id/edit(.:format) control_panel/stories#edit
control_panel_story GET /control_panel/stories/:id(.:format) control_panel/stories#show
PATCH /control_panel/stories/:id(.:format) control_panel/stories#update
PUT /control_panel/stories/:id(.:format) control_panel/stories#update
DELETE /control_panel/stories/:id(.:format) control_panel/stories#destroy
Rails seems to be pushing me towards creating two controllers for the Story resource. One at app/controllers/stories_controller.rb and one at app/controllers/control_panel/stories_controller.rb
Should I use these two controllers? If I were to just use stories_controller, it would save a file, but it would be fiddly having to redirect back to the control_panel namespaced views in every single action if the user is admin. Should I use two controllers?
Use the controller option.
Something like:
namespace :control_panel do
resources :stories, controller: 'stories'
end
For custom actions use actions option
resources :stroies, actions: [:index, :show]
namespace :control_panel do
resources :stories, controller: 'stories', except: [:index, :show]
end
So you can see stories without namespace, but managing them works just in control_panel namespace.
Additional, try active_admin gem for administration. It is easy and helpful
If you have a namespaced controller, it basically puts it in another folder
There's some important inheritance stuff that goes on in the backend, but simply, you'll have another folder called apps/controllers/control_panel which you'll have to add the file to:
#app/controllers/control_panel/stories_controller.rb
Class ControlPanel::StoriesController < ApplicationController
# stuff
end
This is different to your "standard" controller, which will just reside in the standard controllers section. This is a great tutorial for you to see how this works
DRY
You may wonder why you'd use this if it wasn't DRY
The answer is the two controllers allow you to perform different tasks / functionality. For example, in our admin areas, we use this:
#config/routes.rb
resources :stories, only: [:index, :show]
namespace :admin do
resources :stories, except: :show
end
This gives us the ability to define the actions which each controller can perform (making it more secure). You can use #asiniy's solution, but it will put all your code in one controller, which could be a problem
I'm new to Ruby and Ruby on Rails. I've got an installation of Refinery CMS in which I've created two extensions that are related. I pretty much followed this guide. I've got it all working, except that for my second resource (event_types), I'm not able to view them from the front end. The link to view the Event Types goes to localhost:3000/events/event_types, and that makes the events viewer think I'm trying to look at an event with ID "event_types", and I get a RecordNotFound error. What is set up wrong? It seems like it's something wrong with routes, but I don't know what to change.
Can someone point me in the right direction?
Rails routes are matched in the order they are specified so you have to take care about order in config/routes.rb file.
For example given in guide, in file vendor/extensions/events/config/routes.rb you should put event_type resource routes above event resource route.
# Frontend routes
namespace :events do
resources :event_types, :only => [:index, :show]
end
# Frontend routes
namespace :events do
resources :events, :path => '', :only => [:index, :show]
end
To better understand Rails routes you can check http://guides.rubyonrails.org/routing.html
I was reading Rails routes guide and came to this part:
If you want to route /posts (without the prefix /admin) to Admin::PostsController, you could use:
scope module: 'admin' do
resources :posts, :comments
end
Ok I understood this part, it says if we use scope the way it shows us, instead of for example /admin/posts we can directly say /posts
But I didn't underatand the second part below: What does this one do?
If you want to route /admin/posts to PostsController (without the Admin:: module prefix), you could use:
scope '/admin' do
resources :posts, :comments
end
How about this:
Use if you want to have controller in namespace ONLY, but don't want namespaced url for this controller
Use if you want namespaced url ONLY but not controller
I'm trying to create a namespaced API in rails and am running into an issue
# Resources
resources :users do
resources :contacts
end
#==========================================>
# API namespacing and routing
#==========================================>
namespace :api do
namespace :v1 do
# =======================>
# Resources -> Users
# Resources -> Contacts
# =======================>
resources :users do
resources :contacts
end
# =======================>
# Resources -> Messages
# Resources -> Transcriptions
# =======================>
resources :messages do
resources :transcriptions
end
end
end
I want to have my html-responding version of the resource outside of the 'api' namespace (i.e. in the regular app/controllers/users_controller.rb area) but my json-responding inside the namespace.
However when I point my url at the "/api/v1/users.json" link it utilizes the controller specified by the OUTSIDE resources app/controllers/users_controller rather than the one I put in app/controllers/api/v1/users_controller.
Am I only allowed one resources reference despite it being namespaced differently?
Why exactly is this happending
Your routing definitions look ok. The first thing I'd check is what routes are generated by your rails router by running:
$ bundle exec rake routes | grep users
You should have your defined users routes mapped to their respective URL structure. If something's amiss then your routes aren't probably defined correctly. Which i doubt in your case.
Another possible issue might be your controller class name in your namespaced users controller. So your users controller under app/controllers/api/v1 should be
class Api::V1::UsersController < ApplicationController
....
end
Look at the Rubygems.org source which has the same kind of structure you're trying to implement.
your controller should look like
module Api::V1
class UserController < ActionController::Base
...
end
end