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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21311215/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 23:16:25  来源:igfitidea点击:

instance and class variables in rails controller

ruby-on-railsruby

提问by Finks

I'm new to rails and ruby. I was studying the concept of class and instance variables. I understood the difference but when I tried it out using the controller in rails it got me confused. What I did is I declared a class and instance variables outside the class methods:

我是 Rails 和 ruby​​ 的新手。我正在研究类和实例变量的概念。我理解其中的区别,但是当我尝试使用 Rails 中的控制器时,它让我感到困惑。我所做的是在类方法之外声明了一个类和实例变量:

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

I was under the impression that @insworld has the value of "my hobby", but when I tried to check the value of @insworld when I was inside the index method, @insworld was returning a nil value. @@world has the value of "Hello World". So what happened here? Aren't they defined in the same class?

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

回答by Agis

Classes are also objects in Ruby, so they can have their own instance variables which are called class instance variables.

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

  • @@worldis a class variable
  • @insworldis a class instance variable
  • #indexis an instance method
  • @@world是一个类变量
  • @insworld是一个类实例变量
  • #index是一个实例方法

When you try to access @insworldin #index, Ruby searches for the instance variable in the Aobject (meaning A.new) because #indexis an instance method.

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

But you defined @insworldas a class instance variablewhich means it is defined in the class object itself (meaning A).

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

The following code demonstrates:

以下代码演示:

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

Keep in mind that all instance variables return nilif they don't exist.

请记住,nil如果所有实例变量不存在,它们都会返回。

回答by BroiSatse

When you declare @instworldyou are inside BooksController class (i.e. selfwill return BooksController. Weird thing in ruby is that classes are also objects (the are instances of class Class) hence you in fact declares instance variable @instworldfor this particular instance of class Classm not for instance of BooksController.

当你声明@instworld你在 BooksController 类中时(即self会返回。Ruby 中BooksController奇怪的事情是类也是对象(类的实例Class)因此你实际上@instworld为类Classm 的这个特定实例声明了实例变量,而不是实例BooksController

You can check it really easily by declaring class method:

你可以通过声明类方法很容易地检查它:

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'

回答by Sergio Tulentsev

When you declare instance variable outside of method, you might not get the result you want. It is an instance variable, yes, but it belongs to the class itself(which is an instance of class Class).

当你在方法之外声明实例变量时,你可能得不到你想要的结果。它是一个实例变量,是的,但它属于类本身(它是 class 的实例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 

If you try to get value of uninitialized ivar, it will evaluate to nil. That's why you got nilin your experiments: the variable doesn't exist at that scope.

如果您尝试获取未初始化的 ivar 的值,它将评估为nil。这就是您nil参与实验的原因:该变量不存在于该范围内。

To get instance-level variables, set them in methods/actions.

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

回答by lfender6445

Declaring the @insworld within the class but not in the constructor or any of the instance methods sets @insworld scoped to the instance of the class itself.

在类中声明 @insworld 而不是在构造函数或任何实例方法中声明将 @insworld 范围设置为类本身的实例。

BooksController.instance_variable_get(:'@insworld')

If you need the access to variable inside of your index method, consider defining it within the method instead.

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

回答by Ahmad Hussain

The scope of Instance variables are from action to view they initiate when any action occurs and destroy when action ends.

Instance 变量的作用域是从 action 来查看它们在任何 action 发生时启动,在 action 结束时销毁。