Rails 如何知道取哪个变量

How does Rails know which variable to take

Rails 的初学者,请参考 mackenziechild.me 的教程。例如,我创建了一个有很多方法的 PostController。然而,令我困惑的是他们似乎有相同的变量@post。在这种情况下,程序如何真正知道它需要获取哪个正确的变量?当应用程序是 运行 时,他们不会感到困惑吗?

class PostsController < ApplicationController
    def index
        @posts = Post.all.order('created_at DESC')
    end

    def new
        @post = Post.new        
    end 

    def create
        @post = Post.new(post_params)

        if @post.save
            redirect_to @post
        else
            render 'new'
        end     
    end

    def show
        @post = Post.find(params[:id])
    end 

    private

    def post_params
        params.require(:post).permit(:title, :body)
    end     
end

Ikanyu,@post变量是一个实例变量,即它的范围仅限于定义它的方法。所以@post变量定义在新方法中定义的是不同的显示,因此在视图中访问这些不同的变量没有任何问题。

有关如何将这些变量传递到视图中的更多信息,请参阅此 link:

How are Rails instance variables passed to views?

在 rails 中,像 index, new, show etc 这样的每个操作都是 get 方法,在相应的文件夹中都有相应的视图,这些文件夹被命名为 controller 名称。

所以当一个动作被调用时,他们的特定视图就会被调用。

例如:-

def index
    @posts = Post.all.order('created_at DESC')
end

它们应该是文件夹 app/views/posts/ 中的 index.html.erb 视图,并且在该视图中可以访问实例变量 @posts

在这一行Post.all.order('created_at DESC')Post模型查询数据库并从table中获取所有记录作为posts并且还按降序对记录进行排序created _at 列。

Post模型继承自ActiveRecord::Base,因此它可以映射数据库中的poststable。

def show
    @post = Post.find(params[:id])
end 

在上面的show方法中,它只查询id在params[:id].

中的一条记录

实例变量可在视图中访问,因此在 @post = Post.find(params[:id])@post 可以在其对应的视图中使用 show.html.erbapp/views/posts/

I have created a PostController with lots of method. However, what confuses me is they seem to have the same variable @post. In this case, how do the program actually knows which correct variable it needs to get? Don't they will get confused when the application is running?

当您的浏览器请求页面时,请求将被路由到您定义的方法之一。该方法执行,并且该方法设置@post 的值。将响应发送到浏览器后,rails 会销毁所有已创建的变量。

but we have Post.new, Post.new(post_params), Post.find(params[:id]) I came from a Java background. so this is quite confusing me. They area all being assigned to the same @post

在Java中,你当然可以将三个东西赋给同一个变量:

int x = 1;
x = 2;
x = 3;
System.out.println(x);  #=>3

并且,如果您有一个名为 Post 的 class,您还可以将三个不同的 Post 对象分配给同一个变量:

    Post p = new Post("hello");
    System.out.println(p.getText());
    p = new Post("world");
    System.out.println(p.getText());
    p = new Post("goodbye");
    System.out.println(p.getText());  #=>goodbye

每个:Post.newPost.new(post_params)Post.find(params[:id]) returns 一个 Post 对象;此外,它们被分配给同一个变量,所以为什么您对来自 Java 背景 的 感到困惑?

但是,您还应该注意 Rails 在底层使用了一种称为 ruby 的语言,并且在 ruby 中变量没有类型,它们不必是宣布。因此,在 ruby 中,您可以将不同类型分配给同一变量:

some_var = "hello"  #String
some_var = 10  #Integer
some_var = [1, 2, 3]  #Array
some_var = {a: 1, b: 2}  #Hash

如果你说你被这样的事情弄糊涂了,那就更有意义了。然而,即便如此,又有什么可困惑的呢?有两个简单的规则:

  1. 变量名没有类型。
  2. 因此,您不必声明变量。

早些时候,我是这样说的:

When your browser requests a page, the request is routed to ONE of the methods you defined. That method executes, and that method sets the value of @post. After the response is sent to the browser, rails destroys all the variables that were created.

在内部,工作方式是:

  1. 当 url 被路由到某个控制器时,rails 创建该控制器的一个实例 class:

    obj = PostsController.new

  2. Rails使用控制器实例调用控制器中定义的方法之一class(方法由路由决定):

    obj.show

(就像在 Java 中一样,当您将方法名称作为字符串时,有多种方法可以调用方法——在 ruby 中更容易。)

  1. 方法执行。

  2. 响应发送到浏览器后,rails销毁控制器实例:

    obj = nil