Rails: ActiveRecord default_scope and class inheritance

In my application there are not only users, but also admins and superdomains. Since all three have the same attributes, I would like to use only one table with the additional attribute "role", which can be "user", "administrator" or "super_admin":

class User < ActiveRecord::Base # with nickname and password end class Admin < User def power puts "admin rights" end end class SuperAdmin < Admin def superpower puts "I've got the #{power}!" end end 

Now I want to do something like SuperAdmin.all to get only SuperAdmins. Using default_scope is similar to me:

 class SuperAdmin < Admin default_scope where(["role = ?", "super_admin"]) # ... end 

Now I am adding default_scope for admin too:

 class Admin < User default_scope where(["role = ?", "admin"]) # ... end 

Aaaand ... SuperAdmin.all returns nothing more. Why is this?

+4
source share
2 answers

If there is more than one default_scope, ActiveRecord binds them. Thus, SuperAdmin.all is looking for users with the roles of "Admin" and "SuperAdmin" - which can never be.

To get around this, you can override the default_scope of the inherited model, so just define self.default_scope yourself:

  class SuperAdmin < Admin def self.default_scope where(["role = ?", "super_admin"]) end #... end 

SuperAdmin.all should work as expected.

+7
source

Anyone who bothers me in this way is another option (better imo).

You can simply remove all default_scopes that are defined as an array.

 class Admin < User # This line will clear all the default_scopes defined in parent classes self.default_scopes = [] default_scope { ... } end 

Refer to the source code here https://apidock.com/rails/ActiveRecord/Base/default_scope/class . You can see that everything he does adds the next default area to the array.

 self.default_scopes = default_scopes + [scope] 
+1
source

Source: https://habr.com/ru/post/1432949/


All Articles