Search code examples
ruby-on-railsrubyactiverecordmodels

How to target a model and access records nested two levels deep in Ruby on Rails?


I am trying to create a todo list application in ruby on rails that has 3 models as nested resources.

For Example:

  • User: has_many :todo_lists
  • TodoList: has_many :todo_items & belongs_to :user
  • TodoItem: belongs_to :todo_list & scope :completed, -> { where.not(completed_at: nil) }

Running @user.todo_lists returns the user's todo lists.

Running @todo_lists.todo_items returns the todo list's todo items.

Running @todo_lists.todo_items.completed returns the todo list's completed todo items.

But

Running @user.todo_lists.todo_items returns error: NoMethodError: undefined method 'todo_items'.

Running @user.todo_lists.todo_items.completed also returns error: NoMethodError: undefined method 'todo_items'.

We have tried @user.todo_lists.map(&:todo_items).flatten which returns all the todo items for a user but we cannot add the .completed scope.

Am I on the right track?


Solution

  • Try using has_many :through association.

    In your user model define association:

    has_many :todo_items, through: :todo_lists
    

    You should than be able to get todo_items without getting todo_lists first.

    user.todo_items.completed
    

    Using the map you were on the right track.

    user.todo_lists.map { |todo_list| todo_list.todo_items.completed }.flatten