22

我正在尝试设置一些类变量来存储 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 种)来访问它们,但我总是不会遇到异常

4

7 回答 7

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
于 2012-09-25T20:52:04.873 回答
9

虽然我一般不会推荐它,但您可以通过将字符串传递给class_eval如下方式来访问类变量:

Image.class_eval('@@path_to_folder')

至少在更高版本的 Ruby 中。

但是请注意,类变量与子类层次结构中的最上层类相关联。对于像这样的 ActiveRecord 子类,这意味着这些类变量确实存在于ActiveRecord::Base.

于 2013-12-31T20:35:44.677 回答
3

如果您不能或不想扩展类使用:

Image.class_variable_get(:@@path_to_images)
于 2015-10-24T14:23:54.110 回答
3

最好的方法是使用方法设置和获取值。下面是一个示例代码

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
于 2016-03-25T19:11:17.750 回答
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

在某些情况下,类变量比替代变量更合理,但这种情况通常很少见。

于 2012-09-25T20:52:03.807 回答
1

您可以通过将其包装在类方法中来做到这一点,如下所示:

def self.path_to_images
  @@path_to_images
end

但我应该提一下,你应该尽量避免在 rails 中使用类变量

于 2015-02-11T16:08:27.743 回答
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”,因为您使用不存在的方法调用类变量。上面的代码在您所说的行中定义了此方法:

def self.path_to_folder
  @@path_to_folder
end

这现在可以工作了:

Image.path_to_folder
于 2016-02-03T07:20:33.703 回答