开发者

Form_For New Related Model

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 hav开发者_运维百科e 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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜