M.T Davis M.T Davis - 5 months ago 31
Ruby Question

Rendering A Partial In Rails

I'm having trouble saving date from a partial that I created in _form.html.erb. The file name of the partial is _education.html.erb. This is how it's currently stated in _form.html.erb as

<%= render partial:'clients/education' %>
I cant figure out what I'm missing. I'm thinking it might be setting the partial as a local variable but I'm not sure.When I remove the partial the form works just fine.

_education.html.erb

<%=form_for(@client, html: {class: "pure-form pure-form-stacked", multipart:true}) do |f| %>
<!-- START CUSTOM TABS -->
<div class="row">
<div class="col-md-12">
<!-- Custom Tabs -->
<div class="nav-tabs-custom">
<ul class="nav nav-tabs pull-left">
<li class="active"><a href="#tab_1-1" data-toggle="tab">School</a></li>
<li><a href="#tab_2-2" data-toggle="tab">Employment</a></li>
<li><a href="#tab_3-2" data-toggle="tab">Tab 3</a></li>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tab_1-1">
<b><%= f.label :ed_id, "School" %></b>
<%= f.collection_select :ed_id, Ed.all, :id, :school, {prompt: "Choose School"}, class: "btn btn-info", class: "pure-input-4-24" %>
</div><!-- /.tab-pane -->
<div class="tab-pane" id="tab_2-2">
<div class="tab-content">
<div class="tab-pane active" id="tab_1-">
<b><%= f.label :employment_id, "Employment" %></b>
<%= f.collection_select :employment_id, Employment.all, :id, :name, {prompt: "Choose Status"}, class: "btn btn-info", class: "pure-input-4-24" %>
</div>
</div>
</div><!-- /.tab-pane -->
<div class="tab-pane" id="tab_3-2">
...
</div><!-- /.tab-pane -->
</div><!-- /.tab-content -->
</div><!-- nav-tabs-custom -->
</div><!-- /.col -->

<div class="col-md-6">
<!-- Custom Tabs (Pulled to the right) -->

</div><!-- /.col -->
<% end %>
</div> <!-- /.row -->
<!-- END CUSTOM TABS -->


Here is the controller for the client form. I made sure that I added the ed_id to the params because it has a belongs_to in client.rb and has_many in ed.rb

class ClientsController < ApplicationController
before_action :authenticate_user!
before_action :set_client, only: [:show, :edit, :update, :destroy]


# GET /clients
# GET /clients.json
def index
@clients = Client.all.uniq.order("created_at DESC")
@clients_count = Client.uniq.count
end

# GET /clients/1
# GET /clients/1.json
def show
@notes = Note.where(client_id: @client.id) #Where a note belong to the current account
end

# GET /clients/new
def new
@client = Client.new
end

# GET /clients/1/edit
def edit
end

# POST /clients
# POST /clients.json
def create
@client = Client.new(client_params)

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

# PATCH/PUT /clients/1
# PATCH/PUT /clients/1.json
def update
#if params[:remove_image]
#@client.remove_image!
@client.save
#end
respond_to do |format|
if @client.update(client_params)
format.html { redirect_to @client, notice: 'Client was successfully updated.' }
format.json { render :show, status: :ok, location: @client }
else
format.html { render :edit }
format.json { render json: @client.errors, status: :unprocessable_entity }
end
end
end
# DELETE /clients/1
# DELETE /clients/1.json
def destroy
@client.destroy
respond_to do |format|
format.html { redirect_to clients_url, notice: 'Client was successfully destroyed.' }
format.json { head :no_content }
end
end

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

# Never trust parameters from the scary internet, only allow the white list through.
def client_params
params.require(:client).permit(:firstName, :lastName, :dob, :gender_id, :remove_image, :insurance_id, :state_id, :ed_id, :rsource_id, :image, :race_id, :employment_id, :comments, :email, :phone, :address, :city, :state, :zipcode)
end
end


Here is an short version of the form.

<%=form_for(@client, html: {class: "pure-form pure-form-stacked", multipart:true}) do |f| %>
<% if @client.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@client.errors.count, "error") %> prohibited this client from being saved:</h2>

<ul>
<% @client.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<!-- beginning of rails code -->
<form class="pure-form pure-form-stacked">
<fieldset>
<!-- <legend>Client Information</legend> -->
<div>
<h2 class="account">Client Information</h2>
</div>
<div class="pure-g">
<div class="pure-u-1 pure-u-md-1-3">
<%= image_tag @client.image_url, class: "image-client" if @client.image? %>
<%= f.label :image, "Client Image" %>
<%= f.file_field :image %>
<%= f.check_box :remove_image, id: "my-checkbox", :data => { :size=>'mini', 'on-color'=>'success', 'on-text'=>'Done', 'off-text'=>'Yes' } %> Remove Image?
</div>

<div class="pure-u-1 pure-u-md-1-3 firstname">
<%= f.label:firstName, "First Name" %>
<%= f.text_field :firstName, class:"pure-u-2-5", type:"text", placeholder: "First Name", required: true %>

<%= f.label :lastName, "Last Name" %>
<%= f.text_field :lastName, class:"pure-u-2-5", type:"text", placeholder: "Last Name" %>
</div>
</div>
<!-- Employment Information -->
<h2 class="employment">Employment Status</h2>
<div class="pure-g">
<div class="pure-u-1 pure-u-md-1-3">
<%= render partial:'clients/education' %>
</div>
<!-- End of Employment Information -->
</div>
<!-- Client Note -->
...
<!-- End of Client Note -->
</fieldset>
<div class="actions">
<%=f .submit class: "btn btn-primary" %> <%= link_to 'Cancel', clients_path, class: "btn btn-danger" %>
</div>
<% end %>
</form>

Answer

You need to pass the locals to the _education partial:

<%= render partial:'clients/education', locals: {f: f} %>

And then in your _education partial, you don't need another form_for declaration; just keep going with your <%= f.collection_select..., etc.

Hope this helps! :-)