1

I have a class User that inherits from ApplicationRecord. When I check User.ancestors.include?(Class), the result is false but for User.class, the result is Class.

What's the use case for the information supplied by the class method in such cases? What does it really tell me to be of practical use? It doesn't seem to have anything to do with inheritance.

borunbabu
  • 33
  • 6

4 Answers4

2

User is a class. All classes are instances of the class Class (i.e., User.class #=> Class). Therefore, all instance methods defined on Class, or on Class's ancestors, can be invoked on User (i.e., every instance method of Class is a class method of User).

For example, one of Class's instance methods is instance_methods. One can therefore execute User.instance_methods to obtain an array of User's instance methods.

Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100
2

What's the use case for the information supplied by the class method in such cases? What does it really tell me to be of practical use? It doesn't seem to have anything to do with inheritance.

class works the same way for every object. Calling class on a class provides the same information as calling class on an instance. That's because in Ruby, classes are instances, too.

'foo'.class returns String because 'foo' is an instance of String. Likewise, User.class returns Class because User is an instance of Class.

In particular, User is not an instance of ApplicationRecord.

It might not be obvious that User is an instance of Class when creating it via the class keyword:

class User < ApplicationRecord; end

But it becomes very obvious when you create it explicitly via Class.new: (both examples produce the same result)

User = Class.new(ApplicationRecord)
User.class #=> Class

Because the above is just like: (using String.new for demonstration purposes)

foo = String.new('foo')
foo.class #=> String
Stefan
  • 109,145
  • 14
  • 143
  • 218
1

Classes in Ruby are first-class objects—each is an instance of class Class

User is an object of class Class (which inherits from Object). class is an instance method of Object. It returns the class of the object. Therefore, User.class returns Class. Every object will have this method, and it is useful to know what the object is (e.g., for debugging). Consider this code:

1.class
# => Fixnum
"q".class
# => String

The reason why User.ancestors does not return Class is because it returns the modules included in the module. For example, Class.ancestors will include Class, but not User because User is an object of Class, which includes its own modules.

Moti Korets
  • 3,738
  • 2
  • 26
  • 35
  • I have restored the question in its original form. Editor had removed the reference to ApplicationRecord. I guess source of my question is: If User class inherits from ApplicationRecord, why is it (ApplicationRcord) not its class? – borunbabu May 08 '18 at 05:29
  • Moti, I am unclear about what you mean by Name.ancestors. What is Name? – borunbabu May 08 '18 at 07:09
  • `User` is an object of type `Class` thus `User.class` is `Class` as literal `1` is an object of type `Fixnum`. If you run `User.ancestors` you should see `ApplicationRecord` among them – Moti Korets May 08 '18 at 07:33
  • Sorry for the confusion i meant `User` i edited my answer and comment. It is a bit confusing. – Moti Korets May 08 '18 at 07:34
  • You answer is very nice the main confusion point is to remember that a Class definition is also an object. And clarify where the methods such as `class` (`Object`) and `ancestors` (`Module` class) come form – Moti Korets May 08 '18 at 07:44
1

After reading another StackOverflow post, I realized that it can only be understood by keeping the following in mind:

  1. User class has a double role. It plays Class as well as Object.
    • As Class, it lets other classes inherit from it.
    • As Object, it inherits the class method all the way up from the Object class.
  2. If I wanted my User.class to behave on the traditional lines (that is, User.class shows ApplicationRecord), then I have to override it as follows:

    class User def self.class self.superclass end end

borunbabu
  • 33
  • 6
  • `'foo'.class` returns `String` because `'foo'` is an instance of `String`. Why should `User.class` return `ApplicationRecord`? Obviously, `User` is not an instance of `ApplicationRecord`. – Stefan May 08 '18 at 07:13
  • Because it is an object and it inherits from ApplicationRecord. Doesn't that amount to anything? – borunbabu May 08 '18 at 07:39
  • But that's not what `class` is for. `class` returns the class an object has been instantiated from (instantiated != inherited). `User` is an instance of `Class`. It therefore responds to the instance methods of `Class`, like [`superclass`](http://ruby-doc.org/core-2.5.0/Class.html#method-i-superclass). It does not respond to the instance methods of `ApplicationRecord`. – Stefan May 08 '18 at 07:48
  • Yes, that's what I am trying to get my head around. What is the use case for an instance that does not inherit? It will be a great help if you can explain that. – borunbabu May 08 '18 at 07:55
  • What do you mean by _"an instance that does not inherit"_? – Stefan May 08 '18 at 08:19