6

I'm a beginner and it's hard to explain my problem:

My models:

class Skill  
  has_many :categories
  has_many :positions, :through => :categories
end

class Category
  belongs_to :skill
  has_many :positions  
end

class Position
  belongs_to :category
  has_one :skill, :through => :category    
end

I can successfully eager load everything, like this:

@skills = Skill.includes(:positions)

However sometimes I want to apply a scope on the Positions:

class Position
...
  scope :active, where(:hidden => false)
end

I wish I could do:

@skills = Skill.includes(:positions.active)

Instead, I apply the scope in the views, but the eager loading doesn't work anymore:

<%= skill.positions.acitve ... %>

Is it possible to have both eager loading and scope?

Martin Petrov
  • 2,633
  • 4
  • 30
  • 44

2 Answers2

8

You could use another association:

class Skill  
  has_many :categories
  has_many :positions, :through => :categories
  has_many :active_positions, :through => :categories
end

class Category
  belongs_to :skill
  has_many :positions  
  has_many :active_positions, :class_name => "Position", :conditions => {:hidden => false}
end

class Position
  belongs_to :category
  has_one :skill, :through => :category    
end

And then

@skills = Skill.includes(:active_positions)

But then you'll get two associations. If you ever use skill.positions, all the skill's positions will be loaded from the database. You should only use skill.active_positions.

Michaël Witrant
  • 7,525
  • 40
  • 44
  • Thank you Michaël. It worked perfectly. I used some if/else in the controller (if the user is logged_in), and also if/else in the views, like: <% user_signed_in? ? skill.positions : skill.active_positions %> – Martin Petrov May 30 '11 at 05:23
  • For rails 6+ you can do it like this has_many :incomp_bookings, -> { where(bookings: { status: :incomplete }) }, class_name: 'Booking' – Abdul Basit Mangat Jan 13 '21 at 11:15
0

Try this:

@skills = Skill.includes(:positions).where('position.active = TRUE')
Tudor Constantin
  • 26,330
  • 7
  • 49
  • 72
  • It returns: "SQLite3::SQLException: no such column: position.active ..." – Martin Petrov May 29 '11 at 19:47
  • 2
    It's maybe because the table is called 'positions', so it should be 'positions.active' (you're referring to the table here, not the Model. – Pierre May 30 '11 at 05:27
  • 1
    You can't use a `where` condition here because when Rails eager loads, it makes two requests. You could use such a condition with a `join` but it has nothing to do with eager loading. – Michaël Witrant May 30 '11 at 06:39
  • The 'where' jeopardises the eager loading effort. – Boti Aug 11 '15 at 07:58