In my Rails 5 project I have 3 models, User
, Book
, and UserBook
. Basically the user_books table is a connecting table connecting users to books.
This is my UserBook model
class UserBook < ApplicationRecord
belongs_to :user
belongs_to :book
end
This is my Book model
class Book < ApplicationRecord
has_many :user_books
end
And lastly this is my user model
class User < ApplicationRecord
has_many :user_books
has_many :books, through: :user_books
before_update :set_user
private
def set_user
return unless User.current
self.updated_by = User.current
end
end
My controller action is as follows
class UserController < BasicCrudController
def update
if user.update(user)
redirect_to user_path(user), notice: 'User was successfully updated.'
else
render :edit
end
end
private
def user
@user ||= User.build(params[:user])
end
def user_params
params.require(:user).permit(:name, book_ids: [])
end
end
This setup was working fine until I added the :book_ids in my params. Then the updated_by started getting set to blank on update if I update :book_ids. Upon research I confirmed that if there's a collection before_update is not triggered.
I therefore tried to merge updated_by to params by various methods. Example:
def user_params
params.require(:user).permit(:name, book_ids: []).tap do |whitelisted|
whitelisted[:updated_by_id] ||= current_user.id
end
end
No matter what I try however it seems just updating the values of book_ids automatically set updated_by_id to nil
What's going on? And how can I fix this problem?
You could use collection_check_boxes
in your form to allow multiple selections. For example, if you have a User model and a Book model, and you want to assign books to a user:
<%= form_for @user do |f| %>
<%= f.collection_check_boxes :books_ids, Book.all, :id, :name %>
<%= f.submit %>
<% end %>
strong params for your controller:
params.require(:user).permit(:name, ..., ..., books_ids: [])
https://apidock.com/rails/v4.0.2/ActionView/Helpers/FormOptionsHelper/collection_check_boxes