新的form_for模式相关 [英] Form_For New Related Model

查看:102
本文介绍了新的form_for模式相关的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此​​,在我的应用我有一个Person模型,的has_many 描述。我现在需要每个人的节目页面上的形式来添加一个新的描述的那个人。到目前为止,我有以下形式。但它是不及格的人的ID来描述创建行动。

表格

 <%= @的form_for做person.descriptions.new | F | %GT;    <字段集类=输入>
        <%= f.label:名称%>
        <%= f.text_field:名称%>
    < /字段集>    <字段集类=输入>
        <%= f.label:描述%GT;
        <%= f.text_area:描述%GT;
    < /字段集>    <字段集类=按钮>
        <%= f.submit邮报%GT;
    < /字段集><%结束%GT;

PARAMS传递

  {UTF8=>中✓
 authenticity_token=>中OQY8Xcfm6wtWHXp9GjFfM4ICX79smPwyvfVcaDn + C2S =,
 说明=> {名= GT;测试,
 说明=>中这是一个测试},
 提交=>中邮}


解决方案

通过构建它的人,而不是物的形式创建展示行动者控制器描述对象

所以在表演的动作你就必须

 #你可能有这样的事情已经
  @person = Person.find的(PARAMS [:ID])
  #Now做到这一点
  @description = @ p​​erson.descriptions.build

然后改变你的form_for使用@description

这是不是理想的解决方案少了,你会发现这回发的描述控制器,但你可以在的form_for更改URL

此外,依靠的ID找到控制器动作的记录是错的..有人可以很容易地改变code在浏览器的人对象使用不同的ID。你应该非常仔细地考虑这个。很多时候你会发现,一个人只允许编辑自己的描述,以便根据当前登录用户的一个CURRENT_USER对象在节目用这种场景打交道时经常使用和编辑的操作。

更新

忘了提,当窗体回发到控制器按照上述同样的方式在保存之前建立在对人的描述。所以,你需要找到这又不应依赖的ID只使用当前登录的用户的人。
希望帮助

++更新2 +

除了上述以外,我认为你确实需要的form_for @person使用,然后使用fields_for:描述和accepts_nested_attributes_for添加:描述你的人的模型,所以你会像这样结束了。

 <%=的form_for @person做| F | %GT;
  <%= f.fields_for:说明做| desc_builder |
    <字段集类=输入>
        <%= desc_builder.label:名称%>
        <%= desc_builder.text_field:名称%>
    < /字段集>    <字段集类=输入>
        <%= desc_builder.label:描述%GT;
        <%= desc_builder.text_area:描述%GT;
    < /字段集>
  <%结束%GT;
  <字段集类=按钮>
      <%= f.submit邮报%GT;
  < /字段集><%结束%GT;

在您的Person模型添加以下

 类Person< ActiveRecord的::基地
#...添加这一行
    accepts_nested_attributes_for:描述,:reject_if => PROC {|属性|属性['名'。空白? &功放;&安培;属性['说明'。空白? }
#... ---

然后在你的演出行动的人控制只是建立了上述说明

指示

 #你可能有这样的事情已经
  @person = Person.find的(PARAMS [:ID])
  #Now做到这一点
  @description = @#person.descriptions.build添加如果@ person.descriptions.empty?这里如果您只想每人描述。

以上code将安排进行发布表单回到者控制器更新操作,它会自动创建描述记录。无需更改任何其他控制器code在所有。

这是因为的form_for @person将安排URL去更新行动,它已经是一个现有的人

该fields_for将安排被嵌套在params哈希表的更新操作获得的人里面的字段描述字段。

和最后的accepts_nested_attributes_for将安排进行创建或自动更新必要的描述记录。的:reject_if =>进程内安排它,以便如果两个名称和描述都是空白没有新的记录被创建。可以很明显的包括多个字段,更改条件或不能拥有一切。无论适合您的要求。

希望这将让你感动。
你可以找到更多关于accepts_nested_attributes这里如果你觉得有必要
<一href=\"http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html\">http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

So in my app I have a Person model which has_many Descriptions. I now need a form on each person's show page for to add a new description for that person. So far I have the following form. However it isn't passing the person's ID to the Description Create action.

Form

<%= 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 %>

Params Passed

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

解决方案

Create the description object in the show action for the person controller by building it on to the person object instead of in the form

So in the show action you would have

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

then change your form_for to use @description

This is a less than ideal solution as you will be finding this posting back to the description controller but you can change the url in the form_for

Also, relying on ID's to find records in controller actions is wrong.. Someone could easily change the code in the browser to use a different ID on the person object. You should consider this very carefully. Quite often you will find that a person is only allowed to edit their own description so a current_user object based on the currently logged in user is often used in show and edit actions when dealing with this kind of scenario.

Update

Forgot to mention that when the form is posted back to the controller you build the description on to the person before saving in the same way as above. So you will need to find the person which again should not rely on ID's just use the currently logged in user. Hope that helps

++ UPDATE 2 ++

Further to the above I think you really need to use form_for @person then use fields_for :description and add accepts_nested_attributes_for :description to your Person model so you'll end up with something like this.

<%= 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 %>

In your Person model add the following

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

Then in your show action for the person controller just build the description as indicated above

  #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.

The above code will arrange for your form to be posted back to the persons controller update action which will automatically create the description record. No need to change any other controller code at all.

this is because the form_for @person will arrange for the url to go to the update action as it's already an existing person

The fields_for will arrange for the description fields to be nested inside the person fields in the params hash that the update action gets.

And lastly the accepts_nested_attributes_for will arrange for the description record to be either created or updated automatically as necessary. The :reject_if => proc arranges it so that if both the name and the description are blank no new record is created. You can obviously include more fields, change the condition or not have it all. Whatever suits your requirements.

Hopefully that'll get you moving. You can find out more about accepts_nested_attributes here if you feel the need http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

这篇关于新的form_for模式相关的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆