0
votes

I have the following three models:

A TestRun model, A TestResult model and a Test model. A TestRun has many TestResults, and a TestResult has one Test. (A test can have many results but its not really relevant for this question)

I am eager loading everything into a test run using the following:

test_run = TestRun.includes(test_results: [:test]).find(params[:id])

This works fine, creating three separate queries. The problem now is that I want to scope one of the queries. I want to exclude a field (called 'log') from the test_results in this query. I created a scope in the TestResult model but I am not sure how to apply it in this situation.

I could do something like this:

tr = TestRun.find(id)
tr.test_results.without_log.include(:test).load

Which works except for whenever I call the third association it isn't preloaded. E.g.

tr.test_results[1].test #This causes an additonal query

I am trying to keep one TestRun model with all the other associations preloaded. Is this possible?

Edit:

def self.without_log
    select(column_names-['log'])
end
1
I don't know what without_log looks like but TestRun.find(id).test_results.includes(:test).without_log should work if without log is just a where clause. Check This Out for More. You can force eager loading using eager_loadengineersmnky
I'll add without_log to the original post. But yes your query does work but it doesnt save anything. I want to essentially call this query and load all of it into an object that I can pass around. I could do it separately but my serializers and everything are setup, and except a TestRun object that is hopefully fully loaded and doesn't make any additonal queriesuser2644040
If I could take the results from the query you gave me and store it back into a TestRun object that would work fine, im just not sure there is an easy way to do that. Not doing that would require me to change the way my serializers are currently working.user2644040
Do you always want the associations eager loaded? If so or even if not posting the TestRun model associations might be beneficial but you can default a scope with eager loading. This way when you load a TestRun it will automatically eager load the associationsengineersmnky

1 Answers

0
votes

I am going to try and answer this question as best as possible.

IF you always want the associations eager loaded then I would try using default_scope

class TestRun < ActiveRecord::Base
   has_many :test_results
   default_scope includes({:test_results=> :test})
end

That should eager load the associations on every query so TestRun.find(id).without_log should all ready have these items eager loaded.

If you do not always want the associations eager loaded then I would suggest a scope such as

class TestRun < ActiveRecord::Base
  has_many :test_results
  scope :find_with_eager_load,->(id){
       where(id: id).includes({:test_results => :test}).without_log
  }
end

Then call as TestRun.find_with_eager_load(id) and it should produce the requested result. You do have another option although I am uncertain of the implications but you could try

class TestRun < ActiveRecord::Base
  has_many :test_results
  has_many :tests, through: :test_results
end

And then either create a scope or default scope or call as TestRun.find(id).includes(:test_results,:tests).without_log

and it should produce a similar result although I am uncertain of the query when using a has_many through a has_many association. Also since you are not using a where or order clause you many have to change includes to eager_load to force singular queries.

Hope this helps with what you are trying to achieve