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

时间:2014-01-23 14:38:51

标签: ruby-on-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”的价值。那么这里发生了什么?它们不是在同一个类中定义的吗?

5 个答案:

答案 0 :(得分:46)

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

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

当您尝试访问@insworld中的#index时,Ruby会在A对象(意为A.new)中搜索实例变量,因为#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

答案 1 :(得分:6)

当您声明@instworld时,您在BooksController类中(即self将返回BooksController。在ruby中,奇怪的是类也是对象(类{{1}的实例因此,您实际上为类Class的此特定实例声明了实例变量@instworld,而不是Class的实例。

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

BooksController

答案 2 :(得分:3)

在方法之外声明实例变量时,可能无法获得所需的结果。它是一个实例变量,是的,但它属于类本身(它是类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的原因:该范围内的变量不存在。

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

答案 3 :(得分:2)

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

答案 4 :(得分:1)

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

BooksController.instance_variable_get(:'@insworld')

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