让我们试着去了解这整个过程中,控制器的动作定义的逐点
实例变量与渲染视图共享。
在你的情况我假设有一个new
动作像
def new
@movie = Movie.new
end
而且你,你已经创建了这样
= form_for @movie do |f|
形式现在相应的视图new.html.erb
,因为您知道@movie
对象,您在form_for
中传递的方法是在new
中定义的操作。大多数情况下,我们不会将任何参数传递给new
方法中的new
操作。当您加载表单时,表单字段为空,因为对象的属性(在您的案例中为@movie
)默认为空,因为我们只是初始化一个空对象(Movie.new
)。
让我们假设你的Movie
模型具有name
属性,尝试在你的new
动作现在做这个工作
def new
@movie = Movie.new(name: 'Hello World!')
end
时,你会加载新的动作,你会看到Hello World!
填入您的name
文本字段,因为您的@movie
对象使用此值进行初始化。
另外,请记住,在这种情况下,Rails Convention-Over-Configuration会自动生成表单URL,默认情况下它指向create
操作。当您提交form
时,会向创建操作发出请求。这带我到下一个点。
当我们提交所有填写表单值被送到其路径与表单URL匹配的操作(在你的情况URL指向create
行动)的形式
在create
动作您收到以模型属性(Movie
属性)作为关键字并填充信息作为其值的散列形式的参数。在create
行动的第一行是
@movie = Movie.new(movie_params)
这是代码的一个非常重要的线,试着去了解这一点。假设您的表单只有一个文本字段,即name
。现在movie_params
是看起来像这样
def movie_params
params.require(:movie).permit(:name)
end
现在的方法,该方法movie_params
会返回一个哈希像{ 'name' => 'Hello World!' }
,你现在通过这个哈希作为参数传递给Movie.new
方法。
所以现在分手的代码之后,您创建行动的第一线看起来像
@movie = Movie.new({ name: 'Hello World!' })
这意味着您的@movie
实例变量包含name
属性设置为Hello World!
Movie
类的一个对象。在这里,初始化后,如果你做@movie.name
它将返回Hello World!
。
现在,在第二行中,您正在调用@movie.save
,由于您的案例中的验证失败,因此返回false
,因为您已经在问题中提到过了。当它返回false
执行将转到else
部分。现在这带我到下一个点。
在控制器中调用render :action
(在你的情况render :new
)只呈现属于该动作的视图,并且不执行该动作码。
在你的情况下,你调用render :new
,所以你实际上在创建操作中渲染了new.html.erb
视图。换句话说,您只需使用new.html.erb
中的代码,而不是使用new
操作中的代码。这里,render :new
实际上并未调用新操作,它仍处于创建操作中,但呈现new.html.erb
视图。现在
,在new.html.erb
你已经创建了一个看起来像
= form_for @movie do |f|
现在,当我在我的第一点解释的形式,即在行动中声明的实例变量被渲染视图共享,在这case @movie
对象,您在create
中定义的操作由创建操作中呈现的new.html.erb
共享。在我们的示例中,在create
操作中,@movie
对象已使用参数(movie_params
)中收到的一些值进行了初始化,现在new.html.erb
在else
中呈现时,默认情况下在窗体中使用相同的@movie
对象。你明白了吗,你看到魔法了吗?
这就是Rails的工作原理,这就是为什么当我们遵循约定时它真棒! :)
这些博客会帮助你理解的代码更好,
http://blog.markusproject.org/?p=3313
这主旨是伟大的,
https://gist.github.com/jcasimir/1210155
最后但并非最不重要的,官方的Rails指南布局和渲染
http://guides.rubyonrails.org/v4.2/layouts_and_rendering.html
希望上面的例子能够解决您的疑惑,如果没有,请随时在下面的评论框中放下您的查询。 :)
这是一个坚实的回应,但海报也要求官方消息来源参考。补充一点,我会说这是值得的赏金! – toobulkeh
@toobulkeh添加官方消息来源和参考。 – RSB
@RSB - 这个回应帮助了我很大的时间。我不知道为了重新填充表单,我的create方法中的对象需要与新窗体中的相同。你在网上教授编程课吗? –