Reputation: 571
I have a web app that contains a three models - Customers, Jobs and Rooms. They are associated as follows:
class Customer < ActiveRecord::Base
has_many :jobs
class Job < ActiveRecord::Base
belongs_to :customer
has_many :rooms
class Room < ActiveRecord::Base
belongs_to :job
Users can create as many rooms as they want.
Currently, I have a view that looks like this:
<div class="row">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title center">Room Information</h3>
</div>
<div class="panel-body">
<ul class="nav nav-tabs" role="tablist">
<% @job.rooms.each do |room| %>
<li><%= link_to room.room_type %></li>
<% end %>
</ul>
<%= render 'layouts/roomview' %>
<div class="pull-right">
<%= link_to new_job_room_path(@job, @customer), class: "btn btn-primary" do %>
<span class="glyphicon glyphicon-plus"></span> Add New Room
<% end %>
</div>
</div>
</div>
</div>
In this view, I would like to click each tab and then have the roomview partial render for the room associated to the corresponding tab.
My _roomview.html.erb partial is as follows:
<% @job.rooms.each do |job| %>
<div class="table-responsive">
<table class="table">
<tr>
<h4 class="info-text"><%= room.room_type %> Information</h4>
</tr>
<tr class="info">
<th class="col-md-2 info-text"><u>Room Details</u></th>
<th class="col-md-2"></th>
<th class="col-md-2 info-text"><u>Door Style Details</u></th>
<th class="col-md-2"></th>
<th class="col-md-2 info-text"><u>Drawer Box Details</u></th>
<th class="col-md-2"></th>
</tr>
<tr>
<td class="col-md-2"><strong>Room Type:</strong></td>
<td class="col-md-2"><%= room.room_type %></td>
<td class="col-md-2"><strong>Upper Door Style:</strong></td>
<td class="col-md-2"><%= room.upper_door_style %></td>
<td class="col-md-2"><strong>Drawer Box Style:</strong></td>
<td class="col-md-2"><%= room.drawer_box_style %></td>
</tr>
<tr>
<td class="col-md-2"><strong>Material Type:</strong></td>
<td class="col-md-2"><%= room.material %></td>
<td class="col-md-2"><strong>Lower Door Style:</strong></td>
<td class="col-md-2"><%= room.lower_door_style %></td>
<td class="col-md-2"><strong>Drawer Track Style:</strong></td>
<td class="col-md-2"><%= room.track_style %></td>
</tr>
<tr>
<td class="col-md-2"><strong>Material Details:</strong></td>
<td class="col-md-2"><%= room.material_details %></td>
<td class="col-md-2"><strong>Drawer Front Style:</strong></td>
<td class="col-md-2"><%= room.drawer_front_style %></td>
<td class="col-md-2"></td>
<td class="col-md-2"></td>
</tr>
<tr>
<td class="col-md-2"><strong>Exterior Colour:</strong></td>
<td class="col-md-2"><%= room.exterior_colour %></td>
<td class="col-md-2"><strong>Panel Back Style:</strong></td>
<td class="col-md-2"><%= room.panel_back_style %></td>
<td class="col-md-2"></td>
<td class="col-md-2"></td>
</tr>
<tr>
<td class="col-md-2"><strong>Interior Colour:</strong></td>
<td class="col-md-2"><%= room.interior_colour %></td>
<td class="col-md-2"><strong>Finished End Style:</strong></td>
<td class="col-md-2"><%= room.finished_ends %></td>
<td class="col-md-2"></td>
<td class="col-md-2"></td>
</tr>
<tr class="info">
<th class="col-md-2 info-text"><u>Counter Top Details</u></th>
<th class="col-md-2"></th>
<th class="col-md-2 info-text"><u>Molding Details</u></th>
<th class="col-md-2"></th>
<th class="col-md-2 info-text"><u>Custom Order Details</u></th>
<th class="col-md-2"></th>
</tr>
<tr>
<td class="col-md-2"><strong>Counter Top Material:</strong></td>
<td class="col-md-2"><%= room.counter_top_material %></td>
<td class="col-md-2"><strong>Closed To Ceiling:</strong></td>
<td class="col-md-2"><%= room.closed_to_ceiling %></td>
<td class="col-md-2"><strong>Custom Order Name:</strong></td>
<td class="col-md-2"><%= room.order_name %></td>
</tr>
<tr>
<td class="col-md-2"><strong>Counter Top Supplier:</strong></td>
<td class="col-md-2"><%= room.counter_top_supplier %></td>
<td class="col-md-2"><strong>Crown Molding:</strong></td>
<td class="col-md-2"><%= room.crown_molding %></td>
<td class="col-md-2"><strong>Custom Order Details:</strong></td>
<td class="col-md-2"><%= room.order_description %></td>
</tr>
<tr>
<td class="col-md-2"><strong>Counter Top Colour:</strong></td>
<td class="col-md-2"><%= room.counter_top_colour %></td>
<td class="col-md-2"><strong>Under Cabinet Molding:</strong></td>
<td class="col-md-2"><%= room.under_cabinet_molding %></td>
<td class="col-md-2"></td>
<td class="col-md-2"></td>
</tr>
<tr>
<td class="col-md-2"><strong>Counter Top Edge:</strong></td>
<td class="col-md-2"><%= room.counter_top_edge %></td>
<td class="col-md-2"></td>
<td class="col-md-2"></td>
<td class="col-md-2"></td>
<td class="col-md-2"></td>
</tr>
<tr>
<td class="col-md-2"><strong>Counter Top Backsplash:</strong></td>
<td class="col-md-2"><%= room.backsplash %></td>
<td class="col-md-2"></td>
<td class="col-md-2"></td>
<td class="col-md-2"></td>
<td class="col-md-2"></td>
</tr>
<tr>
<td class="col-md-2"><strong>Sink Install:</strong></td>
<td class="col-md-2"><%= room.sink_install %></td>
<td class="col-md-2"></td>
<td class="col-md-2"></td>
<td class="col-md-2"></td>
<td class="col-md-2"></td>
</tr>
</table>
</div>
<% end %>
Here are my routes:
resources :customers do
resources :jobs
end
resources :jobs do
resources :rooms
end
And finally, here is my jobs show controller:
def show
@job = Job.find(params[:id])
@customer = Customer.find(params[:customer_id])
end
As it stands right now, when I load the view I am getting a controller name error for the show action. The error states that I have an undefined method for 'room'.
Considering my stated functionality above - can anyone troubleshoot this? I am unsure of how to structure the show action to properly render my partial.
Here is the exact error string:
undefined local variable or method `room' for #<#<Class:0x007fa01f9827b0>:0x007fa01f9a8d48>
Upvotes: 1
Views: 1071
Reputation: 76784
Several issues here:
Controller
If your models are nested, why don't you use your associations in the controller calls:
#app/controllers/jobs_controller.rb
class JobsController < ActiveRecord::Base
def show
@customer = Customer.find params[:customer_id]
@job = @customer.jobs.find params[:id]
end
end
Far more efficient!
Error
Your error is quite explicit:
undefined local variable or method `room'
This means that somewhere in your show
view, your app is going to try and reference room
(local var) without it being defined. Without a specific reference to the error in question, I'll have to work through to the cause of the issue:
#app/views/jobs/_roomview.html.erb
<% @job.rooms ...
Firstly, the above is incorrect. In partials, you need to pass "local" variables (as otherwise, they lose their modularity):
<%= render partial: "roomview", locals: { job: @job } %>
What would be better would be to use the following:
<%= render partial: "roomview", collection: @job.rooms, as: :room %>
#_roomview.html.erb
(no need for .each any more)
<div class="table-responsive"> ....
--
Finally, I would look at how you're calling the various dependencies of your show
view. Specifically the partial
, but also any links
etc. You have the following link:
<%= link_to room.room_type %>
Surely you'd be better calling <%= link_to "Room", room.room_type %>
Upvotes: 3