Reputation: 727
I am trying to create a todo list application in ruby on rails that has 3 models as nested resources.
For Example:
has_many :todo_lists
has_many :todo_items
& belongs_to :user
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?
Upvotes: 2
Views: 1027
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
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