rails控制器中的实例和类变量

我是铁杆和ruby的新手。 我正在研究类和实例变量的概念。 我理解了差异但是当我在轨道中使用控制器尝试它时让我感到困惑。 我做的是我在类方法之外声明了一个类和实例变量:

class BooksController < ApplicationController # GET /books # GET /books.json @@world = "Hello World" @insworld = "my hobby" def index @books = Book.all binding.pry respond_to do |format| format.html # index.html.erb format.json { render json: @books } end end end 

我的印象是@insworld具有“我的爱好”的价值,但是当我在index method尝试检查@insworld的值时,@ insworld返回了一个零值。 @@ world具有“Hello World”的值。 那么这里发生了什么? 它们不是在同一个类中定义的吗?

类也是Ruby中的对象,因此它们可以拥有自己的实例变量,这些变量称为类实例变量

  • @@world是一个类变量
  • @insworld是一个类实例变量
  • #index是一个实例方法

当您尝试在@insworld中访问@insworld时,Ruby会在A对象中搜索实例变量(意思是#index ),因为#index是一个实例方法。

但是您将@insworld定义为类实例变量 ,这意味着它在类对象本身中定义(意味着A )。

以下代码演示:

 class Hi @@a = 1 # class variable @b = 2 # class instance variable def initialize @c = 3 # instance variable end def test # instance method, works on objects of class Hi puts @@a # => 1 puts @b # => nil, there is no instance variable @b puts @c # => 3 # we defined this instance variable in the initializer end end Hi.class_variables # => @@a Hi.instance_variables # => @b Hi.new.instance_variables # => @c # Hi is an object of class Class # Hi.new is an object of class Hi 

请记住,如果不存在,则所有实例变量都返回nil

当您声明@instworld你在BooksController类中(即self将返回BooksController 。在ruby中奇怪的是类也是对象(类Class实例)因此你事实上为这个特定的类实例声明了实例变量@instworld Class m不是BooksController

您可以通过声明类方法来轻松检查它:

 class A # self here returns class A @variable = 'class instance variable' @@variable = 'class variable' def initalize # self here returns the instance @variable = 'instance variable' end def self.test_me # self here returns class A @variable end def test_me # self returns the instance @variable end #class variable is accessible by both class and instance def test_me2 @@variable end def self.test_me2 @@variable end end A.test_me #=> 'class instance variable' A.new.test_me #=> 'instance variable' A.test_me2 #=> 'class variable' A.new.test_me2 #=> 'class variable' 

实例变量的范围是从操作到查看它们在任何操作发生时启动,并在操作结束时销毁。

在方法之外声明实例变量时,可能无法获得所需的结果。 它是一个实例变量,是的,但它属于类本身 (它是类Class一个实例)。

 class Foo @myvar = "class-level" def initialize @myvar = 'instance-level' end end f = Foo.new f.class.instance_variable_get(:@myvar) # => "class-level" f.instance_variable_get(:@myvar) # => "instance-level" f.instance_variable_get(:@myvar2) # => nil 

如果你试图获得未初始化的ivar的价值,它将评估nil 。 这就是你在实验中得到nil的原因:变量在那个范围内不存在。

要获取实例级变量,请在方法/操作中设置它们。

在类中声明@insworld而不在构造函数或任何实例方法中声明@insworld作用于类本身的实例。

 BooksController.instance_variable_get(:'@insworld') 

如果需要访问索引方法中的变量,请考虑在方法中定义它。