我有一个'创造' Rails中的action方法和:
def create
@movie = Movie.new(movie_params)
if @movie.save
redirect_to @movie, notice: "Movie successfully created"
else
render :new
end
end
现在,我对Movie
模型进行了一些验证。如果这些验证失败,@movie.save
返回false,我只需调用new
模板(不触及new
操作,因为render :new
与render template: 'new'
相同}。
我不明白当Rails再次呈现new
视图时,Rails如何保留我已输入的表单数据。在幕后发生了什么让它能够做到这一点?
答案 0 :(得分:13)
让我们尝试逐点理解整个过程
控制器操作中定义的实例变量与渲染视图共享。
在你的情况下,我假设有new
动作类似
def new
@movie = Movie.new
end
你有一个相应的视图new.html.erb
,你已经创建了一个像这样的表单
= form_for @movie do |f|
现在,您知道@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
时,会对创建操作发出请求。这让我想到了下一点。
当我们提交表单时,所有填写的表单值都会发送到路径与表单网址匹配的操作(在您的情况下网址指向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
实例变量包含Movie
类的对象,name
属性设置为Hello World!
。在此处,初始化后,如果您执行@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|
正如我在第一点所解释的那样,在操作中声明的实例变量由呈现的视图共享,在这种情况下,您在@movie
操作中定义的create
对象是共享的通过创建操作中呈现的new.html.erb
。在我们的示例中,在create
操作中,@movie
对象已使用参数(movie_params
)中收到的一些值进行初始化,现在new.html.erb
在{else
中呈现1}},默认情况下在表单中使用相同的@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
希望以上示例清除您的疑虑,如果没有,请随时在下面的评论框中删除您的查询。 :)
答案 1 :(得分:1)
form_for
助手从@movie
变量中获取数据。在create
操作表单中,数据会分配给@movie
变量。当您致电render :new
时,form_for会从@movie
变量中获取列数据。
答案 2 :(得分:1)
我不确定你想要去多深,但基本上当你对create方法发布POST时,数据会传递到params
,params
只是一个key:值对,其中键和值是字符串,但rails具有特殊的语法和方法,可用于转换为哈希值。 params
数据传递Movie
数据以进行处理,结果存储在@movie
中。呈现表单时,@movie
日期将传递回表单 - 该数据用于重新填充表单。
我建议您使用blog post和the rails guide进一步阅读。
答案 3 :(得分:0)
提交表单时。您可以调用create方法,其中movie_params
的所有值都在@movie
中初始化。现在由于任何原因代码中断,您为相同的对象(render new
)调用@movie
。因此形式提出了价值观。
在整个过程中意味着您的@movie
对象仍然存在。