Reputation: 4044
I want some short way and less duplicate way of creating accessor methods for class variables. Here, I see that there is too much same looking code i.e. methods. Is there any short way like we have for our instance variables. @foobar
which will have attr_accessor :foobar
class User
@@user_id = 0
@@user_long = 0
@@user_lat = 0
# User ID
def self.user_id=(id)
@@user_id = id
end
def self.user_id
@@user_id
end
# Longitude
def self.user_long=(longitude)
@@user_long = longitude
end
def self.user_long
@@user_long
end
# Latitude
def self.user_lat=(latitude)
@@user_lat = latitude
end
def self.user_lat
@@user_lat
end
end
User.user_id = 23423423
User.user_long = -342.34
User.user_lat = 343.3
puts User.user_lat
puts User.user_lat
puts User.user_id
Upvotes: 2
Views: 480
Reputation: 369614
In general, it is very much preferred to use instance variables instead of class variables, because of the somewhat strange sharing semantics of class variables:
class User
class << self
attr_accessor :user_id, :user_long, :user_lat
end
self.user_id = 0
self.user_long = 0
self.user_lat = 0
end
User.user_id #=> 0
User.user_long #=> 0
User.user_lat #=> 0
User.user_id = 23423423
User.user_long = -342.34
User.user_lat = 343.3
User.user_id #=> 23423423
User.user_long #=> -342.34
User.user_lat #=> 343.3
But if you absolutely must use class variables, you can simply write your own methods for generating setters and getters. It's not like there's anything magical about Module#attr_accessor
, it's a method just like any other method:
class Module
def cvar_reader(*names)
names.each do |name|
define_singleton_method(name) { class_variable_get(:"@@#{name}") }
end
end
def cvar_writer(*names)
names.each do |name|
define_singleton_method(:"#{name}=") {|value| class_variable_set(:"@@#{name}", value) }
end
end
def cvar_accessor(*names)
cvar_reader *names
cvar_writer *names
end
end
class User
cvar_accessor :user_id, :user_long, :user_lat
self.user_id = 0
self.user_long = 0
self.user_lat = 0
end
User.user_id #=> 0
User.user_long #=> 0
User.user_lat #=> 0
User.user_id = 23423423
User.user_long = -342.34
User.user_lat = 343.3
User.user_id #=> 23423423
User.user_long #=> -342.34
User.user_lat #=> 343.3
However, it seems like a strange design, regardless of whether you use class instance variables or class variables. Why have a class at all, when you cannot have more than one user in your system anyway? Why not just use an object?
class << (User = Object.new)
attr_accessor :user_id, :user_long, :user_lat
end
User.user_id = 0
User.user_long = 0
User.user_lat = 0
User.user_id #=> 0
User.user_long #=> 0
User.user_lat #=> 0
User.user_id = 23423423
User.user_long = -342.34
User.user_lat = 343.3
User.user_id #=> 23423423
User.user_long #=> -342.34
User.user_lat #=> 343.3
Upvotes: 2
Reputation: 31
What you might be looking for is something like this,
class User
class << self
attr_accessor :user_id
end
end
Which will create instance variables on the class's metaclass, rather than class variables. This might give you what you need but I do suggest reading and understanding Ruby's object model.
Upvotes: 1
Reputation: 5773
You can do it like this:
class User
@user_id = 0
@user_long = 0
@user_lat = 0
class << self
attr_accessor :user_id, :user_long, :user_lat
end
end
Upvotes: 4