Jake
Jake

Reputation: 1380

Rails form drop down select data from database pulled from a different table

I have three models that are connected like the following

Users
has_many :training_resources, through: :user_training_resources
has_many :user_training_resources, dependent: :destroy

TrainingResources
has_many :user_training_resource, dependent: :destroy
has_many :users, through: :user_training_resource

UserTrainingResources
belongs_to :user
belongs_to :training_resource

I'm trying to build out a form on my TrainingResource show page to allow the user to change the status of a UserTrainingResource and it's failed pretty miserably.

This is the latest attempt:

        <% @training_resource.spud_users.each do |training| %>
      <tr>
        <td><%= training.full_name %></td>
        <% utr = training.user_training_resources.where(training_resource: @training_resource).first %>
        <td>
             <%= tb_form_for [:admin, @training_resource], :remote => true, :data => {:errors => :inline, :success => admin_training_resources_path} do |f| %>
               <%= f.collection_select :user_training_resource_ids, @training_resource, :id, :name %>
               <%= f.tb_save_buttons('', admin_training_resources_path) %>
             <% end %>
        </td>
        <td class="table-actions">
          <%= link_to 'Delete', admin_user_training_resource_path(training), :method => :delete, :data => {:confirm => 'Are you sure you want to delete this?'}, :class => 'btn btn-danger btn-sm'  %>
        </td>
      </tr>
    <% end %>

The delete works fine but the select at the moment errors out with: undefined method 'map'.

I've also tried:

<%= f.select(:user_training_resource_ids, UserTrainingResource.pluck(:status, :id))%>

No error on the page but the options displayed appear to display the current status for ALL UserTrainingResource. Plus it's not actually saving a change.

I've tried:

<%= f.select(:user_training_resource_ids, options_for_select(['pending', 'confirmed', 'rejected'], selected: utr.status))%>

This actually does present the options because I'm being explicit and it's actually showing the current status. However it's not saving when a selection is made.

Is this just a simple issue of a wrong route? Is there a better way to select data from a different table in a rails drop down?

Edit:

Here's the UserTrainingResources Controller. It's pointing to the TrainingResources Controller's Admin:

class Admin::UserTrainingResourcesController < Admin::ApplicationController
 belongs_to_app :training_resources
 add_breadcrumb 'Training Resources', :admin_training_resources_path
 before_action :load_training_resource, only: [:show, :edit, :update, :destroy]
 respond_to :html, :json

 def new
   @user_training_resource = UserTrainingResource.new
   respond_with @user_training_resource
 end 

 def edit
  respond_with @user_training_resource
 end

 def show 
  respond_with @user_training_resource
end

def update 
  flash[:notice] = 'UserTrainingResource updated successfully' if @user_training_resource.update(user_training_resource_params)
  respond_with @user_training_resource, location: admin_training_resources_path
end

def destroy
  flash[:notice] = 'UserTrainingResource deleted successfully' if @user_training_resource.destroy
  respond_with @user_training_resource, location: admin_training_resources_path
end

private

def load_training_resource
  @user_training_resource = UserTrainingResource.find_by!(id: params[:id])
end

def user_training_resource_params
  params.require(:user_training_resources).permit(
  :training_resources_id, :status).merge(user_id: current_user_id)
end

end

Another edit: Routes

I feel like this is an issue with saving to the correct place so I've included below the routes for user_training_resources:

get '/user_training_resources' => 'user_training_resources#index'
delete '/user_training_resources/:id' => 'user_training_resources#destroy', as: :destroy_utr
put '/user_training_resources/:id' => 'user_training_resources#update', as: :update_utr

Upvotes: 2

Views: 1019

Answers (3)

Jake
Jake

Reputation: 1380

The issue is actually the form_for being passed to the wrong url. Changed it to reflect a new path url: admin_update_utr_path(utr)

Upvotes: 2

Troy
Troy

Reputation: 5419

It may well be the route - the route for the form using the POST or PATCH (not sure which) method while your route is expecting a PUT method.

To confirm, check your console to see if the route is resolving to the correct controller action. If not, you can either change the routes to be like:

post '/user_training_resources/:id' => 'user_training_resources#update', as: :update_utr

or patch '/user_training_resources/:id' => 'user_training_resources#update', as: :update_utr

Upvotes: 0

byakugie
byakugie

Reputation: 663

I think you need to set "multiple" because @training_resource can has many "user_training_resource_ids"

try this :

<%= f.collection_select :user_training_resource_ids, current_user.user_training_resources, 
                        :id, :name, 
                        {:prompt => "Please select training resources"}, 
                        {:multiple => true} %>

source : https://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_select

Upvotes: -1

Related Questions