Rails 4: accepts_nested_attributes_for и масово присвояване

Опитвам се да възпроизведа railscast #196 в Rails 4. Въпреки това изпитвам някакви проблеми.

В моя пример се опитвам да генерирам телефонен указател - всяко лице може да има множество телефонни номера

Това са важни части от моя контролер:

class PeopleController < ApplicationController
    def new
        @person = Person.new
        3.times{ @person.phones.build }
    end

    def create
        @person = Person.create(person_params)
        @person.phones.build(params[:person][:phones])

        redirect_to people_path
    end

private

    def person_params
        params.require(:person).permit(:id, :name, phones_attributes: [ :id, :number ])
    end
end

и това е новото ми виждане

<h1>New Person</h1>

<%= form_for :person, url: people_path do |f| %>
    <p>
        <%= f.label :name %> </ br>
        <%= f.text_field :name %>
    </p>

    <%= f.fields_for :phones do |f_num| %>
        <p>
            <%= f_num.label :number %> </ br>
            <%= f_num.text_field :number %>
        </p>
    <% end %>

    <p>
        <%= f.submit %>
    </p>
<% end %>

Излишно е да казвам, че имам has_many :phones и accepts_nested_attributes_for :phones в модела my person и belongs_to :person в модела на телефона.

Имам следните проблеми:

  1. Вместо 3 полета за телефонен номер в новата форма има само едно
  2. Когато изпратя формуляра, получавам грешка:

ActiveModel::ForbiddenAttributesError

в линията

@person.phones.build(params[:person][:phones])

Параметри:

{"utf8"=>"✓",
 "authenticity_token"=>"l229r46mS3PCi2J1VqZ73ocMP+Ogi/yuYGUCMu7gmMw=",
 "person"=>{"name"=>"the_name",
 "phones"=>{"number"=>"12345"}},
 "commit"=>"Save Person"}

По принцип бих искал да направя цялото това нещо като обект на формуляр, но мисля, че ако дори не го получа с accepts_nested_attributes, нямам шанс да го направя като обект на формуляр :(


person speendo    schedule 30.08.2013    source източник


Отговори (1)


За да получите три телефона в изгледа, променете form_for :person на form_for @person (искате да използвате обекта, който сте създали тук), както следва:

<%= form_for @person, url: people_path do |f| %>

Това трябва да коригира и грешката ForbiddenAttributes.

И вашето create действие може да бъде:

def create
    @person = Person.create(person_params)

    redirect_to people_path
end

Актуализация:

<%= form_for :person do |f| %> създава обща форма за модела Person и не е наясно с допълнителните подробности, които прилагате към конкретен обект (в този случай @person във вашето new действие). Прикачили сте три phones към обекта @person и @person не е същото като :person, поради което не сте видели три телефонни полета във вашия изглед. Моля, вижте: http://apidock.com/rails/ActionView/Helpers/FormHelper/form_for за повече подробности.

person vee    schedule 30.08.2013
comment
ура! Това реши и двата проблема - не мога да кажа колко се радвам! В базовия урок за релси те използват хеш: guides.rubyonrails.org/getting_started. html#the-first-form - можеш ли да обясниш по-подробно разликата? - person speendo; 31.08.2013
comment
@speendo, моля, вижте актуализацията, ако имате предвид разликата между използването на символ спрямо използването на обект. - person vee; 31.08.2013
comment
Имам последващ коментар. Ако моделът на телефона има phone_type_id и code def new @person = Person.new ph = Person.phone.build ph[:phone_type_id] = 1 ph2 = Person.phone.build ph2[:phone_type_id] = 2 end code Как би изгледът знае идентификационните номера на типа телефон и го изпраща обратно, без да запазва code@personcode в края на новия метод? - person tandoan; 02.12.2013
comment
Това работи много добре, но има нещо, което липсва. Когато по някаква причина входовете са невалидни и person не могат да бъдат създадени, следвайки същите указания, казани от @speendo, ние правим render 'new' и полетата на phones (или в моя случай emails) изчезват. - person unmultimedio; 09.08.2015
comment
@unmultimedio, трябва също така да се уверите, че създавате всички необходими асоциации, преди да се обадите на render 'new'. - person vee; 09.08.2015