There are some other Qs (1 2) but unfortunately they don't help.
I have an event resource, and a namespaced event_participant. The routes, actions, etc look good, but when I attempt to click a link_to to my custom, namespaced action the route is mapped to the events#update controller. No idea what's going wrong!
config/routes.rb
Rails.application.routes.draw do
resources :events
namespace :events do
put "/:id/add_or_rm_role" => "participants#add_or_rm_role"
end
end
rake routes
Prefix Verb URI Pattern Controller#Action
events GET /events(.:format) events#index
POST /events(.:format) events#create
new_event GET /events/new(.:format) events#new
edit_event GET /events/:id/edit(.:format) events#edit
event GET /events/:id(.:format) events#show
PATCH /events/:id(.:format) events#update
PUT /events/:id(.:format) events#update
DELETE /events/:id(.:format) events#destroy
PUT /events/:id/add_or_rm_role(.:format) events/participants#add_or_rm_role #This one looks good!
participants_controller.rb
class ParticipantsController::EventsController < ApplicationController
load_and_authorize_resource
def add_or_rm_role
event = Event.find(event_participants_params.event_id)
#add user role to event...
redirect_to event, notice: 'Changes have been saved!'
end
private
def event_participants_params
params.permit(:role, :is_add, :event_id, :user_id)
end
end
The events_controller.rb is the autogenerated one.
The link_to on events/show is
<%= link_to "Sign Up For Event",
event_path(role: Event::Participant.event_role_types[:participant], is_add: false, id: @event.id),
action: :add_or_rm_role,
method: :put, remote: true %>
When I click the link, the following PUT request is sent. You can see it is processing the wrong link as the wrong format. The link_to is a little button that adds the current_user as a participant to a given event.
Started PUT "/events/_ceEY?is_add=false&role=3" for 127.0.0.1 at 2017-07-31 20:05:10 -0400
Processing by EventsController#update as JS
Parameters: {"is_add"=>"false", "role"=>"3", "id"=>"_ceEY"}
#......
Any idea on what wires are getting cross here?
UPDATE
The following answers suggest using a nested route instead of a namespaced one, but I'd like to keep trying to get namespaced routes to work to improve my organization/file structure in my controller. Switching to nested will be the nuclear option, but I'd like to see where this takes me first. Utilizing the current feedback I have made the following changes:
config/routes.rb
#...
namespace :events do
put :add_or_rm_role, to: 'participants#add_or_rm_role'
end
rake routes
Prefix Verb URI Pattern Controller#Action
#...
events_add_or_rm_role PUT /events/add_or_rm_role(.:format) events/participants#add_or_rm_role
link_to
<%= link_to "Sign Up For Event",
events_add_or_rm_role_path(role: Event::Participant.event_role_types[:participant], is_add: false, event_id: @event.id),
method: :put, remote: true %>
events/participants_controller.rb
class Events::ParticipantsController < ApplicationController #Renamed
#...
def event_participants_params
params.permit(:role, :is_add, :event_id, :user_id)
end
end
Despite this the controller#action is still wrong (and thus seems to be adding in the id
param)
Started PUT "/events/add_or_rm_role?event_id=_ceEY&is_add=false&role=3" for 127.0.0.1 at 2017-07-31 21:37:45 -0400
Processing by EventsController#update as JS
Parameters: {"event_id"=>"_ceEY", "is_add"=>"false", "role"=>"3", "id"=>"add_or_rm_role"}
Where did I go wrong (server was restarted)?
UPDATE
If I change the order of my Rails routing (giving add_or_rm_role higher precedence), the correct controller is matched. Is this because my Event IDs are string?
namespace :events do
put :add_or_rm_role, to: 'participants#add_or_rm_role'
end
resources :events
Now the correct action is called but an error is thrown before it can finish: NameError (uninitialized constant Participant):
UPDATE
NameError (uninitialized constant Participant):
was being thrown because I was attempting to authorize (via CanCanCan) a non-resource at the top of Events::ParticipantsController with load_and_authorize_resource
. Since the model is namespaced I need to specify the resource model manually: load_and_authorize_resource class: "Event::Participant"
UPDATE
After fixing all of the above, I recieved the error NoMethodError (undefined method 'event_id' for #<ActionController::Parameters:0x007f791dcbe240>):
, which I thought has something to do with the strong params, but ended up being caused by using dot notation: event_participants_params.event_id
is broken but event_participants_params[:event_id]
works.