Reputation: 3806
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.
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:
Upvotes: 0
Views: 69
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.
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
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