ruby-on-rails - ejemplos - ruby on rails que es



¿Cuál es la forma correcta de acceder a las variables de clase en Ruby 1.9? (5)

Aunque en general no lo recomendaría, puede acceder a las variables de clase pasando una cadena a class_eval como en:

Image.class_eval('@@path_to_folder')

Al menos en versiones posteriores de Ruby.

Sin embargo, tenga en cuenta que las variables de clase están asociadas con la clase más alta en una jerarquía subclasificada. En el caso de subclases de ActiveRecord como esta, esto significa que estas variables de clase realmente existen en el espacio de nombres de ActiveRecord::Base .

Estoy tratando de establecer algunas variables de clase para almacenar rutas en una aplicación de Rails (pero creo que esto es más una pregunta de ruby)

Básicamente mi clase se ve así

class Image < ActiveRecord::Base

   @@path_to_folder = "app/assets"
   @@images_folder = "upimages"
   @@path_to_images = File.join(@@path_to_folder, @@images_folder)

end

Pero cuando intento acceder a @@path_to_images desde mi controlador haciendo Image.path_to_images , obtengo un NoMethodError

Cuando intento con Image.class_eval( @@path_to_images ) , obtengo uninitialized class variable @@path_to_images in ImagesController

He buscado alrededor y todo lo que he visto dice que funcionaría, así que estoy muy confundido acerca de esto

Es más, traté de definir clases simples con la consola ruby ​​así.

 class Bidule
     @@foo = "foo"
     Bar = "bar"
 end

Y así intenté, creo, todas las formas posibles (incluidas las 2 anteriores) para acceder a ellas, pero de ninguna manera siempre obtengo una excepción.


Answer #1

La mejor manera es establecer y obtener el valor utilizando métodos. A continuación se muestra un código de ejemplo

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

Answer #2

Puedes hacerlo envolviéndolo en un método de clase, como este:

def self.path_to_images
  @@path_to_images
end

pero debo mencionar que debe tratar de evitar el uso de variables de clase en los carriles


Answer #3

Rails proporciona acceso de atributo de nivel de clase para esta funcionalidad

Tratar

class Image < ActiveRecord::Base
  cattr_accessor :path_to_folder
  @@path_to_folder = "app/assets"
end

Luego, para acceder a la variable de clase path_to_folder solo use

Image.path_to_folder

Pero la gente siempre sugiere evitar las variables de clase debido a su comportamiento en la herencia. Por lo tanto, puede usar constantes como

class Image < ActiveRecord::Base
   PATH_TO_FOLDER = "app/assets"
end

Entonces puedes acceder a la constante como

Image::PATH_TO_FOLDER

Answer #4

Yo lo modificaría así:

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

Lo que has hecho aquí es convertir la variable de clase en un método, por lo que ahora puedes acceder usando una llamada de nombre de método. Sin embargo, dado que esta es una variable de clase, solo puede llamar a esto en la clase en sí, no en la instancia de una clase. Obtendrá un 'NoMethodError' porque está llamando a la variable de clase utilizando un método que no existe. El código anterior define este método en las líneas donde dices:

def self.path_to_folder
  @@path_to_folder
end

Esto ahora funcionará:

Image.path_to_folder




ruby