JosephA91
JosephA91

Reputation: 727

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:

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?

Upvotes: 2

Views: 1027

Answers (2)

Prashant Ravi Darshan
Prashant Ravi Darshan

Reputation: 545

You are getting these errors

1-

@user.todo_lists.todo_items

NoMethodError: undefined method 'todo_items'. 

Try with

@user.todo_lists

This will return you active record array or nil but if if you will get nil so you you will error undefined method 'todo_items'. for nil class

Now you are getting result in array so you can not use this method so you can go with the below command

@user.todo_lists.map{|m| {todo_lists: m, todo_items: m.todo_items}}

This will return you todo_lists in array and in first record of todo_lists you will get todo_items of that todo_list. if you want to get only todo items use below command

@user.todo_lists.map{|m| m.todo_items}

2-

@user.todo_lists.map(&:todo_items).flatten.completed 

use command

@user.todo_lists.map(&:todo_items).flatten.collect(&:completed) 

Upvotes: 0

jan.zikan
jan.zikan

Reputation: 1316

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

Upvotes: 3

Related Questions