form_for如何在Ruby on Rails中运行

时间:2013-12-10 16:57:17

标签: ruby-on-rails rails-activerecord params form-for form-helpers

我是新手。我已阅读API文档。但仍然不明白form_for是如何工作的。

首先,从Ruby on Rails教程,关注按钮的表单:

<%= form_for(current_user.relationships.build(followed_id: @user.id)) do |f| %>
  <div><%= f.hidden_field :followed_id %></div>
  <%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>

我理解current_user.relationships.build(followed_id: @user.id)表示新记录。但是为什么我们不能只提交并触发控制器来保存没有hidden_​​field的记录?为什么我们仍然需要将follow_id发布到控制器?

其次,在hidden_​​field中,:followed_id的含义是什么?我相信这是一个符号,即它只等于“followed_id”而不是id的变量。如果那只是输入字段的名称,那么它的值是什么?

第三,form_for如何知道应该将提交内容发送到哪里? form_for将发布哪个控制器和操作?

第四,params如何与form_for合作?在此跟随按钮的情况下,params[:relationship][:followed_id]将在控制器中返回@user.id。它如何知道第一个哈希属性是:relationship?我们既未提及form_for :relationship也未提及form_for @relationship

我知道这些问题可能非常愚蠢,但我真的被卡住了。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:3)

我没有做那个教程,所以请记住我,如果我不直接回答你的问题。

看看rails guide about form helpers,它会详细解释你的问题,可能会以比我更清晰的方式解释。

form_for(path/to/your/controller/action)是一个帮助方法,用于创建具有POST或GET请求的url路径的HTML表单元素。帮助程序根据您在控制器操作中要求执行的操作,知道它应该是新记录还是更新记录。

例如 在您的控制器中

def new
  @my_instance_variable = Myobject.new
end

在您的视图中new.html.erb

<%= form_for @my_instance_variable do |f| %>
...
<% end %>

在你的情况下,逻辑直接写在帮助器中,你也可以直接写

<%= form_for Myobject.new %>

两者都会产生以下html

<form action="/myobjects/new" method="post">
# in this case rails knows its a `POST` request because the route new action
# is by default a POST request. You can check these routes and their request 
# by using `rake routes` in terminal.

然后hidden_field是另一个包含值的助手,在您的情况下,@user.id将作为参数传递,然后保存为给定对象的创建或更新操作。它不会在隐藏字段标记中添加值的原因是因为您已经拥有一个知道用户ID的模型关联,因为表单链接使用构建方法和用户ID。

最后一部分您需要了解form_for链接逻辑

current_user.relationships 
# implies the association of the current_user has many relationships 
current_user.relationships.build 
# .build is a method to populate a new object that can be save as a new record
# means you will create a new relationship record by populating the user_id 
# column with the current_user.id and the followed_id with the target @user.id

答案 1 :(得分:1)

在阅读了The Rails 4 Way这本书之后,我现在更了解form_for。

  

11.9.1.5显示现有值。   如果您正在编辑Person的现有实例,则该对象的属性值将被填充   形式。

这样,当我们使用current_user.relationships.build(followed_id: @user.id)构建关系时,将创建关系实例并获取属性followed_id。因此,我们实际上是通过表单编辑关系,而不是“创建”关系。

然后Rails将知道您正在编辑并将现有属性“followed_id”加载到该字段。因此,我们不需要像使用f.hidden_field :followed_id, value: @user.id那样为字段赋值。

我们必须使用字段将followed_id传递给params的原因是因为HTTP服务器是无状态的,它不记得你正在创建与哪个用户的关系。

编写form_for current_user.relationships.build(followed_id: @user.id)而不是标准form_for @relationship的一个好处是我们不需要在控制器中编写“if-condition”,如下所示:

unless current_user.nil?
  if current_user.following?(@user)
    @relationship=current_user.relationships.find_by(followed_id: @user.id)
  else
    @relationship=current_user.relationships.new
  end
end

params将被发送到属于实例模型的控制器。 “post”方法会去动作创建,“删除”会去破坏,“补丁”会去更新等等。

params将是一个哈希,其中包含另一个哈希,如{instace_name:{field_1:value1,field_2:value2}}或完整参数,如下所示

   Parameters: {"utf8"=>"✓",
     "authenticity_token"=>"afl+6u3J/2meoHtve69q+tD9gPc3/QUsHCqPh85Z4WU=",
     "person"=>{"first_name"=>"William", "last_name"=>"Smith"},
     "commit"=>"Create"}