undefined method `tasks_path' for #<#<Class:0xb663ccf0>:0xb663b3c8> - ruby-on-rails

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.

Related

Rails: param is missing or the value is empty: admin

I am working on a Rails project and I am using namespacing for the models and controllers. That is the child models are put in a directory called user and the controllers are put in a directory called users.
For more clarity, I have a user model that has child admin and student models using Single Table Inheritance (STI). These child models inherit all the attributes of the parent model and can individually define their validations and methods and are placed in a directory called user.
I also have admins_controller and students_controller that use the admin model and the student model respectively. These controllers are placed in a directory called users.
Here's my code;
User model:
class User < ApplicationRecord
has_secure_password
end
Admin model:
class User::Admin < User
end
Student model:
class User::Student < User
end
Admin Controller:
class Users::AdminsController < ApplicationController
before_action :set_admin, only: [:show, :edit, :update, :destroy]
# GET /admins
# GET /admins.json
def index
#admins = User::Admin.all
end
# GET /admins/1
# GET /admins/1.json
def show
end
# GET /admins/new
def new
#admin = User::Admin.new
end
# GET /admins/1/edit
def edit
end
# POST /admins
# POST /admins.json
def create
#admin = User::Admin.new(admin_params)
respond_to do |format|
if #admin.save
format.html { redirect_to users_admin_path(#admin), notice: 'Admin was successfully created.' }
format.json { render :show, status: :created, location: users_admin_path(#admin) }
else
format.html { render :new }
format.json { render json: #admin.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /admins/1
# PATCH/PUT /admins/1.json
def update
respond_to do |format|
if #admin.update(admin_params)
format.html { redirect_to users_admin_path(#admin), notice: 'Admin was successfully updated.' }
format.json { render :show, status: :ok, location: users_admin_path(#admin) }
else
format.html { render :edit }
format.json { render json: #admin.errors, status: :unprocessable_entity }
end
end
end
# DELETE /admins/1
# DELETE /admins/1.json
def destroy
#admin.destroy
respond_to do |format|
format.html { redirect_to users_admins_url, notice: 'Admin was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_admin
#admin = User::Admin.find(params[:id])
end
# Only allow a list of trusted parameters through.
def admin_params
params.require(:admin).permit(:email, :password, :role)
end
end
Routes:
Rails.application.routes.draw do
namespace :users do
resources :admins
resources :students
end
end
index.html.erb:
<p id="notice"><%= notice %></p>
<h1>Admins</h1>
<table>
<thead>
<tr>
<th>Email</th>
<th>Password</th>
<th>Role</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #admins.each do |admin| %>
<tr>
<td><%= admin.email %></td>
<td><%= admin.password %></td>
<td><%= admin.role %></td>
<td><%= link_to 'Show', users_admin_path(admin) %></td>
<td><%= link_to 'Edit', edit_users_admin_path(admin) %></td>
<td><%= link_to 'Destroy', users_admin_path(admin), method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Admin', new_users_admin_path %>
show.html.erb:
<p id="notice"><%= notice %></p>
<p>
<strong>Email:</strong>
<%= #admin.email %>
</p>
<p>
<strong>Password:</strong>
<%= #admin.password %>
</p>
<p>
<strong>Role:</strong>
<%= #admin.role %>
</p>
<%= link_to 'Edit', edit_users_admin_path(#admin) %> |
<%= link_to 'Back', users_admins_path %>
_form.html.erb:
<% if #admin.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#admin.errors.count, "error") %> prohibited this admin from being saved:</h2>
<ul>
<% #admin.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :email %>
<%= form.text_field :email %>
</div>
<div class="field">
<%= form.label :password %>
<%= form.text_field :password %>
</div>
<div class="field">
<%= form.label :role %>
<%= form.text_field :role %>
</div>
<div class="actions">
<%= form.submit %>
</div>
new.html.erb:
<h1>New Admin</h1>
<%= form_with(model: #admin, url: users_admins_path, local: true) do |form| %>
<%= render partial: 'form', admin: #admin, locals: { form: form } %>
<% end %>
<%= link_to 'Back', users_admins_path %>
edit.html.erb:
<h1>Editing Admin</h1>
<%= form_with(model: #admin, url: users_admin_path(#admin), local: true) do |form| %>
<%= render partial: 'form', admin: #admin, locals: { form: form } %>
<% end %>
<%= link_to 'Show', users_admin_path %> |
<%= link_to 'Back', users_admins_path %>
However, when I try creating a new admin or updating an already existing admin, I get the error:
param is missing or the value is empty: admin
I have tried to debug the cause of the issue, but no luck yet. Any form of help will be highly appreciated.
I finally figured it out after careful examination of my logs.
Here's how I solved it:
I examined the request parameters of the create action and I realized that it was of this format:
{"authenticity_token"=>"qJWlHz7Z5myTH3dwNIjjSOzRDY7JN+LoovaG+8dMBnGFRWImJKlWp8cgF7kwTqJXIxqU2fGVkqW9nhOAJ8vFIg==",
"user_admin"=>{"email"=>"promise#gmail.com", "password"=>"[FILTERED]", "role"=>""},
"commit"=>"Create Admin"}
So the request parameters have a hash key of user_admin with values email, password and role, whereas I was passing the admin hash key in my admins_controller.
All I had to do was to modify the admins_params private method in my admins_controller:
From this:
def admin_params
params.require(:admin).permit(:email, :password, :role)
end
To this:
def admin_params
params.require(:user_admin).permit(:email, :password, :role)
end
and that solved the issue.
If you have such an issue, always endeavour to inspect your request parameters in your logs or your application trace. That will give you a lot of information that will help you to resolve the issue.
That's all.
I hope this helps

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

act_as_taggable Gem Ruby on Rails Error: NoMethodError in Posts#index

I am trying to add Tags to my Posts Scaffold using the act_as_taggable Gem but i get an error when i view the index or the show page. I have followed this guide but i still get the error.
here's my code:
posts_controller.rb
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
#posts = Post.all
#posts = Post.tagged_with(params[:tag])
#posts = Post.all.order("created_at DESC")
end
# GET /posts/1
# GET /posts/1.json
def show
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:name, {image:[]}, :tag_list)
end
end
post.rb
class Post < ActiveRecord::Base
acts_as_taggable
mount_uploaders :image, ImageUploader
end
views/posts/_form.html.erb
<%= form_for(#post , html: { multipart: true }) do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #post.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="field">
<%= f.label :image %><br>
<%= f.file_field :image , multiple: true %>
</div>
<div class="form-group">
<%= f.label :tag_list, "Tags (separated by commas)" %>
<%= f.text_field :tag_list, class: "form-control" %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
views/posts/index.html.erb
<p id="notice"><%= notice %></p>
<h1>Listing Posts</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #posts.each do |post| %>
<tr>
<td><%= post.name %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<%= #posts.tags.each do |tag| %>
<span class="label label-teal">
<%= link_to tag.name, tag_path(tag.name) %>
</span>
<% end %>
<br>
<%= link_to 'New Post', new_post_path %>
views/posts/show.html.erb
<p id="notice"><%= notice %></p>
<%= image_tag #post.image%>
<p>
<strong>Name:</strong>
<%= #post.name %>
</p>
<% #posts.tags.each do |tag| %>
<span class="label label-teal">
<%= link_to tag.name, tag_path(tag.name) %>
</span>
<% end %>
<%= link_to 'Edit', edit_post_path(#post) %> |
<%= link_to 'Back', posts_path %>
config/routes.rb
Rails.application.routes.draw do
resources :posts
get 'tags/:tag', to: 'pins#index', as: :tag
end
Did anyone had a solution to this issue ?
You're calling tags on a collection of Posts, but it's the individual posts that have tags.
Either select a single post and run tags on that, or use Tag.all or something similar to find all tags in the system.

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

Resources