Ruby on rails RubyonRails中的变量语法

Ruby on rails RubyonRails中的变量语法,ruby-on-rails,ruby,Ruby On Rails,Ruby,我正在复习RubyonRails教程,但仍然对语法有点困惑 class PostController < ApplicationController def index @posts = Post.all end def create @post = Post.new(post_params) end private def post_params params.require(:post).pe

我正在复习RubyonRails教程,但仍然对语法有点困惑

class PostController < ApplicationController
    def index
        @posts = Post.all
    end

    def create
        @post = Post.new(post_params)
    end 

private
    def post_params
        params.require(:post).permit(:title, :body)
    end
end
class PostController
我来自javascript背景


据我所知,带有
@
@posts
是从models文件夹中的
Post
类实例化的变量。但
:post
的确切含义是什么,
参数从何而来,它是什么?

@posts
是一个实例变量,可以将其视为对象的私有字段或私有属性


:post
是一个符号,类似于常量字符串,在本例中用作散列键(在
params[:id]
中)或指示允许哪些参数的键(在
params.require(:post).permit(:title,:body)

这里有两个东西。一个是实例变量,或者说
@
-前缀变量。这些变量是对象实例的本地变量。也就是说
@posts
可以被在同一对象实例上调用的任何方法访问。这些变量不会在对象实例之间共享

如果您熟悉JavaScript,这很像
this.posts
,其中
this
部分表示“此对象的本地”,而不是“某个名为
posts
的变量”

Rails使用这些变量作为从控制器到视图共享数据的一种方式。您定义的任何实例变量都会传播到视图实例,在视图实例中可以使用它们。这是Rails特有的行为

:post
是一个符号,或一个内部化的字符串。从概念上讲,符号只是一个表示特定名称的常量。
:post
的每个实例都引用同一个对象,因此这意味着它们在存储方面非常便宜,比较也很简单

比较两个字符串时需要做更多的工作。
“post”==“post”
:post==:post
需要进行更多的计算。您会看到Ruby哈希结构中使用了很多符号键,它们通常用于表示方法调用或类名,如
所属的:model\u type
等等

把它们想象成“单态字符串”

Ruby编程语言更奇特的一点是它对符号的依赖程度有多大,符号很容易与字符串混淆,因为许多方法要么采用要么不采用,而另一些方法则非常特殊


当你在概念上习惯了它们时,它们确实很方便,但它不是你在其他语言中看到的,比如C++、Python、JavaScript或者你有什么。<> >代码> @ POST <代码>是一个实例变量。实例变量是一个生存的变量,只要一个类的实例存在,正常变量的范围就大得多。让我举个例子:

class Counter
  def initialize(start = 0)
    @counter = start
  end

  def increment
    @counter += 1
  end
end

counter = Counter.new
counter.increment #=> 1
counter.increment #=> 2
:foo.object_id #=> 1686748
:foo.object_id #=> 1686748
如果您想用计数器替换
@计数器
,您将得到:

class Counter
  def initialize(start = 0)
    counter = start
  end

  def increment
    counter += 1
  end
end

counter = Counter.new
counter.increment # NoMethodError (undefined method `+' for nil:NilClass)
不同之处在于
计数器
在构造函数中设置,但仅在该方法中可用。因此,当调用
增量
时,使用的
计数器
是一个尚未初始化的变量

您可以阅读有关实例变量的更多信息


现在来看问题的第二部分“什么是
:post
的:意思”.Ruby有您应该从JavaScript中了解的字符串。Ruby也有符号,它们类似于字符串,但是全局单例对象。它们比字符串具有更快的查找和比较时间,但一旦使用符号,它将保持加载在符号寄存器中(
symbol.all_符号
)在整个程序期间。它们主要用作哈希(其他语言中的dict)的方法和标签选项

为了向您展示我对singleton对象的意思,让我提供一个示例:

class Counter
  def initialize(start = 0)
    @counter = start
  end

  def increment
    @counter += 1
  end
end

counter = Counter.new
counter.increment #=> 1
counter.increment #=> 2
:foo.object_id #=> 1686748
:foo.object_id #=> 1686748
如您所见,即使我们似乎创建了两个实例,对象仍然保持不变。第一次使用
:foo
时,它被创建并添加到寄存器中,第二次Ruby检测到
:foo
已经在寄存器中并返回该符号

要显示差异,让met演示相同的,但使用字符串:

'foo'.object_id #=> 24742300
'foo'.object_id #=> 26029360
正如您所看到的,两个字符串都有不同的对象id(尽管包含相同的内容),这使它们成为不同的对象

您可以阅读更多有关符号的信息


问题的最后一部分“params
从何而来?它是什么?”,我们必须看看Ruby on Rails框架。您的
PostController
继承自
ApplicationController
,后者又继承自
ActionController::Base
,后者为您提供了一些帮助方法。
params
就是这些方法之一

在Ruby中,括号在调用方法时是可选的,在调用不带参数的方法时通常是不使用的。通过运行代码,这里就是这样:

params.require(:post).permit(:title, :body)
首先调用该方法。此方法继承自
ActionController::Base
,并返回web请求的参数。然后调用返回的参数,如果不存在异常,将获取符号/标签下的值
:post
(这是
require
行为的一部分)。然后使用参数
:title
:body
调用返回的值,这允许使用这些标签/符号及其值

总结起来,以下几行将所有内容联系在一起:

@post = Post.new(post_params)
表示将post的新实例分配给实例变量
@post