mongo.cr
mongo.cr copied to clipboard
Undefined method [] for Nil:Class during compilation
Getting a problem when trying to create an instance of a collection, I can't get past the compilation as I think the compiler is trying to account for the client instance possibly being 'Nil' and there being no method handlers for '[]' on the object which is very odd, as I have validation expressions outside the object. If someone could give a hand on why this is happening, that'd be great.
Implementation:
class MxMongo
-»»»# Initialise everything we need
-»»»def initialize(host : String, username : String, password : String, port : String)
-»»»-»»»@client = Nil
-»»»-»»»@database = "aggregation"
-»»»-»»»self.connect(host, username, password, port)
-»»»end
-»»»
-»»»# Connect to the database
-»»»def connect(host : String, username : String, password : String, port : String)
-»»»-»»»@client = Mongo::Client.new "mongodb://#{username}:#{password}@#{host}:#{port}/#{@database}"
-»»»-»»»return @client
-»»»end
-»»»# Get an instance of the database
-»»»def get_instance
-»»»-»»»if @client.not_nil! && db.not_nil!
-»»»-»»»-»»»return @client
-»»»-»»»else
-»»»-»»»-»»»return Nil
-»»»-»»»end
-»»»end
-»»»def get_collection(collection : String)
-»»»-»»»if [email protected]? && !collection.nil?
-»»»-»»»-»»»client = @client
-»»»-»»»-»»»return client.not_nil![collection] if collection.not_nil!
-»»»-»»»else
-»»»-»»»-»»»return Nil
-»»»-»»»end
-»»»end
end
Error I recieve:
test = mongo_client.get_collection("aggregation")
^~~~~~~~~~~~~~
in classes/init_mongo.cr:27: undefined method '[]' for Nil:Class (compile-time type is (Mongo::Client | Nil:Class))
return client.not_nil![collection] if collection.not_nil!
^
================================================================================
Nil:Class trace:
/usr/lib/crystal/object.cr:156
def not_nil!
^~~~~~~~
/usr/lib/crystal/object.cr:157
self
^~~~
Apologies for the formatting, copied from vim
i think you meant to write it as @client not just client
@datanoise Nope, unfortunately not, I offload the @client instance to a local var, due to the read write differences between instance vars and local vars, I've had issues in the past with Crystal not allowing me to set instance vars etc, so tried offloading to a local var just to see if that fixed it.
If you read the code though, you can see here that I definitely define the client var before being used:
-»»»def get_collection(collection : String)
-»»»-»»»if [email protected]? && !collection.nil?
-»»»-»»»-»»»client = @client
-»»»-»»»-»»»return client.not_nil![collection] if collection.not_nil!
-»»»-»»»else
-»»»-»»»-»»»return Nil
-»»»-»»»end
-»»»end
why Nil is uppercased? is it intentional?
In this instance they would resolve to the same thing anyway, no? As it's a return value, and Nil is just the class, and nil is an global instance of the Nil class. Correct me if I'm wrong.
No, they are not the same thing. 'Nil' is the class type (in this case struct type) and nil is its singleton instance. Nil.not_nil! == Nil as for any other object, but nil.not_nil! will raise an exception. That means that your @client variable could be either an instance of Mongo::Client class or Nil class type and the compiler correctly detects that Nil class type has no method [] defined.
Ah awesome, thanks for the explanation, was curious what was actually going on under the hood, as I've experienced something similar to this I think, and I did not even consider the difference between Nil and nil