3

Context:

I have a company model with many projects, having many tasks. The company also has many employees, which in turn have many tasks.

Schema:

enter image description here

Problem:

I'm building a form to create a project where the user can add multiple tasks. Upon submission the form should create a single project record, one or more task records with hours and employee_id attributes and (!) check if the employee name already exists in the database or create a new one.

I've approached this by adding jquery autocomplete to the form and defining a virtual attribute with a getter and setter method in my Task model. Similar to Railscast #102.

This succesfully sets the employee_id in tasks and creates a new employee record with employee name and task_id.

The problem is currently that the model does not save a company_id.

My code:

class Task < ActiveRecord::Base
    belongs_to :project
    belongs_to :employee

    def employee_name
      employee.try(:name)
    end

    def employee_name=(name)
      self.employee = Employee.find_or_create_by(name: name) if name.present?
    end
end

Question:

How can I make the company_id attribute of the parent model available the setter method of my Task model? Like so:

def shareholder_name=(name)
    self.shareholder = Shareholder.find_or_create_by(name: name, company_id: company_id) if name.present?
end

At the moment this yields the error:

undefined local variable or method "company_id" for #<Task:0x98438b8>

EDIT:

Or, if I try project.company_id this tells me project is a NilClass:

undefined method company_id for nil:NilClass

UPDATE:

Still unsolved. Any ideas why project is nil here?

Matthias
  • 1,884
  • 2
  • 18
  • 35

1 Answers1

1
class Task < ActiveRecord::Base
  belongs_to :project
  belongs_to :employee

  def shareholder_name=(name)
    self.shareholder = Shareholder.find_or_create_by(name: name, company_id: project.company_id) if name.present?
  end
end 

also, so typical pattern with rails, for instance where you have belongs_to :project, that would add an instance method called project to Task, that instance method could then be used to get project associated with task and subsequently the associated company_id in case that may be of interest

Drew
  • 2,583
  • 5
  • 36
  • 54
  • Hi @Drew, thanks for your answer. I indeed got that far myself. I think the question of my post should have been how to get the `company_id` attribute accessible in the `Task` model. Any suggestions? – Matthias Feb 20 '16 at 13:58
  • response revised with what if I had to guess could facilitate getting `company_id` in `Task` in case that may be of interest – Drew Feb 20 '16 at 16:38
  • Hmm, if I add to the setter method (`company_id: foo`) and `def foo` as `project.company_id`, I get the exception `no block given (yield)`. – Matthias Feb 20 '16 at 16:52
  • you wouldn't have your revised code off-hand by any chance would you? – Drew Feb 20 '16 at 16:57
  • Not sure what you mean by 'off-hand'? – Matthias Feb 20 '16 at 17:02
  • oh sorry, in other words available without preperation, or at the ready – Drew Feb 20 '16 at 17:03
  • also, response revised! in case that may be of interest – Drew Feb 20 '16 at 17:12
  • Thanks @Drew. Unfortunately, this also gives me a LocalJumpError `no block given (yield)`. Would there be a way to explicitly pass this attribute from the `Project` model to my `Task` model? – Matthias Feb 20 '16 at 17:16
  • Hi @Drew, regarding your "off-hand" question and in case you still feel helpful, see the unredacted version here: http://stackoverflow.com/questions/35536824/rails-why-is-my-parent-model-nil-in-child-model :-) – Matthias Feb 21 '16 at 13:57
  • matthias, guessing there is no project associated with the task. had you been creating a new record? or thoughts? – Drew Feb 21 '16 at 14:05