Null object pattern

I am trying to create a null object in my application. I would like to
assigned a null user object for anonymous/ mot-logged-in user, i.e. if
session variable has nil data.

In my User model, I have created a subclass like this:
class UnassignedUser < User

def save
false
end

def update
false
end

def username
“Unassigned”
end

def county_id
“-999”
end

def role_id
“5”
end
end

When I go to console to try out this model following is the output:

UnassignedUser.new
NameError: uninitialized constant UnassignedUser
from
/usr/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:278:in
load_missing_constant' from /usr/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:467:inconst_missing’
from
/usr/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/dependencies.rb:479:in
`const_missing’
from (irb):1

User.new
=> #<User id: nil, username: nil, section_id: nil, password_hash: nil,
password_salt: nil, role_id: nil, member_number: nil, tm_zone_info: nil,
region_id: nil>

UnassignedUser.new
=> #<UnassignedUser id: nil, username: nil, section_id: nil,
password_hash: nil, password_salt: nil, role_id: nil, member_number:
nil, tm_zone_info: nil, region_id: nil>

If I create user object first and then unassigneduser then it does not
give any error (although it is not doing what I intend to do).

Can anyone please elaborate on how to use null object pattern?

Thanks,
CS.

If you have a construct like this (all in the same file):

app/models/user.rb

class User < ActiveRecord::Base
# …
end

class UnassignedUser < User
def self.shout
puts “yeah”
end
end

script/console will behave like this:

UnassignedUser.shout
NameError: uninitialized constant UnassignedUser (…)

User
=> User(id: integer, login: string, email: string, password: string,
created_at: datetime, updated_at: datetime)

UnassignedUser.shout
yeah
=> nil

UnassignedUser gets only loaded when User is loaded. put it in its own
file and maybe add:
self.abstract_class = true

other than that you can load it whenever you want via include or
require.

MaD wrote:

If you have a construct like this (all in the same file):

app/models/user.rb

class User < ActiveRecord::Base
# …
end

class UnassignedUser < User
def self.shout
puts “yeah”
end
end

script/console will behave like this:

UnassignedUser.shout
NameError: uninitialized constant UnassignedUser (…)

User
=> User(id: integer, login: string, email: string, password: string,
created_at: datetime, updated_at: datetime)

UnassignedUser.shout
yeah
=> nil

UnassignedUser gets only loaded when User is loaded. put it in its own
file and maybe add:
self.abstract_class = true

Separate file in the model directory?

My objective is to avoid nil object errors when no user is logged in -
i.e. when session[:user] is nil.

However, I still need to call some instance methods on this object.

Please suggest me how can I do this?

other than that you can load it whenever you want via include or
require.

Hi Carlos,

On Sat, 2009-03-14 at 21:30 +0100, Carlos S. wrote:

My objective is to avoid nil object errors when no user is logged in -
i.e. when session[:user] is nil.

However, I still need to call some instance methods on this object.

Please suggest me how can I do this?

I’m thinkin’ I must be missin’ somethin’. Why can’t you use…

do_somethin’ unless session[:user].nil?

?

Best regards,
Bill

On Mar 14, 8:30 pm, Carlos S. [email protected]
wrote:

MaD wrote:

UnassignedUser gets only loaded when User is loaded. put it in its own
file and maybe add:
self.abstract_class = true

Separate file in the model directory?

Yes. The think to understand is that if your app hits the constant
Foo, rails will try and load foo.rb hoping that it defines Foo. If
there is no such foo.rb because Foo is in fact declared in bar.rb then
this don’t work.
You need to either put things where rails will find them automatically
or explicitly require them (using require_dependency)

Fred

I put UnassignedUser class in a separate file and added
self.abstract_class = true and also included requirement of User class.
Still same error.

Any more guidelines?

CS.

Frederick C. wrote:

On Mar 14, 8:30�pm, Carlos S. [email protected]
wrote:

MaD wrote:

UnassignedUser gets only loaded when User is loaded. put it in its own
file and maybe add:
� self.abstract_class = true

Separate file in the model directory?

Yes. The think to understand is that if your app hits the constant
Foo, rails will try and load foo.rb hoping that it defines Foo. If
there is no such foo.rb because Foo is in fact declared in bar.rb then
this don’t work.
You need to either put things where rails will find them automatically
or explicitly require them (using require_dependency)

Fred

It worked…
Had a typo… :frowning:

Thanks for the help.

Carlos S. wrote:

I put UnassignedUser class in a separate file and added
self.abstract_class = true and also included requirement of User class.
Still same error.

Any more guidelines?

CS.

Frederick C. wrote:

On Mar 14, 8:30�pm, Carlos S. [email protected]
wrote:

MaD wrote:

UnassignedUser gets only loaded when User is loaded. put it in its own
file and maybe add:
� self.abstract_class = true

Separate file in the model directory?

Yes. The think to understand is that if your app hits the constant
Foo, rails will try and load foo.rb hoping that it defines Foo. If
there is no such foo.rb because Foo is in fact declared in bar.rb then
this don’t work.
You need to either put things where rails will find them automatically
or explicitly require them (using require_dependency)

Fred

Hello Carlos,
I am glad it worked for you. Access control is a fundamental
requirement along with authentication. Jim N.'s Bort which is
available on Github, packages Role Requirements written by Tim H.
along with Restful Authentication for creating a baseline
application. Tim has done an excellent job of implementing a
“minimal” authorization plugin. I am using Bort to develop my own
toolkit for creating applications.
I looked at the article that you list above. It is very well written
and very nice to learn from. The key thing missing from it is that it
fails to deal with Roles and instead deals directly with users. I
think a minimal layer of roles between users and controllers is a key
requirement.
I am not saying that Role Requirement is the only plugin that
addresses it. It is just that it packaged with Bort which has other
key plugins in addition to Restful Authentication and Role
Requirements. Gets the job done.
So instead of saying session[:current_user].nil? you may want to say
[:current_user].has_role?(‘anonymous’) for example. See the method
“has_role?” provided by Role Requirement? That is the key in my
opinion.
I may be wrong, but that is where I am going with this.
Hope this helps.
Bharat

In that case I won’t get any user object.
Basically I am trying to implement in my application as mentioned here:
http://pivotallabs.com/users/nick/blog/articles/272-access-control-permissions-in-rails

For this I have some instance methods in User class. So the
‘do_somethin’ is basically not optional (only if user is logged in). So
as suggested in the article, I am trying to create a null object.

I also looked at acts_as_nullobject plugin: http://martincik.com/?p=22 .
But it is giving me some errors.

Any help/suggestions are welcome.

bill walton wrote:

Hi Carlos,

On Sat, 2009-03-14 at 21:30 +0100, Carlos S. wrote:

My objective is to avoid nil object errors when no user is logged in -
i.e. when session[:user] is nil.

However, I still need to call some instance methods on this object.

Please suggest me how can I do this?

I’m thinkin’ I must be missin’ somethin’. Why can’t you use…

do_somethin’ unless session[:user].nil?

?

Best regards,
Bill

I have a roles table and I check authorization as:

def can_be_deleted_by?(user)
return false if user.role.nil?
valid_roles = %w{admin creator}
return false unless user.username == self.creuser ||
valid_roles.include?(user.role.name)
return true
end

One other thing I had to modify after using null obect was to check
user.role.nil? before calling user.role.name, which otherwise checks for
nil.name for anonymous user.

The delete action can be performed only by admin or the one who created
that topic/item. Hence I am using roles as well as check by
username(creator).

CS.

Bharat R. wrote:

Hello Carlos,
I am glad it worked for you. Access control is a fundamental
requirement along with authentication. Jim N.'s Bort which is
available on Github, packages Role Requirements written by Tim H.
along with Restful Authentication for creating a baseline
application. Tim has done an excellent job of implementing a
“minimal” authorization plugin. I am using Bort to develop my own
toolkit for creating applications.
I looked at the article that you list above. It is very well written
and very nice to learn from. The key thing missing from it is that it
fails to deal with Roles and instead deals directly with users. I
think a minimal layer of roles between users and controllers is a key
requirement.
I am not saying that Role Requirement is the only plugin that
addresses it. It is just that it packaged with Bort which has other
key plugins in addition to Restful Authentication and Role
Requirements. Gets the job done.
So instead of saying session[:current_user].nil? you may want to say
[:current_user].has_role?(‘anonymous’) for example. See the method
“has_role?” provided by Role Requirement? That is the key in my
opinion.
I may be wrong, but that is where I am going with this.
Hope this helps.
Bharat