6

I have the following situation in my Rails app. There are two models, let's say User and Company:

class User < ActiveRecord::Base
  belongs_to :company
  default_scope -> {where(removed_at: nil)}
end

and

class Company < ActiveRecord::Base
  has_many :users
end

What I want now is loading an Company record and include the Users

Company.unscoped.all.includes(:users)

What will result in a query to the users table which includes the default-scope. So I get the Company record with all not removed users prefetched. But in this case I do also want the Users where removed_at is not null (=> the removed User records). The "unscoped" method is only applied to the Company model, not to the User model.

Is there any way to do this? Thanks for any ideas!

milkman
  • 476
  • 9
  • 11

4 Answers4

4

Here is the solution I got working in my Rails 4.0 application

class User < ActiveRecord::Base
  belongs_to :company
  default_scope -> {where(removed_at: nil)}
end

class UserUnscoped < User
  self.default_scopes = []
end

class Company < ActiveRecord::Base
  has_many :users, class_name: "UserUnscoped"
end

Company.unscoped.all.includes(:users)
abstractcoder
  • 376
  • 2
  • 5
3

This method accepts a block. All queries inside the block will not use the default_scope:

User.unscoped { Company.includes(:users).all }

or:

User.unscoped do
 Company.includes(:users).all
end
user2503775
  • 4,267
  • 1
  • 23
  • 41
2

The relation is not preserving this state, when accessing it later (Rails 6.0)

A possible workaround for some cases is forcing the resolution, e.g.:

User.unscoped { Company.includes(:users).to_a }

to_a resolves the relation while in the block, so the scope is effectively removed.

estani
  • 24,254
  • 2
  • 93
  • 76
0

I had a greatly-branched STI models set. So the only approach, which works for me (Rails 4.2.5) is the following:

class UndeadUser < ActiveRecord::Base
  self.table_name = 'users'
end

class User < UndeadUser
  # real logic here
end

class Employee < User; end
class Manager < Employee; end

# grouping model
class Organization < ActiveRecord::Base
  has_many :employees

  has_many :users, class: UndeadUsers
  before_destroy :really_destroy_users_and_data! # in case of using acts_as_paranoid or paranoia gems it might be helpful
end

Solution from @abstractcoder doesn't work for me, because rails try to add WHERE users.type IN ('UndeadUser') when UndeadUser inherited from User.

evilguc
  • 910
  • 8
  • 14