简体   繁体   中英

Understanding Eager Loading - Rails

I'm trying to understand the concept of eager loading and what better way than implementing the concept right into an actual app. As I was trying this I ran into a problem. I'm getting this error when I try to load my assignment show page: undefined method "includes" for #<Assignment:0x007f82f6e41210> . I thought that if you include an association that is the concept of preloading so that you don't have to make multiple trips the the database? But clearly I'm doing something wrong here. Any help would be great here is my code and models that apply:

Timekeeper.rb

class Timekeeper < ApplicationRecord
  belongs_to :assignment

  validates :assignment_id, presence: true
end

Assignment.rb

class Assignment < ApplicationRecord
  validates :name, presence: true
  validates :description, presence: true

  belongs_to :account
  has_many :tasks
  has_many :assignment_relationships
  has_many :users, through: :assignment_relationships
  has_many :timekeepers

  def assigned_workers
    assignment_relationships.where(designated: true).count
  end
end

Assignment Controller:

  def show
    @assignment = current_account.assignments.find(params[:id]).includes(:timekeepers)
    @tasks = @assignment.tasks.all
    @task = @assignment.tasks.new
  end

Additionally how would I call this in the view once it works? Thanks for the help.

undefined method "includes" for #< Assignment:0x007f82f6e41210>

This means you are trying to call includes on an Assignment instance where as you must be chaining it to ActiveRecordCollection

You need to change the order of your methods use includes and then find .

def show
  @assignment = current_account.assignments.includes(:timekeepers).find(params[:id])
  @tasks = @assignment.tasks.all
  @task = @assignment.tasks.new
end

This will return you a single record of Assignment with id = params[:id] and will also eager load all the associated timekeepers .

You're getting this error because you're trying to use includes on a single object, find returns a single object in this statement.

@assignment = current_account.assignments.find(params[:id]).includes(:timekeepers)

You can do however this, because where returns an activerecord relation and you can do includes on that. Whether it makes sense to do this in your case you'll have to decide.

@assignment = current_account.assignments.where(id: params[:id]).includes(:timekeepers)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM