How to remove resource name from route helper? - ruby-on-rails

I have a route:
resources :promo_pages, path: 'promo' do
get :promo_rubizza, on: :collection, path: 'rubizza', as: :rubizza
end
This route is created - rubizza_promo_pages_path
But I'd like to have - rubizza_path.
How to implement it?
I wanted to implement this as resources :promo_pages, path: 'promo', as: '', but it created rubizza__index_path
UPD: output rails routes
rubizza_promo_pages GET /promo/rubizza(.:format) promo_pages#promo_rubizza

In routes, please define the following route (put it on the same level as resources, without nesting):
get 'promo/rubizza', to: 'promo_pages#promo_rubizza', as: 'rubizza'
Then, you should be able to use rubizza_path and rubizza_url.

what you can do is define this path in your application controller:
class ApplicationController < ActionController::Base
...
def rubizza_path
rubizza_promo_pages_path
end
helper_method :rubizza_path
end
in your routes.rb:
resources :promo_pages, path: 'promo' do
get :promo_rubizza, on: :collection, path: 'rubizza', as: :rubizza
end
That way, you can still use rubizza_path in your views, helpers, controllers, etc. but it uses the full nested route instead.

Customising the routes names details are available here.
What about defining the path based on controller and action?
get 'promo_pages/promo_rubizza', to: 'promo_pages#promo_rubizza', as: :rubizza
it will return:
Prefix Verb URI Pattern Controller#Action
rubizza GET /promo_pages/promo_rubizza(.:format) promo_pages#promo_rubizza

Related

Rails multiple routes, same `as`

I have the following routes:
authenticated :user do
scope module: 'admin', path: ':publisher_id' do
get 'settings/general', to: 'publishers#index', as: 'publisher_settings'
post 'settings/general', to: 'publishers#create'
put 'settings/general', to: 'publishers#update'
end
end
However the first as: can only be used once. How can I make this apply to all these routes? I want all of them to work for the publisher_settings_path
You can also pass the as option to namespaces and scopes in Rails Routes.
# prefix the routing helper name: +sekret_posts_path+ instead of +posts_path+
scope as: "sekret" do
resources :posts
end
Source: https://api.rubyonrails.org/v5.1/classes/ActionDispatch/Routing/Mapper/Scoping.html
This should also work though i think
Rails.application.routes.draw do
resources :publishers, only: [:create, :update, :index], path: 'settings/general', as: 'publisher_settings'
end
Get's me
publisher_settings GET /settings/general(.:format) publishers#index
POST /settings/general(.:format) publishers#create
publisher_setting PATCH /settings/general/:id(.:format) publishers#update
PUT /settings/general/:id(.:format) publishers#update
publisher_settings_path already returns the path of of the three routes, e.g. /admin/settings/general. So you don't need to set as: multiple times.
And actually setting the same as: multiple times for multiple routes would not make sense, it has to return one value.

Getting 'Unknown action in controller'

I'm getting this error :
"The action 'create' could not be found for ObjectController"
I know it should be obvious but I'm missing something, that's my controller :
class ObjectController < ApplicationController
def index
end
def create
end
end
And that is my routes :
Rails.application.routes.draw do
get 'object/index'
get 'object/create'
match ':controller(/:action(/:id))', :via => :get
resources :objets
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
root 'object#index'
You probably want to scrap those routes and try something simpler like
resources :objects, only: [:get, :create, :show]
Then use
$ rake routes
To make sure your routes are as the should be. You will want a POST route to /objects to create a new object etc..
Ok that one was dumb, actually I had two directories and I wasn't modifying the right one, sorry about that...
Your routes could be greatly improved:
#config/routes.rb
Rails.application.routes.draw do
root 'objects#index'
resources :objects
--
Next, the "standard" way to achieve what you're looking for is to use the new action; IE not the "create" action. If you wanted to use the create path name (instead of new), you'll be able to define it in the path_names argument:
#config/routes
resources :objects, path_names: { new: "create", create: "create" } #-> url.com/objects/create
To understand why you should be using new instead of create, you should look up resourceful routing, and how it pertains to object orientated programming.
Finally, your controller should be named in the plural:
#app/controllers/objects_controller.rb
class ObjectsController < ApplicationController
...
end
Whilst you can call it whatever you like, Rails defaults to plural controller names, singular model names.

Why is custom action for resource not working?

I have an AppleController
it has a def sliceme method
when I go to: /apple#sliceme
it routes to #index
In my routes.config I have
resources :apples
Why?? And what is the correct route??
Resources will create the CRUD method routes (see here)
If you want to specificity another route you can specify it like so in your routes file:
get "apple/sliceme", to: "apple#sliceme"
Or
resources :apple do
get :sliceme, on: :collection
end
To check what routes actually exist, run rake routes in the terminal

Routing to non-restfull controller

I have a controller Sagepay, which have number of custom method (not RESTfull resources). How can I write routes for those actions? So far I tried:
namespace :sagepay, controller: :sagepay, as: :sagepay do
post :notification
get :iframe_breaker
get :accept_payment
end
This however tries mapping to sagepay/sagepay_controller instead simple sagepay_controller.
Obviously I can do this:
match '/sagepay/notification' => 'sagepay#notification', via: :post, as: sagepay_notification
(etc)
which works, but this is not a solution I am looking for. Is there any way I can write it in common block?
The reason you get sagepay/sagepay_controller is the reason why namespaces are used. In order to get sagepay/notification you can define a resource and add collection routes within it, as follows:
# config/routes.rb
resource :sagepay, controller: :sagepay do
collection do
post :notification
get :iframe_breaker
get :accept_payment
end
end
Update:
In order to define only the routes defined within the collection and avoid definition of the seven restful routes that Rails create you can pass in only option to the resource definition as follows:
# config/routes.rb
resource :sagepay, controller: :sagepay, only: [] do
collection do
post :notification
get :iframe_breaker
get :accept_payment
end
end
I think I found the solution:
scope 'sagepay', controller: :sagepay, as: :sagepay do
post :notification
get :iframe_breaker
get :accept_payment
end

Routing Error: uninitialized constant

I'm trying to set up routes for a mobile API, which should have a versioned api-path. I already could make the mobile Auth work, which is implemented in a separate Controller AuthController located in /controllers/api/v1/mobile/.
Usage example:
myapp.com/api/v1/mobile/auth
But now I want to register my existing ressources-Controllers to this path-pattern as additional api-routes. Concrete: this would be the TasksController located at /controllers/tracker/tasks_controller.rb. So I added a mobile route to the routes-definition:
# routes.rb
namespace :tracker, path: 'timetracking' do
resources :tasks, 'jobs'
end
namespace :api do
namespace :v1 do
namespace :mobile do
resources :auth, :only => [:create, :destroy]
namespace :tracker do #added mobile route
resource :tasks, controller: 'tracker/tasks', as: :mobile_tasks
end
end
end
end
But when I call myapp.com/api/v1/mobile/tracker/tasks it results in an error-message:
Routing Error
uninitialized constant Api::V1::Mobile::Tracker
I especially added the alias :mobile_tasks to this route, to avoid any conflicts with the original tasks-route above. Any ideas, how to set the controller properly for this route?
Update#1
Defining this route as a scope instead of a namespace, didn't work aswell.
scope "/api/v1/mobile/tracker" do
resources :tasks, controller: 'tracker/tasks', as: :mobile_tasks
end
But this time, it didn't even resolve the route-path itself.
Routing Error
No route matches [GET] "/api/v1/mobile/tracker/tasks"
I assume it might be a problem, that my additional mobile-api route tries to point to a completely different namespace tracker.
According to http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing you should use scope instead of namespace.
If you want to route /admin/posts to PostsController (without the Admin:: module prefix), you could use:
scope "/admin" do
resources :posts, :comments
end
Adding this answer to get clarity on namespace & scope.
When you use namespace, it will prefix the URL path for the specified resources, and try to locate the controller under a module named in the same manner as the namespace.
# config/routes.rb
namespace :admin do
resources :posts, only: [:index]
end
# rake routes
Prefix Verb URI Pattern Controller#Action
admin_posts GET /admin/posts(.:format) admin/posts#index
When we add scope, it will just map the controller action for the given scope patterns. No need to define controller under any module.
# config/routes.rb
scope :admin do
resources :posts, only: [:index]
end
# rake routes
Prefix Verb URI Pattern Controller#Action
admin_posts GET /admin/posts(.:format) posts#index
Note that, controller is just posts controller without any module namespace.
If we add a path option to scope it will map to the controller with the path option specified as follows
# config/routes.rb
scope module: 'admin', path: 'admin' do
resources :posts, only: [:index]
end
# rake routes
Prefix Verb URI Pattern Controller#Action
admin_posts GET /admin/posts(.:format) admin/posts#index
Note that the controller now is under admin module.
Now, if we want to change the name of path method to identify resource, we can add as option to scope.
# config/routes.rb
namespace module: 'admin', path: 'admin', as: 'root' do
resources :posts, only: [:index]
end
# rake routes
Prefix Verb URI Pattern Controller#Action
root_posts GET /admin/posts(.:format) admin/posts#index
You can see the change in the Prefix Verb.
Hope it helps others.
Late answer, but still might be helpful:
scope '/v1' do
resources :articles, module: 'v1'
end
controller
# app/controller/v1/articles_controller.rb
class V1::ArticlesController < ApplicationController
end
Now you should be able to access this url:
http://localhost:3000/v1/articles

Resources