Reputation: 51
Hey any help would be appreciated!
Basically I have two models - User (using Devise) and Sport
class User < ApplicationRecord
has_and_belongs_to_many :sports
end
class Sport < ApplicationRecord
has_and_belongs_to_many :users
end
I have a predefined list of Sports that are seeded into my database (e.g. Running, Weightlifting etc). What I want to do is have a user login and then select which sports they do and have that saved through an association. This then allows the user to search for and see what sports other users do etc.
I have managed to create associations through the console like this:
user = User.find(1)
sport = Sport.find(1)
user.sports << sport
but I can't figure how to translate that to a form.
So far I've got this even though all it does is create a new Sport (which I don't want):
#sports_controller.rb
def index
@sports = Sport.where(["name ILIKE ?", "%#{params[:search]}%"])
end
def new
@sport = Sports.new
end
def create
@sport = current_user.sports.create(sports_params)
end
private
def sports_params
params.require(:sport).permit(:name)
end
and then for my form:
#sports/new.html.erb
<%= form_for @sport do |f| %>
<div class="form-group">
<%= f.label :exercises %><br>
<%= f.collection_check_boxes :name, Sport.all, :id, :name %>
</div>
<%= f.button :submit %>
<% end %>
Is it right doing it through this controller? I'm really lost as to how to do this and it's a core functionality for my uni project.
Thanks in advance!
Upvotes: 1
Views: 47
Reputation: 2970
Firstly I would get rid of your SportsController, this feels like you are updating a User only. The SportsController would be for creating Sports themselves, which you don't need to do as you are seeding them)
So if you haven't got one already, add the user routes (this won't allow updating devise fields e.g password, but that's outside of the scope of this question):
resources :users
Then in your ApplicationController, add this method:
def after_sign_in_path_for(_resource)
edit_user_path(current_user)
end
That will redirect the user after signin to their edit page.
Finally the form:
#users/edit.html.erb
<%= form_for @user do |form| %>
<% @sports.each do |sport| %>
<%= check_box_tag "user[sport_ids][]", sport.id, form.object.sports.include?(sport) %>
<%= sport.name %>
<% end %>
<%= f.button :submit %>
<% end %>
This will pass up an array of sport_ids, which will automatically associate all the selected sports with your user, due to Rails magic :). The magic being you can also associate objects like so:
@model.associated_model_ids << [1,2,3]
And your UsersController:
def UsersController < ApplicationController
def edit
@user = User.find(params[:id])
@sports = Sport.all.order(name: :asc)
end
def update
@user = User.find(params[:id])
if @user.update(user_params)
redirect_to @user
else
render 'edit'
end
end
def show
@user = User.find(params[:id])
end
private
def user_params
params.require(:user).permit(sport_ids: [])
end
end
You will need to add the user show.html.erb template but that should be enough to get you going. I think there is a nicer way to do the checkboxes so I might update this later, but that should work.
Example to see if it worked:
#users/show.html.erb
<%= @users.sports.map(&:name).join(', ') %>
Upvotes: 1