Make NullObject Evaluation False in Ruby

After implementing the Null Object Pattern in a Rails application (also described in episode 112 of RubyTapas), I reorganized some code, but there is a syntax construct that doesn't seem to work anymore.

I used to write operators like current_user || redirect_out current_user || redirect_out , where if current_user was set, it would return it, and if it was nil , it is redirected, but now current_user can be an instance of Null::User and, therefore, "true", and this fragment will never be redirected.

I tried to define the || operator but did not work. Is it possible to use this syntax with objects with null (but "true")?

+6
source share
3 answers

I think that you only half accepted this pattern and incorrectly accepted its spirit. I understand that the very purpose of the template is to avoid || .

You must have some purpose for calling current_user || redirect_out current_user || redirect_out , and this can do something with it or get some attribute. For example, suppose your code has:

 (current_user || redirect_out).foo 

If current_user not an instance of Null::User , you would like to call it foo . In this case, you need to define Null::User#foo as redirect_out (perhaps it will be followed by a few more operations like foo for other classes).

 class Null::User def foo; redirect_out ... end end 

and instead of (current_user || redirect_out).foo you should just do

 current_user.foo 

If current_user not an instance of Null::User , it calls foo . When this is such an instance, then the redirect_out ... procedure will be called on it.

+6
source

I once wrote an article about how it is impossible to define "false" objects in Ruby and why attempts to make a false Null Object are usually wrong.

Basically, the best thing you can do is create a dimly inconsistent object using #! , nil? etc.

As others have noted, usually when you want to make a Null Object β€œfalse” because you are not using full polymorphism. The whole purpose of a Null object is to avoid type checks, and checking for NilClass in the form of an if is the same type checking as any other.

However, sometimes this is inevitable. Therefore, in my Naught library , I generate an Actual() conversion helper function (among several other conversions). Actual() converts null objects back to nil values, but leaves all other objects alone. Therefore, for cases when you need to include the truth of objects, you can do it as follows:

 if Actual(obj_that_might_be_null) # ...do stuff... end 
+5
source

There are exactly two objects in Ruby that are false: nil and false . Period.

Unfortunately, it is impossible to define your own false objects, and it is also impossible to redefine logical operators (except for not / ! ). This is a shame, in fact: it is one of the main pillars of OO that an object can mimic another object, but in Ruby it is not possible to simulate false or nil , therefore breaking one of the fundamental properties of OO in a language with a pretty good OO model.

+3
source

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


All Articles