我正在尝试设置一些类变量来存储Rails应用程序中的路径(但我认为这更像是一个红宝石问题)
基本上我的课看起来像这样
class Image < ActiveRecord::Base
@@path_to_folder = "app/assets"
@@images_folder = "upimages"
@@path_to_images = File.join(@@path_to_folder, @@images_folder)
end
但是当我尝试通过执行@@path_to_images
从我的控制器访问Image.path_to_images
时,我得到NoMethodError
当我尝试Image.class_eval( @@path_to_images )
时,我得到uninitialized class variable @@path_to_images in ImagesController
我已经四处搜寻了,我所看到的一切都说会有用,所以我对此感到很困惑
更重要的是,我尝试使用ruby控制台定义简单类,如此
class Bidule
@@foo = "foo"
Bar = "bar"
end
所以,我认为,我尝试了所有可能的方式(包括前2个)来访问它们但是我总是不会得到异常
答案 0 :(得分:24)
Rails为此功能提供了类级属性访问器
尝试
class Image < ActiveRecord::Base
cattr_accessor :path_to_folder
@@path_to_folder = "app/assets"
end
然后访问path_to_folder类变量只需使用
Image.path_to_folder
但人们总是建议避免类变量,因为它在继承中的行为。所以你可以使用像
这样的常量class Image < ActiveRecord::Base
PATH_TO_FOLDER = "app/assets"
end
然后你可以像
那样访问常量Image::PATH_TO_FOLDER
答案 1 :(得分:9)
虽然我一般不推荐它,但您可以通过将字符串传递给class_eval
来访问类变量,如下所示:
Image.class_eval('@@path_to_folder')
至少在Ruby的后期版本中。
但请注意,类变量与子类层次结构中最上层的类相关联。对于像这样的ActiveRecord子类,这意味着这些类变量确实存在于ActiveRecord::Base
的命名空间中。
答案 2 :(得分:3)
如果你不能或不想扩展课堂使用:
Image.class_variable_get(:@@path_to_images)
答案 3 :(得分:2)
类变量在Ruby应用程序中很少使用,因为它们有很多限制,并且往往会违反正确的面向对象设计。
几乎在每种情况下,类变量都可以用适当的常量,类方法或两者替换。
您的示例可能更好地描述为:
class Image < ActiveRecord::Base
PATH_TO_FOLDER = "app/assets"
IMAGES_FOLDER = "upimages"
PATH_TO_IMAGES = File.join(PATH_TO_FOLDER, IMAGES_FOLDER)
end
类变量对于所讨论的类是私有的,并且不会渗透到子类,并且难以从外部上下文访问。使用常量允许使用以下内容:
image_path = Image::PATH_TO_FOLDER
在某些情况下,类变量比替代方案更合理,但这些通常非常罕见。
答案 4 :(得分:2)
最好的方法是使用方法设置和获取值。以下是示例代码
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
答案 5 :(得分:1)
您可以通过将其包装在类方法中来实现,如下所示:
def self.path_to_images
@@path_to_images
end
但我应该提一下,你应该尽量避免在rails中使用类变量
答案 6 :(得分:1)
我会像这样修改它:
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
您在此处所做的是将类变量转换为方法,因此您现在可以使用.method名称调用进行访问。因为这是一个类变量,所以你只能在类本身上调用它,而不能在类的实例上调用它。 你得到了一个NoMethodError&#39;因为您使用不存在的方法调用类变量。上面的代码在你说的行上定义了这个方法:
def self.path_to_folder
@@path_to_folder
end
现在可以使用:
Image.path_to_folder