Search code examples
ruby-on-railsactiverecordfind-by-sql

Active Record find_by_sql and rspec expect block. New ids are created for no reason


I am working on a complex SQL query with rails 4.2.1

def self.proofreader_for_job(job)
  User.find_by_sql(
    "SELECT * FROM users
     INNER JOIN timers 
     ON users.id = timers.proofreader_id
     INNER JOIN tasks
     ON tasks.id = timers.task_id
     WHERE tasks.job_id = #{job.id}")
end

My schema is (jobs has_many tasks, tasks has_many timers, and a timer belongs_to a user(role: proofreader) through the foriegn key proofreader_id)

The issue is that when I call the method it is returning what is the correct user's email and attributes but the id doesn't match.

For exeample User.proofreader_for_job(job) returns

[#<User id: 178, email: "[email protected]">]

[email protected] is the correct email, but I don't have a user in my db with an id of 178.

User.all just returns

 [#<User id: 12, email: "[email protected]">,
 #<User id: 11, email: "[email protected]">]

I noticed the issue in my rspec tests, but it happens on both development and test environments.

Does anyone have any idea why my methods is returning a user with such a high id. Is this done by design, if so why?

Thank you.


Solution

  • Since you're doing 'Select *', your statement will return all columns for each of the tables in the JOIN statement. So when you're casting the output from the SQL statement to a User type, I think the wrong 'id' column is being grabbed for the User id (likely the timers or tasks table).

    Try explicitly specifying the columns to return like the below statement:

    User.find_by_sql(
        "SELECT users.id, users.email FROM users
        INNER JOIN timers 
        ON users.id = timers.proofreader_id
        INNER JOIN tasks
        ON tasks.id = timers.task_id
        WHERE tasks.job_id = #{job.id}")
    end