Form_For 新相关模型

发布于 2024-11-28 03:00:51 字数 880 浏览 0 评论 0原文

因此,在我的应用程序中,我有一个 Person 模型,其中 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"}

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"}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

请远离我 2024-12-05 03:00:51

通过在人员对象上而不是在表单中构建描述对象,在人员控制器的显示操作中创建描述对象

因此,在显示操作中,您将

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

更改 form_for 以使用 @description

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

另外,依靠 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 %>

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

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

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

  #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 将安排 url 转到更新操作,因为它已经是现有人员

fields_for 将安排将描述字段嵌套在更新操作获取的 params 哈希中的人员字段内。

最后,accepts_nested_attributes_for 将安排描述记录根据需要自动创建或更新。 :reject_if => proc 对其进行安排,以便如果名称和描述均为空,则不会创建新记录。显然,您可以包含更多字段、更改条件或不拥有全部。任何适合您的要求。

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

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

遗心遗梦遗幸福 2024-12-05 03:00:51

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

hidden_field(:person, :id)

另外,不要在中创建新描述您认为,您可能应该在 Persons 控制器中创建模板描述。

The easiest way to make sure you get the id of the @person object in your params hash, is to simply add it as a hidden field on your form e.g.:

hidden_field(:person, :id)

Also, rather than creating your new description in your view, you should probably be creating a template description in your Persons controller.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文