Missing required keys rails - ruby-on-rails

I'm trying to create a form for task in my app.App has two entities:
Project belongs_to User
Task belongs_to Project
But I get this error in my view when I'm trying to create this (pretty basic) form
No route matches {:action=>"index", :controller=>"tasks"} missing required keys: [:project_id]
Here is a part of my view with this form
<div class="glyphicon glyphicon-plus col-xs-1 left_plus" ></div>
<div class="col-xs-10" >
<%= form_for [#project, #task],url: project_tasks_path do |f| %>
<%= f.input :body,class: 'form-control' %>
<%= f.submit 'Add task', class: 'btn' %>
<% end %>
And here is the project controller:
class ProjectsController < ApplicationController
before_action :load_project, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
def index
#projects = current_user.projects unless current_user.nil?
#task = Task.find_by(params[:project_id])
end
def show
#task = #project.tasks.build
end
def new
#project = current_user.projects.new
end
def edit
end
def create
#project = current_user.projects.create(project_params)
if #project.save
redirect_to root_path
else
render :new
end
end
def update
if #project.update(project_params)
redirect_to #project
else
render :edit
end
end
def destroy
#project.destroy
redirect_to projects_path
end
private
def load_project
#project = Project.find(params[:id])
end
def project_params
params.require(:project).permit(:name, :user_id)
end
end
And the tasks controller:
class TasksController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
def index
#tasks = Task.where(project_id: project_id)
end
def show
project = Project.find_by(id: params[:project_id])
#task = Task.new(project: project)
end
def new
project = Project.find_by(id: params[:project_id])
#task = Task.new(project: project)
end
def edit
project = Project.find_by(id: params[:project_id])
#task = Task.new(project: project)
end
def references
respond_to do |format|
if #task.valid?
format.html { redirect_to root_url }
format.json { render :show, status: :created, location: #task }
else
format.html { render :home_url }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
def create
#project = Project.find_by(id: params[:project_id])
#task = #project.tasks.create(task_params)
respond_to do |format|
if #task.valid?
format.html { redirect_to root_url }
format.json { render :show, status: :created, location: #task }
else
format.html { render :home_url }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #task.update(task_params)
format.html { redirect_to root_url }
format.json { render :home_url, status: :ok, location: #task }
else
format.html { render :root_url }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
def edit
end
def destroy
#task.destroy
respond_to do |format|
format.html { redirect_to root_url }
format.json { head :no_content }
end
end
private
def set_task
#task = Task.find(params[:id])
end
def task_params
params.require(:task).permit(:deadline, :body, :project_id)
end
end
The routes file:
devise_for :users, :controllers => { :omniauth_callbacks => "callbacks" }
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root 'projects#index'
resources :projects do
resources :tasks
end
And my routes:
projects#index
project_tasks GET /projects/:project_id/tasks(.:format) tasks#index
POST /projects/:project_id/tasks(.:format) tasks#create
new_project_task GET /projects/:project_id/tasks/new(.:format) tasks#new
edit_project_task GET /projects/:project_id/tasks/:id/edit(.:format) tasks#edit
project_task GET /projects/:project_id/tasks/:id(.:format) tasks#show
PATCH /projects/:project_id/tasks/:id(.:format) tasks#update
PUT /projects/:project_id/tasks/:id(.:format) tasks#update
DELETE /projects/:project_id/tasks/:id(.:format) tasks#destroy
projects GET /projects(.:format) projects#index
POST /projects(.:format) projects#create
new_project GET /projects/new(.:format) projects#new
edit_project GET /projects/:id/edit(.:format) projects#edit
project GET /projects/:id(.:format) projects#show
PATCH /projects/:id(.:format) projects#update
PUT /projects/:id(.:format) projects#update
DELETE /projects/:id(.:format) projects#destroy
Can somebody please help me to clarify where is the problem and what is the problem?

The problem is with your TasksController#index action. What is project_id there? For accessing a project's tasks, the project needs to exist in the first place. And not just that. To access any CRUD action on tasks, a project has to exist first.
Modify your TasksController as
class TasksController < ApplicationController
before_action :set_project
before_action :set_task, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
def index
#tasks = #project.tasks
end
def show
#makes use of set_task
end
def new
#task = #project.tasks.new
end
def edit
end
def references
respond_to do |format|
if #task.valid?
format.html { redirect_to root_url }
format.json { render :show, status: :created, location: #task }
else
format.html { render :home_url }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
def create
#task = #project.tasks.create(task_params)
respond_to do |format|
if #task.valid?
format.html { redirect_to root_url }
format.json { render :show, status: :created, location: #task }
else
format.html { render :home_url }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #task.update(task_params)
format.html { redirect_to root_url }
format.json { render :home_url, status: :ok, location: #task }
else
format.html { render :root_url }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
def destroy
#task.destroy
respond_to do |format|
format.html { redirect_to root_url }
format.json { head :no_content }
end
end
private
def set_project
#project = current_user.projects.find(params[:project_id]
end
def set_task
#task = #project.tasks.find(params[:id])
end
def task_params
params.require(:task).permit(:deadline, :body, :project_id)
end
end
Since we have defined a before_action set_project, #project will be available to all methods. Note that set_projectfinds the project from the projects created by the current user.
In the ProjectsController#index, you won't actually get a value for params[:project_id]. Modify your index action to
def index
#projects = current_user.projects unless current_user.nil?
end
And I don't understand your show method. The build method is actually used to create a in-memory representation of an object. The show method of projects_controller can be used to display the project along with its tasks. If this is what you need, change you show action in ProjectsController to
def show
##project is available from load_project
#tasks = #project.tasks
end
You could also modify your load_project project as
def load_project
begin
#project = Project.find(params[:id]) #raises an exception if project not found
rescue ActiveRecord::RecordNotFound
redirect_to projects_path
end
end
To know more about rescuing exceptions, see Begin, Rescue and Ensure in Ruby?
For more, see http://blog.8thcolor.com/en/2011/08/nested-resources-with-independent-views-in-ruby-on-rails/

If the form to create a new task is in projects/index.html.erb you should make a #task variable available to the view; try to change the index action as follow:
def index
#projects = current_user.projects unless current_user.nil?
#task = Task.new
end

The problem is with the url for submitting the form. If you check your rake routes you'd see that all your task routes would be nested under projects, therefore in passing the url option, you should have something like:
<div class="glyphicon glyphicon-plus col-xs-1 left_plus" ></div>
<div class="col-xs-10" >
<%= form_for [#project, #task],url: project_tasks_path(#project) do |f| %>
<%= f.input :body,class: 'form-control' %>
<%= f.submit 'Add task', class: 'btn' %>
<% end %>
or even better, I think you should be able to do that without passing the url option:
<div class="glyphicon glyphicon-plus col-xs-1 left_plus" ></div>
<div class="col-xs-10" >
<%= form_for [#project, #task] do |f| %>
<%= f.input :body,class: 'form-control' %>
<%= f.submit 'Add task', class: 'btn' %>
<% end %>
UPDATE
def index
project = Project.find(params[:project_id])
#projects = ProjectsViewPresenter.new(project)
end
# presenters/projects_view_presenter.rb
class ProjectsViewPresenter
attr_reader :project
def initialize(project)
#project = project
end
def tasks
#tasks ||= project.tasks
end
def task
#task ||= tasks.new
end
end
Your form_for would now be like this:
<div class="glyphicon glyphicon-plus col-xs-1 left_plus" ></div>
<div class="col-xs-10" >
<%= form_for [#project.project, #project.task] do |f| %>
<%= f.input :body,class: 'form-control' %>
<%= f.submit 'Add task', class: 'btn' %>
<% end %>

Related

No route matches {:action=>"create", :controller=>"reviews", :id=>"2", :user_id=>#<Profile id: 2...} missing required keys: [:profile_id]

I am working on user_profile_reviews and have got stuck. I have 3 models for now, and I know, that doing a separate model for a profile wasn't really a great idea, but since all my routes depend on this structure, meaning the links in all the views also, I decided not to change it.
To give you a clearer understanding:
Rails.application.routes.draw do
devise_for :user, controllers: { omniauth_callbacks: 'users/omniauth_callbacks', registrations: "users/registrations" }
resources :users do
resources :profiles do
resources :reviews, only: [:new, :create]
end
end
root 'home#index'
end
Here are my controllers:
class ProfilesController < ApplicationController
before_action :set_profile, only: [:show, :edit, :update, :destroy]
def index
#profiles = Profile.all
end
def show
#user = User.find(params[:user_id])
#profile = Profile.find(params[:id])
#reviews = Review.where("profile_id = ?", params[:id])
end
def new
#user = User.find(params[:user_id])
end
def edit
#profile = Profile.find(params[:id])
end
def create
#profile = current_user.build_profile(profile_params)
respond_to do |format|
if #profile.save
format.html { redirect_to user_profile_path(current_user.id, current_user.profile.id), notice: 'Profile was successfully created.' }
format.json { render :show, status: :created, location: #profile }
else
format.html { render :new }
format.json { render json: #profile.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #profile.update(profile_params)
format.html { redirect_to user_profile_path(current_user.id, current_user.profile.id), notice: 'Profile was successfully updated.' }
format.json { render :show, status: :ok, location: #profile }
else
format.html { render :edit }
format.json { render json: #profile.errors, status: :unprocessable_entity }
end
end
end
def destroy
#profile.destroy
respond_to do |format|
format.html { redirect_to profiles_url, notice: 'Profile was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_profile
#profile = Profile.find(params[:id])
end
def profile_params
params.permit(:about, :rating, :avatar)
end
end
Reviews
class ReviewsController < ApplicationController
before_filter :set_profile
before_filter :set_review, only: [:new, :create]
def new
#review = Review.new
end
def create
#profile = Profile.find(params[:profile_id])
#review = #profile.reviews.build(review_params)
#review.user_id = current_user.id
if #review.save
redirect_to #profile
else
redirect_to #profile, notice: "Error saving"
end
end
private
def review_params
params.permit(:content, :rating)
end
def set_pfofile
#profile = Profile.find(params[:profile_id])
end
def set_review
#profile = Profile.find(params[:id])
end
end
So now, I am trying to create a form for reviews, which I am then rendering in Profiles#show, and getting the mistake above.
<div class="submit-review">
<%= form_for [#review, :url => user_profile_reviews_path(#profile)] do |f| %>
<label for="review">How was your experience?</label><br>
<%= f.label :rating %>
<%= f.select :rating, options_for_select([["Please select one", ""], 5, 4, 3, 2, 1]) %>
<%= f.input :content, placeholder:"Please enter your feedback here" %>
<%= f.submit "Submit your review", class: "btn btn-default" %> <br><br>
<% end %>
Showing ... /_form.html.erb where line #2 raised:
No route matches {:action=>"create", :controller=>"reviews", :id=>"2", :user_id=>#<Profile id: 2, about: "lena", rating: 3, created_at: "2019-11-22 21:27:03", updated_at: "2019-11-22 21:27:03", user_id: 2>}, missing required keys: [:profile_id]
But, as I see, it gets to the profile, I am onto, so I don't understand what's the issue here.
Something wrong with the syntax, try this
= form_for([#profile.user, #profile, #review], :url => user_profile_reviews_path(#profile.user, #profile)) do |f|
Since your resources are nested, you need to pass user, profile and then review as the first argument in form_for
Suggestion: Looking at your code, you don't even need user_id, you can avoid nesting profile and review under user in routes.
Hope that helps!
Ok, this worked perfectly for solving the described problem with missing id.
form_for([#profile.user, #profile, #review], :url => user_profile_reviews_path(#profile.user, #profile)) do |f|
I was getting another error though:
First argument in form cannot contain nil or be empty
I saw then, that in my Profile#show I wasn't defining #review. Only reviews. So I did it this way:
def show
#user = User.find(params[:user_id])
#profile = Profile.find(params[:id])
#review = Review.new
#reviews = Review.where("profile_id = ?", params[:id])
end
I can now finally go to profile and there is a review window, which is great! I can't save the reviews though, as another error is showing up. But that's different case. Thank you so much!

Couldn't find ProjectSession with 'id'=

Here i have a project to which i am adding a session and for a project session i am trying to add task.
i am able to create project and add project session for project but when i am trying to add task for session using project_sessions_id i am getting error Couldn't find ProjectSession with 'id'= and 'app/controllers/tasks_controller.rb:60:in set_project_session i am able to get the project session id also project_sessions/11 in the url but when i click 'create task' i am getting this error. how can i resolve this?
here's what i have done
ProjectSessionController:
class ProjectSessionsController < ApplicationController
before_action :set_project_session, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
before_action :set_project
def index
#project_sessions = ProjectSession.all
end
def show
#project_sessions = ProjectSession.where(project_id: #project.id).order("created_at DESC")
end
def new
#project_session = ProjectSession.new
end
def edit
end
def create
#project_session = ProjectSession.new(project_session_params)
#project_session.project_id = #project.id
#respond_to do |format|
if #project_session.save
redirect_to #project
#format.html { redirect_to #project_session, notice: 'Project session was successfully created.' }
#format.json { render :show, status: :created, location: #project_session }
else
format.html { render :new }
format.json { render json: #project_session.errors, status: :unprocessable_entity }
end
#end
end
def update
respond_to do |format|
if #project_session.update(project_session_params)
format.html { redirect_to #project_session, notice: 'Project session was successfully updated.' }
format.json { render :show, status: :ok, location: #project_session }
else
format.html { render :edit }
format.json { render json: #project_session.errors, status: :unprocessable_entity }
end
end
end
def destroy
#project_session.destroy
respond_to do |format|
format.html { redirect_to project_sessions_url, notice: 'Project session was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_project_session
#project_session = ProjectSession.find(params[:id])
end
def set_project
#project = Project.find(params[:project_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def project_session_params
params.require(:project_session).permit(:session_date, :session_name, :session_description, :start_time, :end_time)
end
end
Task controller:
class TasksController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
before_action :set_project_session
def index
#tasks = Task.all
end
def show
end
def new
#task = Task.new
end
def edit
end
def create
#task = Task.new(task_params)
#task.session_id = #project_session.id
respond_to do |format|
if #task.save
redirect_to #project_session
else
format.html { render :new }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #task.update(task_params)
format.html { redirect_to #task, notice: 'Task was successfully updated.' }
format.json { render :show, status: :ok, location: #task }
else
format.html { render :edit }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
def destroy
#task.destroy
respond_to do |format|
format.html { redirect_to tasks_url, notice: 'Task was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_task
#task = Task.find(params[:id])
end
def set_project_session
#project_session = ProjectSession.find(params[:project_session_id])
end
def task_params
params.require(:task).permit(:name, :description)
end
end
routes:
Rails.application.routes.draw do
get 'hr_dashboard/index'
resources :roles
resources :project_sessions
devise_for :users
resources :tasks
resources :projects do
resources :project_sessions, except: [:show, :index]
end
resources :project_sessions do
resources :tasks, except: [:show, :index]
end
authenticated :user do
root 'admindashboard#index', as:"authenticated_root"
end
root 'welcome#index'
get 'userdashboard/index'
get 'admindashboard/index'
get 'welcome/index'
end
View for creating new task
<div class="container">
<h1>New Task</h1>
<%= 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 |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 :description %><br>
<%= f.text_area :description %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<%= link_to 'Back', tasks_path %>
</div>
I figured it out!
I had forgotten to add #project_session in
<%= form_for([#project_session, #task]) do |f| %>
just added that and it worked.
In your create action of Task controller, you have to add:
#task= #project_session.tasks.build(task_params)
Because right now, you're not telling the task, to build from the project_session (or with respect to the project_session) you're just telling it to create a new task.
#task = Task.new
And in the routes.rb file, you've prepared for that to happen by nesting the resources, so it's currently looking for the ID of a task that belongs_to project_session. But can't find any.
And also, in your form_for element when creating a ProjectSssion you have let that form know which route it should belong to - I guess you could say - since you still have the un-nested resources available:
resources :tasks
If project_sessions shouldn't be creatable without a parent, there's no reasons for keeping that, so you should just remove it.
Anyways, here's what the form_for should look like:
<%= form_for([#project_session, #task]) do |f| %>

No route for post comments

ive been having a problem now for 2 days, i followed many videos and tutorials on how to add comments to a post, and for everyone else it seemed to work smoothly.
I got 4 controllers, Users,Posts,Comments and Walls , basically this site is gonna be a facebook clone. So im displaying everything on the Wall index.html.erb
The error im getting is:
No route matches {:action=>"index", :controller=>"comments", :post_id=>nil} missing required keys: [:post_id]
Routes:
Rails.application.routes.draw do
devise_for :users
resources :uploads
resources :users
resources :posts do
resources :comments
end
resources :walls
root 'walls#index'
end
Comments-controller:
class CommentsController < ApplicationController
before_action :find_post
def index
#comments = Comment.all
end
def new
#post = Post.find(params[:post_id])
end
def create
#comment = #post.comments.create(params[:comment].permit(:content))
#comment.post_id = #post.id
#comment.user_id = current_user.id
#comment.save
# #comment = #post.comments.create(params[:comment].permit[:content])
# #comment.post_id = #post.id
respond_to do |format|
if #comment.save
format.html { redirect_to root_path }
# format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
# def comment_params
# params.require(:comment).permit(:content)
# end
def find_post
#post = Post.find(params[:post_id])
end
end
Posts-controller:
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
def new
#post = Post.new
#comment = Comment.new
end
# GET /posts/1/edit
def edit
#post = Post.find(params[:id])
#post.user_id = current_user.id
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
#post.user_id = current_user.id
#post.user = current_user
respond_to do |format|
if #post.save
format.html { redirect_to root_path }
# 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
#post.user_id = current_user.id
#post.save
respond_to do |format|
if #post.update(params[:post].permit(:image,:content,:youtube_url))
format.html { redirect_to root_path, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
format.json { respond_with_bip(#post) }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
format.json { respond_with_bip(#post) }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post = Post.find(params[:id])
#post.destroy
respond_to do |format|
format.html { redirect_to root_path, 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(:content, :image, :username, :avatar, :youtube_url,:image_cache)
end
end
I am rendering the form in the index.html.erb for the wall controller index
<%= render "form" %>
And the form loop
views/walls/_form.html.erb
<div class="comments">
<%= form_for ([#post, #post.comments.build]) do |f| %>
byebug
<%= f.text_area :content, class: 'comments js-auto-size', id: 'alex2' ,:rows => 1 %>
<%= f.submit "Submit", class: "btn btn-default" %>
<% end %>
</div>
I dont understand why it cant find the post_id though :/
Since your comments is nested inside posts in routes, you have to pass post_id to the index in CommentsController
class CommentsController < ApplicationController
before_action :find_post
def index
#comments = #post.comments
end
end
# in view
<%= link_to "Comments", post_comments_path(#post) %>
Otherwise, you can define comments to be independent resources so you can do it without passing post_id
Rails.application.routes.draw do
resources :posts
resources :comments
end

Make unique object in rails

So I'm learning rails via writing some simple application and in that app I have two types of objects: Tasks and Projects.Sense is that all those objects can be created by user,user must be able to manipulate them and so on.Each task belongs_to project and project has_many tasks.But when I create new project - it already has all tasks from all another projects,so it looks like:
This '123' task was created by simply adding task to 'Project' but same task still appear in 'Another project'.How can I fix this bug and make my task unique?I think something must be added to task or projects model
but I don't know what should I add.
Here are corresponding models and controllers:
Task.rb
class Task < ActiveRecord::Base
belongs_to :project
end
Project.rb
class Project < ActiveRecord::Base
belongs_to :user
has_many :tasks, dependent: :destroy
validates :name, presence: true, uniqueness: true
end
tasks_controller.rb
class TasksController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
# GET /tasks
# GET /tasks.json
def index
#tasks = Task.all
end
# GET /tasks/1
# GET /tasks/1.json
def show
end
# GET /tasks/new
def new
#task = Task.new
end
# GET /tasks/1/edit
def edit
end
# POST /tasks
# POST /tasks.json
def create
#task = Task.new(task_params)
respond_to do |format|
if #task.save
format.html { redirect_to home_url }
format.json { render :show, status: :created, location: #task }
else
format.html { render :home_url }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tasks/1
# PATCH/PUT /tasks/1.json
def update
respond_to do |format|
if #task.update(task_params)
format.html { redirect_to home_url }
format.json { render :home_url, status: :ok, location: #task }
else
format.html { render :home_url }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tasks/1
# DELETE /tasks/1.json
def destroy
#task.destroy
respond_to do |format|
format.html { redirect_to home_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_task
#task = Task.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def task_params
params.require(:task).permit(:deadline, :name)
end
end
projects_controller.rb
class ProjectsController < ApplicationController
before_action :set_project, only: [:show, :edit, :update, :destroy]
# GET /projects
# GET /projects.json
def index
#projects = Project.all
end
# GET /projects/1
# GET /projects/1.json
def show
end
# GET /projects/new
def new
#project = Project.new
end
# GET /projects/1/edit
def edit
end
# POST /projects
# POST /projects.json
def create
#project = Project.new(project_params)
respond_to do |format|
if #project.save
format.html { redirect_to home_url }
format.json { render :show, status: :created, location: #project }
else
format.html { render :home_url }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /projects/1
# PATCH/PUT /projects/1.json
def update
respond_to do |format|
if #project.update(project_params)
format.html { redirect_to home_url }
format.json { render :show, status: :ok, location: #project }
else
format.html { render :home_url }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
# DELETE /projects/1
# DELETE /projects/1.json
def destroy
#project.destroy
respond_to do |format|
format.html { redirect_to home_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_project
#project = Project.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def project_params
params.require(:project).permit(:name)
end
end
task view -
<% #tasks.each do |task| %>
<div class="row task">
<div class="col-xs-12">
<div class="col-xs-1 checkbox">
<%= check_box_tag 'accept' %>
</div>
<div class="col-xs-8 taskbody">
<%= task.name %>
</div>
<div class="mini-glyph">
<div class="col-xs-1">
<span class="glyphicon glyphicon-arrow-up"></span>
<span class="glyphicon glyphicon-arrow-down"></span>
</div>
<div class="col-xs-1">
<%= link_to edit_task_path(task) do %>
<span class="glyphicon glyphicon-pencil"></span>
<% end %>
</div>
<div class="col-xs-1">
<span><%= link_to " ", task, method: :delete, data: { confirm: 'Are you sure?' }, class:"glyphicon glyphicon-trash" %></span>
</div>
</div>
</div>
</div>
<% end %>
To set the project_id when you create a task, add something like this to your form:
<%= f.select :project_id, options_for_select(Project.choices) %>
then in project.rb
def self.choices
all_projects = []
Project.find_each do |project|
# show the name but save the id
all_projects << [project.name, project.id]
end
all_projects
end
Then change display the tasks with Task.where(project_id: project_id) instead of Task.all as the first two comments suggest.

Rails - using link_to on application.html.erb for nested resource not getting id

I have a sidebar on application.html.erb, and the links should go to /brands/[brand_id]/coupons
I used brand_coupons_path(#brand) but I get an error saying 'No route matches {:action=>"index", :brand_id=>nil, :controller=>"coupons"} missing required keys: [:brand_id]'
resources :brands do
resources :coupons, :sales
end
class Brand < ActiveRecord::Base
has_many :coupons
has_many :sales
accepts_nested_attributes_for :coupons
accepts_nested_attributes_for :sales
end
class Coupon < ActiveRecord::Base
belongs_to :brand
end
<div class="sidebar">
<ul class="sidebar-list">
<li><a class="sidebar-header">Most Popular Brands</a></li>
<% #brands.each do |brand| %>
<% if current_page?(:controller => 'coupons') %>
<li><%= link_to brand.name, brand_coupons_path(#brand), :class => "sidebar-link" %></li>
<% else %>
<li><%= link_to brand.name, brand_sales_path(#brand), :class => "sidebar-link" %></li>
<% end %>
<% end %>
</ul>
</div>
class CouponsController < ApplicationController
before_action :set_coupon, only: [:show, :edit, :update, :destroy]
# before_filter :load_brand
def new
#coupon = Coupon.new
end
def index
#coupons = Coupon.where(brand_id: params[:brand_id])
end
def show
end
def create
#coupon = Coupon.new(coupon_params)
respond_to do |format|
if #coupon.save
format.html { redirect_to '/', notice: 'Coupon was successfully created.' }
format.json { render :show, status: :created, location: #coupon }
else
format.html { render :new }
format.json { render json: #coupon.errors, status: :unprocessable_entity }
end
end
end
class BrandsController < ApplicationController
before_action :set_brand, only: [:show, :edit, :update, :destroy]
# GET /brands
# GET /brands.json
def index
#brands = Brand.all
end
# GET /brands/1
# GET /brands/1.json
def show
end
# GET /brands/new
def new
#brand = Brand.new
end
# GET /brands/1/edit
def edit
end
# POST /brands
# POST /brands.json
def create
#brand = Brand.new(brand_params)
respond_to do |format|
if #brand.save
format.html { redirect_to #brand, notice: 'Brand was successfully created.' }
format.json { render :show, status: :created, location: #brand }
else
format.html { render :new }
format.json { render json: #brand.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /brands/1
# PATCH/PUT /brands/1.json
def update
respond_to do |format|
if #brand.update(brand_params)
format.html { redirect_to #brand, notice: 'Brand was successfully updated.' }
format.json { render :show, status: :ok, location: #brand }
else
format.html { render :edit }
format.json { render json: #brand.errors, status: :unprocessable_entity }
end
end
end
# DELETE /brands/1
# DELETE /brands/1.json
def destroy
#brand.destroy
respond_to do |format|
format.html { redirect_to brands_url, notice: 'Brand was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_brand
#brand = Brand.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def brand_params
params.require(:brand).permit(:name, :logo)
end
end
You're passing an undefined #brand variable into your routes helpers, rather than the block variable brand. Change:
<%= link_to brand.name, brand_coupons_path(#brand), :class => "sidebar-link" %>
<%= link_to brand.name, brand_sales_path(#brand), :class => "sidebar-link" %>
to
<%= link_to brand.name, brand_coupons_path(brand), :class => "sidebar-link" %>
<%= link_to brand.name, brand_sales_path(brand), :class => "sidebar-link" %>
What does #brand contains? I think you should put an object to #brand variable.
Like this. #brand = Brand.find(params[:id])
Can we see the controller of your index?

Resources