[英]What is the proper way to access virtual atributes in Ruby on Rails?
[英]What is the proper way to access class variables in Ruby 1.9?
我正在嘗試設置一些類變量來存儲Rails應用程序中的路徑(但我認為這更像是一個紅寶石問題)
基本上我的班級看起來像這樣
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_to_images
從我的控制器訪問@@path_to_images
,我得到一個NoMethodError
當我嘗試使用Image.class_eval( @@path_to_images )
,我uninitialized class variable @@path_to_images in ImagesController
獲得了uninitialized class variable @@path_to_images in ImagesController
我已經四處尋找,我所看到的一切都說會有用,所以我對此非常困惑
更重要的是,我嘗試使用ruby控制台來定義簡單的類
class Bidule
@@foo = "foo"
Bar = "bar"
end
因此,我認為,我嘗試了所有可能的方式(包括前2個)來訪問它們,但我總是得到一個例外
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
雖然我一般不會推薦它,但您可以通過將字符串傳遞給class_eval
來訪問類變量,如下所示:
Image.class_eval('@@path_to_folder')
至少在Ruby的更高版本中。
但請注意,類變量與子類層次結構中最高級的類相關聯。 對於像這樣的ActiveRecord子類,這意味着這些類變量確實存在於ActiveRecord::Base
的命名空間中。
如果您不能或不想擴展類使用:
Image.class_variable_get(:@@path_to_images)
類變量在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
在某些情況下,類變量比替代方案更合理,但這些通常非常罕見。
最好的方法是使用方法設置和獲取值。 下面是一個示例代碼
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
您可以通過將其包裝在類方法中來實現,如下所示:
def self.path_to_images
@@path_to_images
end
但我應該提一下,你應該盡量避免在rails中使用類變量
我會像這樣修改它:
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.