0

I’m trying to update an attribute on a show page, keeping it in the show page, that is connected through a different table. For example: manager logs into admin site and sees several resources, clicks on one and can see all users that have access to the resource (either approved or pending). They can currently delete a user’s access. What I’m trying to do is allow the manager to change the status of the request say from pending to approved.

So for my models I have the following:

class TrainingResource
  has_many :user_training_resources, dependent: :destroy
end

class UserTrainingResource
  belongs_to :user
  belongs_to :training_resource
 enum status: [:pending, :confirmed, :rejected]

end

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

TrainingResourcesController

class Admin::TrainingResourcesController < 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 index
    @training_resources = TrainingResource.paginate(page: params[:page])
    @training_resources = @training_resources.search(params[:search]) if params[:search]
    respond_with(@training_resources)
  end

  def show
    respond_with @training_resource
  end

  def new
    @training_resource = TrainingResource.new
    respond_with(@training_resource)
  end

  def create
    @training_resource = TrainingResource.new(training_resource_params)
    flash[:notice] = 'TrainingResource created successfully' if @training_resource.save
    respond_with @training_resource, location: admin_training_resources_path
  end

  def edit
    respond_with(@training_resource)
  end

  def update
    flash[:notice] = 'TrainingResource updated successfully' if @training_resource.update(training_resource_params)
    respond_with @training_resource, location: admin_training_resources_path
  end

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

  private

  def load_training_resource
    @training_resource = TrainingResource.find_by!(id: params[:id])
  end

  def training_resource_params
    params.require(:training_resource).permit(:name, :description, :total_subscriptions, :url)
  end
end

UserTrainingResourcesController, which is pointing to the TrainingResourcesController

class Admin::UserTrainingResourcesController < Admin::ApplicationController
  belongs_to_app :training_resources
  add_breadcrumb 'Training Resources', :admin_training_resources_path
  before_action :load_training_resource
  respond_to :html, :json

  def edit
    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

Training Resource Show

  <tbody>
    <% @training_resource.users.each do |training| %>
      <tr>
        <td><%= training.full_name %></td>
        <% utr = training.user_training_resources.where(training_resource: @training_resource).first %>
        <td><%= utr.status.capitalize %>
          <%= form_tag '/user_training_resource/edit', :method => :get do %>
            <%= select_tag( :user_training_resources_id, options_for_select(['pending', 'confirmed', 'rejected']))%>
            <%= submit_tag 'Edit Status', class: 'btn btn-default btn-sm' %>
        <% end %>

        <%= tb_form_for [:admin, @training_resource], :remote => true, :data => {:errors => :inline, :success => admin_user_training_resources_path} do |f| %>
          <%= tb_form_errors(f.object, :base) %>
          <%= f.tb_select :name, options_for_select(holder, :status) %>
          <%= f.tb_save_buttons('User Training Resource', admin_user_training_resources_path) %>
        <% end %>
        </td>
        <td class="table-actions">
          <%= link_to 'Edit', edit_admin_user_training_resource_path(training), :class => 'btn btn-default btn-sm' %>
          <%= 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 %>
  </tbody>

User Training Resource Helper, Holder Method

  def holder
    TrainingResource.all.each(&:id)
  end

The link to Edit I’ll end up taking out because it pushes the user to the UserTrainingResource edit page and I want to keep it on the current page. The top form with the select_tag isn’t actually reading in the current status and then the submit_tag is redirecting the page.

My latest attempt is the bottom form_for. This is pulling in the TrainingResource and not the UserTrainingResource data. When I change the tb_select to :status, options_for_select(holder, :status) I end up with undefined method `status’. It looks like it’s only aiming at TrainingResource. I’ve also tried:

Thought here that it would pull in the default status and then allow the options to change. Still have an issue with undefined method of ‘status’ and even then there’s the issues with save.

I’ve also tried:

In this case I end up with undefined method ‘map’. Which I've tried to pinpoint down with attempting pluralization on @training_resource and @user_training_resource but that turns up First argument in form cannot contain nil or be empty.

Edit:

Tried in the UserTrainingResourcesController:

def set_to_confirmed
 @user_training_resource = UserTrainingResource.find(params[:user_training_resource])
end

Then in the show

              <%= link_to 'Confirmed', {:controller => 'user_training_resources', :action => 'set_to_confirmed', :status => @training_resource.user_training_resource }, :class => 'btn btn-default btn-sm'%>

Although no errors on the page load when clicking on the link I get:

Requested URL: https://localhost:3000/admin/set_to_confirmed?status=%23%3CUserTrainingResource%3A%3AActiveRecord_Associations_CollectionProxy%3A0x00007f93ee8b0f90%3E

Latest attempt using the following:

        <% @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.select(:user_training_resource_id, options_for_select(['pending', 'confirmed', 'rejected']), :selected => utr.status)%>
               <%= f.tb_save_buttons('', admin_training_resources_path) %>
             <% end %>
        </td>

This will show only the options, which is good, but I need it to default to what's current in the database and the save isn't sticking.

Jake
  • 1,328
  • 1
  • 21
  • 51

1 Answers1

0

If I get the point, you need to update the joining table UserTrainingResource changing the status column.

I probably would create three actions in Admin::UserTrainingResourcesController:

def set_to_pending
end

def set_to_confirmed
end

def set_to_rejected
end

Then I would add three link to each row in the table in TrainingResource#Show passing the necessary parameters to complete the action, like explained in this post: pass parameter by link_to ruby on rails

iGian
  • 11,023
  • 3
  • 21
  • 36
  • I do need to update the joining table with the ability to change the status column. So I actually put in the following: <%= link_to 'Confirmed', {:controller => 'user_training_resources', :action => 'set_to_confirmed', :status => @training_resource.user_training_resource }, :class => 'btn btn-default btn-sm'%>. After putting in the methods, updating the routes, it ends up with a 404 Not Found when clicking the link. There's also the major annoyance that it would be three buttons as opposed to say a drop down and save. – Jake Aug 13 '18 at 16:32
  • You can also use the dropdown as you like posting to action `update_status`, which trigger one of the three the actions based on params. This can also be useful: https://stackoverflow.com/questions/13414663/using-rails-link-to-for-links-that-post – iGian Aug 13 '18 at 16:41