Updated answer:
If I got the relationships right:
# models/event.rb
class Event < ApplicationRecord
has_many :user_event_states
has_many :users, through: :user_event_states
end
# models/user.rb
class User < ApplicationRecord
has_many :user_event_states
has_many :events, through: :user_event_states
accepts_nested_attributes_for :user_event_states
end
# models/user_event_state.rb
class UserEventState < ApplicationRecord
belongs_to :event
belongs_to :user
accepts_nested_attributes_for :user_event_states
end
And I understand your goal:
I would like to have buttons for each user and update only the state from the selected user
Then here are some things I would change:
Create a UserEventStatesController
:
# app/controllers/user_event_states_controller.rb
class UserEventStatesController < ApplicationController
before_action :set_event
before_action :set_user_event_state, only: %i[show edit update destroy]
before_action :set_user, only: %i[show edit update destroy]
...
def update
if @user_event_state.update(user_event_state_params)
# action to perform on success
else
# action to perform on fail
end
end
...
private
def set_event
@event = Event.find(params[:event_id])
end
def set_user_event_state
@user_event_state = @event.user_event_states.find(params[:id])
end
def set_user
@user = @user_event_state.user
end
def user_event_state_params
params.require(:user_event_state).permit(:event_id, :user_id, :state)
end
end
And change your EventsController
back to a more standard controller:
#app/controllers/events_controller.rb
before_action :set_event, only: %i[ show edit update destroy]
def show
# get *ALL* UserEventStates for this Event
@ues_events = UserEventState.where(event_id: @event.id)
end
private
def set_event
@event = Event.find(params[:id])
end
def event_params
params.require(:event).permit(:description, :date, :meeting_time, :start_time, :end_time)
end
Nest UserEventState
routes under Event
:
# config/routes
devise_for :users
resources :events do
resources :user_event_states
end
Run rails routes
from your terminal to check the prefixes of the routes. Should look like this:
$ rails routes
Prefix Verb URI Pattern Controller#Action
...
event_user_event_states GET /events/:event_id/user_event_states user_events_states#index
POST /events/:event_id/user_event_states user_events_states#create
new_event_user_event_state GET /events/:event_id/user_event_states/new user_events_states#new
edit_event_user_event_state GET /events/:event_id/user_event_states/edit user_events_states#edit
event_user_event_state GET /events/:event_id/user_event_states/show user_events_states#show
PATCH /events/:event_id/user_event_states/:id user_events_states#update
PUT /events/:event_id/user_event_states/:id user_events_states#update
DELETE /events/:event_id/user_event_states/:id user_events_states#destroy
Now to views:
#app/views/events/show.html.erb
<% @ues_events.each do |ues_ev| %>
<%= ues_ev.user.email %>
<%= ues_ev.state %>
<%= ues_ev.night %>
<% form_with model: ues_ev, url: [@event, ues_ev] do |form| %>
<%= form.text_field :state %> <!-- or whatever kind of input :state needs to be -->
<%= form.submit 'Zusagen' %>
<% end %>
The form should submit a PATCH request to /events/:event_id/user_event_states/:id
, which will hit the UserEventStatesController#update
action.
The params[:user_event_state]
should be { state: 'form response' }
upgrade idea:
Submitting a form and getting redirected can be slow and not very smooth in terms of user experience.
Say you want to say right on the events#index
page and just click buttons to toggle the state for a few users.
You could look at replacing your forms with buttons or links that use:
First answer:
get 'right route'
can be whatever you want, as long as it is a viable URI path.
Any symbols in the path are accessible via params
So get 'events/:events_id/users/:id/update-event-state' to: ...
Would have params[:event_id]
and params[:id]
.
Since it looks like you need only :event_id
params, it doesn't have to include user.
get 'events/:event_id/user-state', to: ...
But it also doesn't have to follow convention:
get 'foo/bar/baz/:event_id', to: ...
If you want to nest the route, you can, but you lose control over what the URL will be:
resources :events do
# url would be events/:id/update_user_event_state
get :update_user_event_state, on: :member
resources :users do
# url would be events/:event_id/users/update_user_event_state
get :update_user_event_state, on: :collection
# url would be events/:event_id/users/:user_id/update_user_event_state
get :update_user_event_state, on: :member
end
end
Also, I think you have a typo. It should be like this, I think:
def update_user_event_state
@ues_event.update(state: 1)
# not self.update
end