在 Ruby 1.9 中访问类变量的正确方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12590723/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the proper way to access class variables in Ruby 1.9?
提问by Geoffrey H
I'm trying to set some class variables to store paths in a Rails application (but I think this more a ruby question)
我正在尝试设置一些类变量来存储 Rails 应用程序中的路径(但我认为这更像是一个红宝石问题)
Basically my class looks like this
基本上我的班级看起来像这样
class Image < ActiveRecord::Base
@@path_to_folder = "app/assets"
@@images_folder = "upimages"
@@path_to_images = File.join(@@path_to_folder, @@images_folder)
end
But when I try to access @@path_to_imagesfrom my controller by doing Image.path_to_images, I get a NoMethodError
但是当我尝试@@path_to_images通过执行从我的控制器访问时Image.path_to_images,我得到一个 NoMethodError
When I try with Image.class_eval( @@path_to_images ), I get uninitialized class variable @@path_to_images in ImagesController
当我尝试使用时Image.class_eval( @@path_to_images ),我得到uninitialized class variable @@path_to_images in ImagesController
I've searched around and all I've seen says those would work, so I'm very confused about this
我四处搜索,我所看到的一切都说这些会起作用,所以我对此感到非常困惑
What's more, I tried defining simple classes with the ruby console like so
更重要的是,我尝试像这样用 ruby 控制台定义简单的类
class Bidule
@@foo = "foo"
Bar = "bar"
end
And so I tried, I think, all the ways possible (previous 2 included) to access them but no way I always get an exception raised
所以我尝试了,我想,所有可能的方式(包括前 2 种)来访问它们,但我没有办法总是引发异常
回答by Soundar Rathinasamy
Rails provides class level attribute accessor for this functionality
Rails 为此功能提供了类级别的属性访问器
Try
尝试
class Image < ActiveRecord::Base
cattr_accessor :path_to_folder
@@path_to_folder = "app/assets"
end
Then to access path_to_folder class variable just use
然后访问 path_to_folder 类变量只需使用
Image.path_to_folder
But people always suggest to avoid class variables due to its behavior in inheritance.So you can use constants like
但是人们总是建议避免类变量,因为它在继承中的行为。所以你可以使用像这样的常量
class Image < ActiveRecord::Base
PATH_TO_FOLDER = "app/assets"
end
Then you can access the constant like
然后你可以像这样访问常量
Image::PATH_TO_FOLDER
回答by Peter Alfvin
Although I wouldn't in general recommend it, you can access class variables by passing a string to class_evalas in:
虽然我一般不推荐它,但您可以通过将字符串传递给以下内容来访问类变量class_eval:
Image.class_eval('@@path_to_folder')
at least in later versions of Ruby.
至少在 Ruby 的更高版本中。
Note, however, that class variables are associated with the uppermost class in a subclassed hierarchy. In the case of ActiveRecord subclasses like this one, this means that these class variables really exist in the namespace of ActiveRecord::Base.
但是请注意,类变量与子类层次结构中最上层的类相关联。对于像这样的 ActiveRecord 子类,这意味着这些类变量确实存在于ActiveRecord::Base.
回答by rgtk
If you can't or don't want to extend class use:
如果您不能或不想扩展类使用:
Image.class_variable_get(:@@path_to_images)
回答by Sriram R
Best way is to set and get the value using methods. Below is a sample code
最好的方法是使用方法设置和获取值。下面是一个示例代码
class Planet
@@planets_count = 0
def initialize(name)
@name = name
@@planets_count += 1
end
def self.planets_count
@@planets_count
end
def self.add_planet
@@planets_count += 1
end
def add_planet_from_obj
@@planets_count += 1
end
end
Planet.new("uranus")
Plant.add_planet
obj = Planet.new("earth")
obj.add_planet_from_obj
回答by tadman
Class variables are rarely used in Ruby applications because they have a lot of limitations and also tend to run against the grain of proper Object-Oriented design.
类变量在 Ruby 应用程序中很少使用,因为它们有很多限制,而且往往与正确的面向对象设计的粒度背道而驰。
In nearly every case a class variable can be replaced with a proper constant, a class method, or both.
几乎在所有情况下,类变量都可以用适当的常量、类方法或两者替换。
Your example is probably better described as:
您的示例可能更好地描述为:
class Image < ActiveRecord::Base
PATH_TO_FOLDER = "app/assets"
IMAGES_FOLDER = "upimages"
PATH_TO_IMAGES = File.join(PATH_TO_FOLDER, IMAGES_FOLDER)
end
Class variables are private to the class in question and don't trickle down to sub-classes and are difficult to access from an external context. Using constants allows the use of things like:
类变量是相关类的私有变量,不会渗透到子类,并且难以从外部上下文访问。使用常量允许使用以下内容:
image_path = Image::PATH_TO_FOLDER
There are some circumstances under which a class variable is more reasonable than the alternative, but these are usually very rare.
在某些情况下,类变量比替代方案更合理,但这些通常非常罕见。
回答by Marco Prins
You can do that by wrapping it in a class method, like this:
您可以通过将其包装在类方法中来做到这一点,如下所示:
def self.path_to_images
@@path_to_images
end
but I should mention that you should try to avoid using class variables in rails
但我应该提到你应该尽量避免在 rails 中使用类变量
回答by GMarx
I would modify it like this:
我会像这样修改它:
class Image < ActiveRecord::Base
@@path_to_folder = "app/assets"
@@images_folder = "upimages"
@@path_to_images = File.join(@@path_to_folder, @@images_folder)
def initialize
end
...
def self.path_to_folder
@@path_to_folder
end
end
What you've done here is make the class variable into a method, so you can now access is using a .method name call. Since this is a class variable though, you can only call this on the class itself, not on the instance of a class. You are getting a 'NoMethodError' because you're calling the class variable using a method which has not exist. The code above defines this method on the lines where you say:
您在这里所做的是将类变量变成一个方法,因此您现在可以使用 .method 名称调用进行访问。由于这是一个类变量,您只能在类本身上调用它,而不能在类的实例上调用。您收到“NoMethodError”是因为您正在使用不存在的方法调用类变量。上面的代码在你说的行上定义了这个方法:
def self.path_to_folder
@@path_to_folder
end
This will now work:
这现在可以工作:
Image.path_to_folder

