Search code examples
ruby-on-railsruby-on-rails-4has-many-throughnomethoderror

NoMethodError in TasksController#create when creating new task from project


I have a projects model and a task model, however a task can have many projects and vice versa...so i created a relationship model between the two. Now from the project profile, i want to be able to create a task and automatically have it create the task and the relationship between the new task and the project it was created from.

However when i try to accomplish this i am getting the following error:

NoMethodError in TasksController#create
undefined method `related?' for nil:NilClass

My Tasks Controller

class TasksController < ApplicationController

  def new
    @task = Task.new
  end

  def create
    @task = current_user.own_tasks.build(task_params)
    if @task.save
      flash[:success] = "Your task has been created."
      redirect_to @task
      @project.relate!(@task) unless @project.related?(@task) # establishes task relationship w/ project only if relationship doesn't already exist
    else
      render 'task'
    end
  end

private

def task_params
  params.require(:task).permit(:title, :description, :user_id, taskrelationship_attributes: [:taskproject_id, :projecttask_id])
end

end

My TaskRelationship Model:

class TaskRelationship < ActiveRecord::Base
  belongs_to :taskproject, class_name: "Project"
  belongs_to :projecttask, class_name: "Task"
  validates :taskproject_id, presence: true
  validates :projecttask_id, presence: true
end

My Task Model:

class Task < ActiveRecord::Base
  belongs_to :owner, :foreign_key=>'user_id', :class_name=>'User'

  has_many :reverse_taskrelationships, foreign_key: "projecttask_id",
                                   class_name: "TaskRelationship",
                                   dependent: :destroy
  has_many :taskprojects, through: :reverse_taskrelationships, source: :taskproject

  validates :title, presence: true
  validates :description, presence: true, length: { maximum: 140 }
end

end Project Model:

class Project < ActiveRecord::Base
  belongs_to :owner, :foreign_key=>'user_id', :class_name=>'User'

  has_many :tasks
  has_many :taskrelationships, foreign_key: "taskproject_id", dependent: :destroy
  has_many :projecttasks, through: :taskrelationships, source: :projecttask

  validates :title, presence: true
  validates :background, presence: true

  def related?(some_task)
   taskrelationships.find_by_projecttask_id(some_task.id)
  end

  def relate!(some_task)
   self.taskrelationships.create!(projecttask_id: some_task.id)
  end
end

I'm not sure where i'm going wrong... thx,

UPDATE:

I've added the following line at the top of the create method as marsAtomic pointed out was missing...

@project = Project.find(params[:id]) 

Solution

  • Look closely at the error:

    undefined method `related?' for nil:NilClass
    

    You're trying to call the related? method on a nil object, in your case, Project. Your create method doesn't define @project anywhere.

    UPDATE:

    Your added code:

    @project = Project.find(params[:id])
    

    will not find the correct project because the param :id refers to the ID of the task rather than its associated project. Remember, you're in tasks_controller.rb.

    You'd need something like the following, assuming each Task has a reference to a Project via your projecttask_id field:

    @project = Project.find(params[:projecttask_id])
    

    Keep in mind that projecttask_id is kind of an odd way to name a foreign key. It would be less confusing to name it project_id.