ruby-on-railsruby-on-rails-5

collection_check_boxes messes with update values


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?


Solution

  • 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