Codejoy
Codejoy

Reputation: 3806

dealing with select_tags in controller after a submit

Trying to figure out how to use section

3.2 Select Boxes for Dealing with Models http://guides.rubyonrails.org/form_helpers.html

With my deeply nested models. (A provider can have a provider location, which is a join on provider id and group locationid. A group location is a group and an address). This is the nesting of like how do I deal/consume the data thats in those select boxes once the user adds/removes locations that way.

enter image description here

This takes all the group locations and lists them and lets me add them to the current provider under proivder_locations.

Basically get what is working 'dumbly' on the controller side upon f.submit

Flow is:

User creates a provider, then the show it asks if they would like to add location to their newly created provider. If so it takes them to add_location.html.erb file where they have two select boxes. One with all the locations they can add and one that shows any current locations the provider already has.

I have the page handling displaying of the right locations and that and handling the form adding/deleting. This is great, but the form_for breaks (see bottom) and even then I have no idea how to handle or deal with the data that is on the client side in these select tags. Do I consume it in the controller somehow? Again the section 3.2 talks about it but the part that really stumps me is it doesn't seem applicable to my models in their 3.2 section.

(Side note, I had that f.form_for in there not really tested, without it the form works great in terms of buttons adding subtracting from the lists on the html side, with it breaks when I click any of the buttons to add/remove things from lists) (error screen shot at bottom)

All the code:

Provider.rb

class Provider < ActiveRecord::Base

    validates :first_name, presence: true
    validates :last_name, presence: true
    #validates :credentialing_contact, presence: true

    has_many :provider_locations
    has_many :group_locations, through: :provider_locations
    has_many :groups, through: :group_locations 
    belongs_to :designation
    belongs_to :specialty
    #has_many :provider_locations
    has_many :invoices
    has_many :provider_terms
end

provider_location.rb

class ProviderLocation < ActiveRecord::Base
  belongs_to :provider  
  belongs_to :group_location

end

group_location.rb

class GroupLocation < ActiveRecord::Base  
  belongs_to :address
  belongs_to :group
  has_many :provider_locations
end

providers_controller.rb

class ProvidersController < ApplicationController
    before_action :set_provider, only: [:show, :edit, :update, :destroy]


  def index
    @providers = Provider.all
  end

  def show
    #@provider = Provider.find(params[:id])
  end

  def new
    @provider=Provider.new

     respond_to do |format|
        format.html # new.html.erb
        format.json { render json: ghouse }
      end

  end

  def edit
  end

  def add_location
    @provider = Provider.find(params[:id])
    @group_locations = GroupLocation.all
    if @provider.nil?
      puts 'Error here!'
    end
    #throw an error if the provider is nil

  end

  def create
    @provider = Provider.new(provider_params)

    respond_to do |format|
        if @provider.save
            format.html { redirect_to @provider, notice: 'Provider was successfully created.'}
            format.json { render :show, status: :created, location: @provider }
        else
            format.html { render :new }
            format.json { render json: @provider.errors, status: :unprocessable_entity }
        end
    end
  end

  # PATCH/PUT /groups/1
  # PATCH/PUT /groups/1.json
  def update
    respond_to do |format|
      if @provider.update(provider_params)
        format.html { redirect_to @provider, notice: 'provider was successfully updated.' }
        format.json { render :show, status: :ok, location: @provider }
      else
        format.html { render :edit }
        format.json { render json: @provider.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /groups/1
  # DELETE /groups/1.json
  def destroy
    #@group = Group.find(params[:id])
    #if(@group.present?)
    #   @group.destroy
    #end
    @provider.destroy
    respond_to do |format|
      format.html { redirect_to providers_url, notice: 'provider was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_provider
      @provider = Provider.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def provider_params
      params.require(:provider).permit(:last_name, :first_name, :dob, :license_num, :license_exp, :dea_num, 
        :dea_exp, :ptan, :caqh_num, :provider_npi, :effective_date, :provisional_effective_date, :date_joined, 
        :provider_contact, :credentialing_contact, :hospitalaffiliation, :group_id, :specialty_id, :designation_id, :notes, :created_at, :updated_at)    
    end
end

(add_location.html.erb this is gotten to from the show controller)

<div class="container">
<div class="row">
  <%= form_for (@provider) do |f| %>
    <div class="col-md-4">
            <table>
              <tr>
                <th>            
                  <h3> <%= @provider.last_name %> , <%= @provider.first_name %> 's Locations</h3>
                </th>
              </tr>
              <tr>
                <td>          
                 <% if @provider.provider_locations.count >0 %>
                    <%= select_tag "provider_locations", options_from_collection_for_select(@provider.provider_locations.map{|j| j.group_location}, :id , :dba), :multiple => true %>
                  <% else %>
                    <%= select_tag "provider_locations", "<option></option>".html_safe, :multiple => true, :style => "width: 300px" %>       
                  <% end %>
                </td>
              </tr>
              <tr>
                <td>          
                   <button class="remove">Remove</button> 

                </td>
                <td>          
                  <button class="removeAll">Remove All</button>
                </td>
              </tr>
            </table>         
    </div>
    <div class="col-md-4">
         <table>
              <tr>
                <th>            <!-- maybe some buttons here -->

                </th>
              </tr>                   
            </table>
     </div>
     <div class="col-md-4">
            <table>
              <tr>
                <th>            
                 <h3> All Group Locations </h3> <!-- might need a search here too -->
                </th>
              </tr>
              <tr>
                <td>          
                  <% if @group_locations.count >0 %>
                    <%= select_tag "group_providers", options_from_collection_for_select(GroupLocation.all, :id , :dba), :multiple => true %>
                  <% else %>
                    <%= select_tag "group_providers", "<option>Add new...</option>".html_safe, :multiple => true, :style => "width: 300px" %>       
                  <% end %>

                </td>
              </tr>
              <tr>
                <td>          
                    <button class="add">Add</button>

                </td>
                <td>          
                    <button class="addAll">Add All</button>
                </td>
              </tr>
            </table>        
    </div>
    <div class="actions">
      <%= f.submit %>
    </div>
  <% end %>
  </div>
</div>

Second issue the form_for in general is breaking my code:

enter image description here

Upvotes: 0

Views: 69

Answers (1)

SomeSchmo
SomeSchmo

Reputation: 665

I'm pretty sure the reason you're getting an error when you try to submit is because you're submission is trying to go to the update action (because your parameters '_method' is 'patch'). When it gets there it hits the line

if @provider.update(provider_params)

which directs it to your provider_params method. This method is designed to only let through certain parameters, mainly a provider and its associated information (denoted by the ':provider' symbol). Since that information isn't there it stops the submission and errors out. There are several ways you can fix this.

  1. Have your form_for submit to a different controller action (Routing form submission to a different controller)
  2. Change your update action to support the lack of provider parameters

Personally I recommend the first option, though it is getting away for rails REST architecture.

As for handling the data, if I understand correctly you're trying to create the link between the provider and the group_location (i.e. a provider_location). Forgetting anything else that object might require it will certainly need

  1. The provider's id
  2. The group_location's id

Which I believe you already have coming through in your params, assuming 'id' refers to your provider's id and 'group_providers' is an array of the group_location ids (if it's not then you need to use the form_for to get that info in the parameter since you'll need it). Then it's as simple as looping through the group_location ids and creating a provider_location with the group_location id and the provider id.

params[:group_providers].each do |g_id|
   # using 'find_or_create_by' may be unnecessary but
   # can help avoid duplicate entries
   ProviderLocation.find_or_create_by(provider_id: params[:id].to_i, group_location_id: g_id.to_i)
end

Note: if the IDs that come through are meant to reflect the exact state of the provider_location (i.e. if when you submit you also want to delete provider_locations that currently exist but who's ids aren't included in the params) then the loop becomes significantly more complicated algorithmically so if that's what you're trying to do let me know and I'll try to help

Upvotes: 1

Related Questions