Form_For新的相关模型

时间:2011-08-06 09:00:42

标签: ruby-on-rails forms associations belongs-to

所以在我的应用程序中,我有一个人员模型has_many描述。我现在需要在每个人的节目页面上添加一个表单,以便为该人添加新的描述。到目前为止,我有以下表格。但是,它没有将人员的ID传递给描述创建操作。

表格

<%= form_for @person.descriptions.new do |f| %>

    <fieldset class="input">
        <%= f.label :name %>
        <%= f.text_field :name %>
    </fieldset>

    <fieldset class="input">
        <%= f.label :description %>
        <%= f.text_area :description %>
    </fieldset>

    <fieldset class="button">
        <%= f.submit "Post" %>
    </fieldset>

<% end %>

参与通过

{"utf8"=>"✓",
 "authenticity_token"=>"OQY8Xcfm6wtWHXp9GjFfM4ICX79smPwyvfVcaDn+C2s=",
 "description"=>{"name"=>"Test",
 "description"=>"This is a test"},
 "commit"=>"Post"}

2 个答案:

答案 0 :(得分:6)

在人物控制器的show动作中创建描述对象,方法是将其构建到person对象而不是表单

所以在show动作中你会有

  #You probably have something like this already
  @person = Person.find(params[:id])
  #Now do this
  @description = @person.descriptions.build

然后将form_for更改为使用@description

这是一个不太理想的解决方案,因为您将发现此帖子返回到描述控制器,但您可以更改form_for中的网址

此外,依靠ID来查找控制器操作中的记录是错误的。有人可以轻松更改浏览器中的代码以在person对象上使用不同的ID。你应该仔细考虑这个问题。通常,您会发现只允许某人编辑自己的描述,因此在处理此类场景时,基于当前登录用户的current_user对象通常用于显示和编辑操作。

更新

忘记提及当表单回发给控制器时,您将以与上述相同的方式在保存之前为该人员构建描述。因此,您需要找到不再依赖ID的人才使用当前登录的用户。 希望有所帮助

++ UPDATE 2 ++

除此之外,我认为您确实需要使用form_for @person然后使用fields_for:description并将accepts_nested_attributes_for:description添加到您的Person模型中,这样您最终会得到类似的结果。

<%= form_for @person do |f| %>
  <%= f.fields_for :description do |desc_builder|
    <fieldset class="input">
        <%= desc_builder.label :name %>
        <%= desc_builder.text_field :name %>
    </fieldset>

    <fieldset class="input">
        <%= desc_builder.label :description %>
        <%= desc_builder.text_area :description %>
    </fieldset>
  <%end%>
  <fieldset class="button">
      <%= f.submit "Post" %>
  </fieldset>

<% end %>

在您的Person模型中添加以下内容

class Person < ActiveRecord::Base
#... Add this line
    accepts_nested_attributes_for :descriptions, :reject_if => proc { |attributes| attributes['name'].blank? && attributes['description'].blank? }
#... ---

然后在人员控制器的show动作中,只需构建如上所示的描述

  #You probably have something like this already
  @person = Person.find(params[:id])
  #Now do this
  @description = @person.descriptions.build # add an if @person.descriptions.empty? here if you only ever want one description per person.

上述代码将安排您的表单回发到人员控制器更新操作,该操作将自动创建描述记录。无需更改任何其他控制器代码。

这是因为form_for @person会安排网址转到更新操作,因为它已经是现有的人

fields_for将安排描述字段嵌套在更新操作获得的params散列中的person字段内。

最后,accepts_nested_attributes_for将根据需要自动创建或更新描述记录。 :reject_if =&gt; proc安排它,以便如果名称和描述都是空白的,则不会创建新记录。显然,您可以包含更多字段,更改条件或不拥有所有字段。无论什么适合您的要求。

希望这会让你感动。 如果您有需要,可以在此处找到有关accepts_nested_attributes的更多信息 http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

答案 1 :(得分:0)

确保在params散列中获取@person对象的id的最简单方法是将其添加为表单上的隐藏字段,例如:

hidden_field(:person, :id)

此外,您可能应该在人员控制器中创建模板描述,而不是在视图中创建新描述。