Rails 4: Render partial in div after submit button click - ruby-on-rails

I'm not getting it. I'm building a rails application and want to do some single page actions. What I got from now is, when a I pick a 'customer' from the list on the customers/index.html.erb, I render it in the 'current_customer' div. When I click on edit, the form is rendered in the 'current_customer' - perfect. But when I click on sumbit on the form, I get an error (which I understand) 'ActionController::UnknownFormat' because of the action oin the controller for 'show'. I'm routed to 'http://localhost:3000/customers/2'
What I want to is to route to 'http://localhost:3000/customers' after clikcing sumit and the render the cutomers/_show.html.erb in the 'current_customer' div.
My Code:
customers/index.html.erb
<h1>Listing Customers</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th colspan="3">Actions</th>
</tr>
</thead>
<tbody>
<% #customers.each do |customer| %>
<tr>
<td><%= customer.name %></td>
<td><%= link_to 'Show', customer, remote: true %></td>
<td><%= link_to 'Edit', edit_customer_path(customer), remote: true %></td>
<td><%= link_to 'Destroy', customer, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<div id="current_customer"></div>
<br>
<%= link_to 'New Customer', new_customer_path, class: "button", id: "new_customer" %>
customers/_show.html.erb
<p>
<strong>Name:</strong>
<%= #customer.name %>
<%= #customer.id %>
</p>
<%= link_to 'Edit Customer', edit_customer_path(#customer) %> |
customers/_edit.html.erb
<h1>Editing Customer</h1>
<%= render 'form' %>
<%= link_to 'Show', #customer %> |
customers/_form.html.erb
<%= form_for(#customer) do |f| %>
<% if #customer.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#customer.errors.count, "error") %> prohibited this customer from being saved:</h2>
<ul>
<% #customer.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit id: "customer_button", remote: true %>
</div>
<% end %>
customers/edit.js.erb
$("#current_customer").html("<%= escape_javascript(render partial: 'customers/edit', locals: { customer: #customer } ) %>");
customers_controller.rb (partly)
def show
respond_to do |format|
format.js {render layout: false}
end
end
# GET /customers/new
def new
end
# GET /customers/1/edit
def edit
respond_to do |format|
format.js {render layout: false}
end
end
def update
respond_to do |format|
if #customer.update(customer_params)
format.html { redirect_to #customer, notice: 'Customer was successfully updated.' }
format.json { render :show, status: :ok, location: #customer }
else
format.html { render :edit }
format.json { render json: #customer.errors, status: :unprocessable_entity }
end
end
end
I'd be glad for every help!
Thanks

You need to put remote: true in form_for tag instead of submit button, add it here
<%= form_for #customer, remote: true do |f| %>
Remove it from
<%= f.submit id: "customer_button" %>
Also, update action should accept AJAX requests too, create update.js.erb template and handle the AJAX request as you are submitting the form using remote: true
Hope that helps!

Submitting you form as is will call POST /customer/1. You need to defined an update method in your controller and routes, and add method: :patch to your form to achieve a PATCH /customer/1.
Also, you might want to defined a update.js.erb and add remote: true to your form to add some dynamic AJAX.

you can replace your show link by this:
<%= link_to "show", {:action => :show}, :remote => true %>
or
<%= link_to "show", customer_path(customer), :remote => true %>

Related

Rails: Undefined local variable or method `form' in rails 4.1

In my _form partial I render another partial like below
<%= render :partial => 'test', :object => #application.type, \
:locals => {:form => form, \
:application_type => "application[type]"} %>
When I try to load the form I get this error
undefined local variable or method `form' for #<#<Class:0x6daf2c8>:0x8dd3c80>
My test partial
<%= fields_for application_type, application do |application_f| %>
<div>
<div>
<%= application_f.label :uni_id, "University" %>
<%= application_f.collection_select :uni_id, #unis, :id, :check, {:include_blank => true} %>
</div>
</div>
<div>
<% end %>
I recently updated to rails 4.1 from 3.2. It was working before but now it shows error. I guess it is syntax error but could not solve it.
Maybe you need to replace something like this, in your top-level template:
<%= render partial: "form", form: form %>
or like this:
<%= render partial: "form", object: form %>
with something like this (the locals parameter is required now)
<%= render partial: "form", locals: { form: form } %>
Quite a few errors:
<%= render partial: 'test', locals: {form: form }, object: #application %>
<%= form.fields_for application.type, application do |application_f| %>
<div>
<div>
<%= application_f.label :uni_id, "University" %>
<%= application_f.collection_select :uni_id, #unis, :id, :check, {:include_blank => true} %>
</div>
</div>
</div>
<% end %>
This should provide the correct syntax for you.
The error is down to the form variable not being populated. This seems to be from the <%= render call. Without context, the best fix I can give is how it should look:
<%= form_for #variable do |form| %>
<%= render partial: "test", locals: {form:form}, object: #application %>
<% end %>
I experienced this same issue when working on a Rails 6 application
I did an overriding of my routes due to some conflicts from
resources :sessions
to
resources :sessions, as: :sets
Here's how I fixed it:
app/views/sessions/new.html.erb
<h1>New Session</h1>
<%= form_with(model: #session, url: sets_path, local: true) do |form| %>
<%= render partial: 'form', session: #session, locals: { form: form } %>
<% end %>
<%= link_to 'Back', sets_path %>
Note: A URL was defined for the New Form since routing override was done. Thus, the form_with container was isolated from the _form.html.erb partial. This is in a bid to avoid creating multiple _form.html.erb partials for the new.html.erb and edit.html.erb files, since they have different URLs.
app/views/sessions/edit.html.erb
<%= form_with(model: #session, url: set_path(#session), local: true) do |form| %>
<%= render partial: 'form', session: #session, locals: { form: form } %>
<% end %>
<%= link_to 'Show', set_path(session) %> |
<%= link_to 'Back', sets_path %>
Note: A URL was defined for the New Form since routing override was done. Thus, the form_with container was isolated from the _form.html.erb partial. This is in a bid to avoid creating multiple _form.html.erb partials for the new.html.erb and edit.html.erb files, since they have different URLs.
app/views/sessions/_form.html.erb
<% if #session.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#session.errors.count, "error") %> prohibited this session from being saved:</h2>
<ul>
<% #session.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :name %>
<%= form.text_field :name %>
</div>
<div class="field">
<%= form.label :prefix %>
<%= form.text_field :prefix %>
</div>
<div class="actions">
<%= form.submit %>
</div>
Note: Notice that there is no form helper definition in the _form.html.erb file, it was moved to the new.html.erb and edit.html.erb files, since they now have different URLs due to the modification of their route.
app/views/sessions/index.html.erb
<p id="notice"><%= notice %></p>
<h1>Sessions</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Prefix</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #sessions.each do |session| %>
<tr>
<td><%= session.name %></td>
<td><%= session.prefix %></td>
<td><%= link_to 'Show', set_path(session) %></td>
<td><%= link_to 'Edit', edit_set_path(session) %></td>
<td><%= link_to 'Destroy', set_path(session), method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Session', new_set_path %>
Note: Pay attention to the modification of the link URLs in the new action.
app/views/sessions/show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #session.name %>
</p>
<p>
<strong>Prefix:</strong>
<%= #session.prefix %>
</p>
<%= link_to 'Edit', edit_session_path(#session) %> |
<%= link_to 'Back', sessions_path %>
Note: Pay attention to the modification of the link URLs in the edit and back actions.
app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
before_action :set_session, only: [:show, :edit, :update, :destroy]
# GET /sessions
# GET /sessions.json
def index
#sessions = Session.all
end
# GET /sessions/1
# GET /sessions/1.json
def show
end
# GET /sessions/new
def new
#session = Session.new
end
# GET /sessions/1/edit
def edit
end
# POST /sessions
# POST /sessions.json
def create
#session = Session.new(session_params)
respond_to do |format|
if #session.save
format.html { redirect_to sets_path(#sesion), notice: 'Session was successfully created.' }
format.json { render :show, status: :created, location: sets_path(#sesion) }
else
format.html { render :new }
format.json { render json: #session.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /sessions/1
# PATCH/PUT /sessions/1.json
def update
respond_to do |format|
if #session.update(session_params)
format.html { redirect_to sets_path(#sesion), notice: 'Session was successfully updated.' }
format.json { render :show, status: :ok, location: sets_path(#sesion) }
else
format.html { render :edit }
format.json { render json: #session.errors, status: :unprocessable_entity }
end
end
end
# DELETE /sessions/1
# DELETE /sessions/1.json
def destroy
#session.destroy
respond_to do |format|
format.html { redirect_to sets_url, notice: 'Session was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_session
#session = Session.find(params[:id])
end
# Only allow a list of trusted parameters through.
def session_params
params.require(:session).permit(:name, :prefix)
end
end
Note: Pay attention to the modification of the redirect URLs in the create and update actions.
That's all.
I hope this helps

adding my comment system to the index page

i have a comment system associated to a shipment model in my app where a user can have many shipments and a shipment can have many comments.
Everything is working perfectly the only problem is that i want my whole comment system to be shown in the index page of my model currently it is in the show page.
when i try to put it on the index page i get an error:
undefined method `comments' for nil:NilClass
My Controllers
shipment_controller.rb
class ShipmentsController < ApplicationController
before_action :set_shipment, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
# GET /shipments
# GET /shipments.json
def index
#shipments = Shipment.all
end
# GET /shipments/1
# GET /shipments/1.json
def show
#comments = Comment.where(shipment_id: #shipment)
end
# GET /shipments/new
def new
#shipment = Shipment.new
end
# GET /shipments/1/edit
def edit
end
# POST /shipments
# POST /shipments.json
def create
#shipment = current_user.shipments.new(shipment_params)
respond_to do |format|
if #shipment.save
format.html { redirect_to #shipment, notice: 'Shipment was successfully created.' }
format.json { render :show, status: :created, location: #shipment }
else
format.html { render :new }
format.json { render json: #shipment.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /shipments/1
# PATCH/PUT /shipments/1.json
def update
respond_to do |format|
if #shipment.update(shipment_params)
format.html { redirect_to #shipment, notice: 'Shipment was successfully updated.' }
format.json { render :show, status: :ok, location: #shipment }
else
format.html { render :edit }
format.json { render json: #shipment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /shipments/1
# DELETE /shipments/1.json
def destroy
#shipment.destroy
respond_to do |format|
format.html { redirect_to shipments_url, notice: 'Shipment was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_shipment
#shipment = Shipment.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def shipment_params
params.require(:shipment).permit(:name, :description, :from, :to, :date, :pay)
end
end
comments_controller.rb
class CommentsController < ApplicationController
before_action :authenticate_user!
def create
#shipment = Shipment.find(params[:shipment_id])
#comment = Comment.create(params[:comment].permit(:content))
#comment.user_id = current_user.id
#comment.shipment_id = #shipment.id
if #comment.save
redirect_to shipment_path(#shipment)
else
render 'new'
end
end
end
My routes
Rails.application.routes.draw do
devise_for :users, :controllers => {:registrations => "registrations"}
resources :shipments do
resources :comments
end
root 'shipments#index'
end
Shipment View
show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong><%= current_user.full_name %></strong>
</p>
<p>
<strong>Description:</strong>
<%= #shipment.description %>
</p>
<p>
<strong>From:</strong>
<%= #shipment.from %>
</p>
<p>
<strong>To:</strong>
<%= #shipment.to %>
</p>
<p>
<strong>Date:</strong>
<%= #shipment.date %>
</p>
<p>
<strong>Pay:</strong>
<%= #shipment.pay %>
</p>
<div id="comments">
<h2 class="comment_count">
<%= pluralize(#shipment.comments.count, "comment") %>
</h2>
<% #comments.each do |comment| %>
<div class="comment">
<p class="full_name">
<%= comment.user.full_name %>
</p>
<p class="content">
<%= comment.content %>
</p>
</div>
<% end %>
<%= render "comments/form" %>
</div>
<%= link_to 'Edit', edit_shipment_path(#shipment) %> |
<%= link_to 'Back', shipments_path %>
Comments View render
_form.html.erb
<%= simple_form_for([#shipment, #shipment.comments.build]) do |f| %>
<%= f.input :content, label: "Reply to thread" %>
<%= f.button :submit, class: "button" %>
<% end %>
index.html.erb without comments
<h1>Listing Shipments</h1>
<%= link_to "Post a new Shipment", new_shipment_path, class: "btn btn-success" %>
<% #shipments.each do |shipment| %>
<div class="shipment">
<h3><strong><%= shipment.user.full_name%></strong></h3>
<h5><strong>DESCRIPTION: </strong><%= shipment.description %></h5>
<div class="meta">
<%= link_to time_ago_in_words(shipment.created_at) + " ago" %> |
<%= link_to "show", shipment %>
<span class="admin">
| <%= link_to "Edit", edit_shipment_path(shipment) %> |
<%= link_to "Delete", shipment, method: :delete, data: { confirm: "Hey! Are you sure! You wanna delete this shipment??"} %>
</span>
</div>
</div>
<% end %>
index.html.erb with comment system
<h1>Listing Shipments</h1>
<%= link_to "Post a new Shipment", new_shipment_path, class: "btn btn-success" %>
<% #shipments.each do |shipment| %>
<div class="shipment">
<h3><strong><%= shipment.user.full_name%></strong></h3>
<h5><strong>DESCRIPTION: </strong><%= shipment.description %></h5>
<div class="meta">
<%= link_to time_ago_in_words(shipment.created_at) + " ago" %> |
<%= link_to "show", shipment %>
<span class="admin">
| <%= link_to "Edit", edit_shipment_path(shipment) %> |
<%= link_to "Delete", shipment, method: :delete, data: { confirm: "Hey! Are you sure! You wanna delete this shipment??"} %>
</span>
</div>
</div>
<div id="comments">
<h2 class="comment_count">
<%= pluralize(#shipment.comments.count, "comment") %>
</h2>
<% #comments.each do |comment| %>
<div class="comment">
<p class="full_name">
<%= comment.user.full_name %>
</p>
<p class="content">
<%= comment.content %>
</p>
</div>
<% end %>
<%= render "comments/form" %>
<% end %>
After Pavan's Answer
Error
ActiveRecord::RecordNotFound (Couldn't find Shipment with 'id'=):
app/controllers/shipments_controller.rb:9:in `index'
Rendered C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/actionpack-4.2.3
/lib/action_dispatch/middleware/templates/rescues/_source.erb (1.0ms)
Rendered C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/actionpack-4.2.3
/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (3.0ms)
Rendered C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/actionpack-4.2.3
/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
(1.0ms)
Rendered C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/actionpack-4.2.3
/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within re
scues/layout (36.0ms)
Rendered C:/RailsInstaller/Ruby2.0.0/lib/ruby/gems/2.0.0/gems/web-console-2.2.
1/lib/web_console/templates/_markup.html.erb (1.0ms)
You've got an ivar #comments that doesn't appear to be defined...Try #shipment.comments.each
I want my whole comment system to be shown in the index page of my
model currently it is in the show page
You need to loop through #shipments in the index view like below
<% #shipments.each do |shipment| %>
<% shipment.comments.each do |comment| %>
----rest of the code---
<% end %>
<% end %>
Update:
You are getting the error here in this line <%= pluralize(#shipment.comments.count, "comment") %>. You just need to change it to
<%= pluralize(shipment.comments.count, "comment") %>
And you need to modify the comments iteration part like I said above.

Input new record into database using a form with the association belongs_to

I’m relatively new to ruby on rails so bear with me.
I'm trying to create an app where there are many Projects with specific Issues associated to each project. The following is my code:
My Models:
class Issue < ActiveRecord::Base
belongs_to :project
end
class Project < ActiveRecord::Base
has_many :issues
has_and_belongs_to_many :users
validates :name, :description, :manager, presence: true
validates :name, uniqueness: true
end
My Controllers:
in project_controller.rb
def create
#project = Project.new(project_params)
respond_to do |format|
if #project.save
format.html { redirect_to #project, notice: "Project #{#project.name} was successfully created." }
format.json { render :show, status: :created, location: #project }
else
format.html { render :new }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
in issues_controller.rb
def create
#issue = Issue.new(params[:issue])
project = Project.find(params[:project_id])
respond_to do |format|
if #issue.save
format.html { redirect_to root_path, notice: "A new Issue was successfully added to project #{project.name}." }
format.json { render :show, status: :created, location: #issue }
else
format.html { render :new }
format.json { render json: #issue.errors, status: :unprocessable_entity }
end
end
end
My project index html file which is also my root url:
<tbody>
<% #projects.each do |project| %>
<tr>
<td><%= project.name %></td>
<td><%= project.manager %></td>
<td><%= project.description %></td>
<td><%= project.created_at.strftime("%d %B %Y # %H:%M") %></td>
<td><%= button_to 'Report An Issue', new_issue_path(project_id: project) %>
<td><%= link_to 'Show', project %></td>
<td><%= link_to 'Edit', edit_project_path(project) %></td>
<td><%= link_to 'Destroy', project, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
My question is how am i supposed to define the create method in issues_controller.rb to open the new.html.erb form get input from user then save in database while being linked to the project the report an issue button referred to. Any answers, insights or additional links i can look at would be greatly appreciated.
_form.html.erb
<%= form_for(#issue) do |f| %>
<% if #issue.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#issue.errors.count, "error") %>
prohibited this issue from being saved:</h2>
<ul>
<% #issue.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<fieldset>
<legend><strong>Enter Issue Details</strong></legend>
<div class="field">
<%= f.label :description %><br>
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :type %><br>
<%= f.text_field :type %>
</div>
<div class="field">
<%= f.label :status %><br>
<%= f.text_field :status %>
</div>
<div class="field">
<%= f.label :reporter %><br>
<%= f.text_field :reporter %>
</div>
<div class="field">
<%= f.label :remarks %><br>
<%= f.text_area :remarks %>
</div>
<div class="field">
<%= f.label :priority %><br>
<%= f.text_field :priority %>
</div>
<div class="field">
<%= f.label :assignedto %><br>
<%= f.text_field :assignedto %>
</div>
<div class="actions">
<%= f.submit %>
</div>
</fieldset>
<% end %>
new.html.erb
<h1>New Issue</h1>
<%= render 'form' %>
<%= link_to 'Back', issues_path %>
I have to reinput the url /issues/new?project_id=15 manually for it to open the form page otherwise i get routing error and after submission it gives me Couldn't find Project with 'id'=
You are on the right track, you have created an association, now you just need to reference the project in the create method like this :
def new
#project = Project.find params[:project_id]
#issue = #project.issues.build
end
def create
#project = Project.find(params[:project_id])
#issue = #project.issues.build(issue_params)
## rest of code
end
then in your _form.html.erb you should now have :
form_for [#project,#issue]
#rest of code

undefined method `tasks_path' for #<#<Class:0xb663ccf0>:0xb663b3c8>

I have two controllers: tasks and workers.
I visited localhost:3000/workers. When I pressed "Add a New Task" (this is the link I put: <%= link_to 'Add a New Task', new_worker_path %>), I got errors:
NoMethodError in Workers#new
Showing /home/alon/projects/todo/app/views/workers/new.html.erb where line #3 raised:
undefined method `tasks_path' for #<#<Class:0xb663ccf0>:0xb663b3c8>
Extracted source (around line #3):
1: <h1>New task</h1>
2:
3: <%= form_for #workers do |f| %>
4: <p>
5: <%= f.label :name %><br />
6: <%= f.text_field :name %>
Rails.root: /home/alon/projects/todo
Application Trace | Framework Trace | Full Trace
app/views/workers/new.html.erb:3:in `_app_views_workers_new_html_erb___132490529__619346358'
app/controllers/workers_controller.rb:28:in `new'
Request
Parameters:
None
Show session dump
Show env dump
Response
Headers:
None
Why did I get these errors?
I created the files _form.html.erb, index.html.erb, new.html.erb, show.html.erb, and edit.html.erb in views/workers.
I defined in routes.rb:
resources :workers do
resources :tasks
end
This is my workers_controller:
class WorkersController < ApplicationController
def index
#workers = Task.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #workers }
end
end
# GET /workers/1
# GET /workers/1.json
def show
#.find(params[:id])
#workers = Task.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #workers }
end
end
# GET /workers/new
# GET /workers/new.json
def new
#workers = Task.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #workers }
end
end
# GET /workers/1/edit
def edit
#worker = Task.find(params[:id])
end
# POST /workers
# POST /workers.json
def create
#worker = Task.new(params[:task])
respond_to do |format|
if #worker.save
format.html { redirect_to #worker, notice: 'Your task was created.' }
format.json { render json: #worker, status: :created, location: #worker }
else
render "new"
end
end
end
# PUT /workers/1
# PUT /workers/1.json
def update
#worker = Task.find(params[:id])
respond_to do |format|
if #worker.update_attributes(params[:task])
format.html { redirect_to #worker, notice: 'Task was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #worker.errors, status: :unprocessable_entity }
end
end
end
# DELETE /workers/1
# DELETE /workers/1.json
def destroy
#worker = Task.find(params[:id])
#worker.destroy
respond_to do |format|
format.html { redirect_to tasks_url }
format.json { head :no_content }
end
end
end
In addition, I wrote the next code in models/tasks.rb:
class Task < ActiveRecord::Base
belongs_to :Worker
attr_accessible :done, :name, :task
end
This is my workers/new.html.erb file:
<h1>New task</h1>
<%= form_for #workers do |f| %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :task %><br />
<%= f.text_area :task %>
</p>
<p>
<%= f.label :done %><br />
<%= f.check_box :done %>
</p>
<p>
<%= f.submit "add a new task" %>
</p>
<% end %>
and this is workers/_form.html.erb:
<%= form_for(#task) do |f| %>
<% if #task.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#task.errors.count, "error") %> prohibited this task from being saved:</h2>
<ul>
<% #task.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :task %><br />
<%= f.text_area :task %>
</div>
<div class="field">
<%= f.label :done %><br />
<%= f.check_box :done %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
If you type rake routes you will see:
$ rake routes
worker_tasks GET /workers/:worker_id/tasks(.:format) tasks#index
POST /workers/:worker_id/tasks(.:format) tasks#create
new_worker_task GET /workers/:worker_id/tasks/new(.:format) tasks#new
...
So new_worker_task will give you a new task for the worker in question when you pass the worker in.
<%= link_to 'Add a New Task', new_worker_task_path(worker) %> # (below)
I recreated your app locally and got it to work with:
<table>
<tr>
<th></th>
<th></th>
<th></th>
</tr>
<% #workers.each do |worker| %>
<tr>
<td><%= link_to 'Show', worker %></td>
<td><%= link_to worker.name, worker %></td>
<td><%= link_to 'Edit', edit_worker_path(worker) %></td>
<td><%= link_to 'New Task', new_worker_task_path(worker) %>
<td><%= link_to 'Destroy', worker, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
Note that I added a 'name' attribute for worker to make them easier to show (added it to the form and the index pages and of course a db migration to add it to the db).
As pjammer points out you can also do this through nested_attributes in forms, e.g. form_for([#worker, #task])
you seem to be using nested routes but are passing in Task.new instead of something like Worker.new and if you want to add tasks to the worker, use accepts_nested_attributes_for or create a Form Object to handle the creation of tasks.

retrieving multiple model objects from rails partial form

I have the below form working as a partial, i'm trying to do a partial call for a Contractors models and i want to also pass the current page's model id which is a quote id.
Its failing on this line <%= hidden_field_tag :quote_id, #quote.id %> 'called id for nil'
I've tried creating a manual route and putting the search on a seperate method, but then i get a template error so i'm just leaving it in the index method for now.
Form in show.html.erb:
<%= form_tag quotes_path, :method => 'get', :id => "contractors_search" do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<br><br><br>
<div id="contractors"><%= render 'contractors' %></div>
<% end %>
_contractors.html.erb
<table>
<% #contractors.each do | contractor | %>
<tr>
<td><%= contractor.firstname %></td>
<td>
<%= form_tag (quote_add_contractor_path) do %>
<%= hidden_field_tag :quote_id, #quote.id %>
<%= hidden_field_tag :contractor_id, contractor.id %>
<%= submit_tag "Add" %>
<% end %>
</td>
</tr>
<% end %>
</table>
Index.js.erb
$("#contractors").html("<%= escape_javascript(render :partial => "contractors") %>");
Controller:
def index
#quotes = Quote.all
#contractors = Contractor.search(params[:search])
end
def add_contractor
#quote = Quote.find(params[:quote_id])
#contractor = Contractor.find(params[:contractor_id])
#quote.contractors << #contractor
if #quote.save
redirect_to #quote, notice: "contractor was added"
else
render :show, notice: "Sorry, something went aweful"
end
end
In index.js.erb you render the partial contractors but you do not set the #quote instance variable in your index action of the controller. That is why you are getting this failure. Try to add #quote = # Some logic here to your index action.

Resources