Grant David Bachman
Grant David Bachman

Reputation: 2248

Ruby '.find' method only returning first occurrence

I have models as follows: User has_many goals, Goal has_many tasks, Task has_many day_tasks. I'm trying to write a method which finds all day_tasks that

  1. belong to a certain user
  2. have :target_date == Date.today (target_date is a column in the day_tasks table).

I want to put the results into the @day_tasks array.

my code:

@user = current_user
@day_tasks = DayTask.find { |x| x.task.goal.user == @user && x.target_date == Date.today }

This code only returns the first record that matches these criteria. I've also tried using the DayTasks.where method with the same code in the braces, but I just a "Wrong number of arguments ( 0 for 1 )" error. Could someone explain why my method only returns the first occurrence and what exactly the difference is between .find and .where?

Upvotes: 9

Views: 22969

Answers (2)

Tilo
Tilo

Reputation: 33752

please check the ActiveRecord Query Interface for Rails 3.x :

http://m.onkey.org/active-record-query-interface

http://guides.rubyonrails.org/active_record_querying.html

you'll probably want find(:all, ...) or where()

Upvotes: 1

Ryan Bigg
Ryan Bigg

Reputation: 107738

You wrote this:

@day_tasks = DayTask.find { |x| x.task.goal.user == @user && x.target_date == Date.today }

The find method here is actually falling back to Enumerable's find, which is an alias for detect, which takes a block and will return the first element in that collection that matches the block's conditions or will return nil.

In order to fix this, you're going to need to use ARel's query stuff that's built-in to ActiveRecord.

DayTask.joins(:task => { :goals => :user }).where("users.id = ? AND day_tasks.target_date = ?", @user.id, Date.today)

The joins method here will join the tables that match the association names in your DayTask model and related models. This means you must have a task association on the DayTask model and on that model have a goals association and on the goals model have one for user.

The where will then construct an SQL condition that will query the joins to find all records that belong to a user and have a target_date of today.

Upvotes: 14

Related Questions