Rails 3.1: вложенные атрибуты не сохраняются через форму

Я подозреваю, что это может быть очень простая ошибка, но я потратил 3 часа на ее поиски, поэтому я подумал, что могу попросить помощи у сообщества.

Я просматриваю отличные скринкасты Райана Бейтса о формах вложенных моделей и пытаюсь применить их к своему собственному проекту. Проблема в том, что вложенный атрибут не сохраняется при использовании формы. Я могу заставить его сохраниться через консоль, но при просмотре формы он отображается только как пустые скобки.

Вот соответствующий код:

Представление формы (с использованием haml)

= form_for(@article) do |f|
  - if @article.errors.any?
    #error_explanation
      %h2
        = pluralize(@article.errors.count, "error")
        prohibited this article from being saved:
        %ul
          - @article.errors.full_messages.each do |msg|
            %li= msg
  .field
    = f.label :title
    %br/
    = f.text_field :title
  .field
    = f.label :intro
    %br/
    = f.text_area :intro
  = f.fields_for :subsections do |builder|
    = render 'subsections_fields', :f => builder
  .field
    = f.label :published_at
    %br/
    = f.text_field :published_at
  .actions
    = submit_or_cancel(f)

представление формы subsection_fields

= f.label :header
%br/
= f.text_field :header
= f.label :order_id
= f.number_field :order_id
%br/
= f.label :body
%br/
= f.text_area :body
%br/
= f.check_box :_destroy
= f.label :_destroy, "Remove Subsection"
%br/

Контроллер

class ArticlesController < ApplicationController
  def new
    @article = Article.new
    3.times { @article.subsections.build }
  end

  def create
    @article = Article.new(params[:article])

    if @article.save
      flash[:notice] = "Successfully created article."
      redirect_to @article
    else
      render :action => 'new'
    end
  end

  def edit
    @article = Article.find(params[:id])
  end

  def update
    @article = Article.find(params[:id])
    if @article.update_attributes(params[:article])
      flash[:notice] = "Successfully updated article."
      redirect_to @survey
    else
      render :action => 'edit'
    end
  end

  def destroy
    Article.find(params[:id]).destroy
    flash[:notice] = "Succesfully destroy article."
    redirect_to articles_url
  end

  def show
    @article = Article.find(params[:id])
  end

  def index
    @articles = Article.all
  end
end

И модели

class Article < ActiveRecord::Base
  attr_accessible :title, :intro

  has_many :subsections, :dependent => :destroy
  accepts_nested_attributes_for :subsections, :reject_if => lambda { |a| a[:body].blank? },
                                              :allow_destroy => true
  has_and_belongs_to_many :categories
  validates :title, :presence => true
end


class Subsection < ActiveRecord::Base
  attr_accessible :header, :body, :order_id

  belongs_to :article

  validates :header,  :presence => true
  validates :body,    :presence => true 
end

Любая помощь в выяснении этого очень ценится.


person Phil Aquilina    schedule 14.01.2012    source источник


Ответы (3)


Я не совсем уверен, но попробуйте и с attr_accessible :article_id в вашей модели Subsection?

person Vapire    schedule 14.01.2012
comment
Я новичок в рельсах, но не опасно ли это? Разве это не позволяет кому-то массово присваивать идентификаторы статей? - person Phil Aquilina; 15.01.2012
comment
Да, именно поэтому существует MassAssignmentSecurity чтобы помочь вам очистить ваши атрибуты. Но вы устанавливаете article_id через массовое назначение, через форму. - person Vapire; 15.01.2012
comment
Возможно, это немного выходит за рамки, но, насколько я понимаю, использование @article.subsections.build в контроллере не устанавливает автоматически внешний ключ article_id? Я пошел дальше и все равно попробовал, и это не решает проблему. - person Phil Aquilina; 16.01.2012

Добавление «attr_accessible» к модели меняет способ работы массового назначения в рельсах.

Если вы удалите строки «attr_accessible» в своих моделях, весь ваш код будет работать безукоризненно.

Метод класса «accepts_nested_attributes_for» добавляет в вашу модель метод «subsections_attributes=(value)».

Во-вторых, когда вы добавляете «attr_accessible» в модель, вы теперь вынуждены добавлять дополнительные записи «attr_accessible» для каждого поля, которое вы хотите назначить с помощью массового назначения. то есть когда вы используете Article.new(params[:article]).

Надеюсь, это было понятно.

person cmrichards    schedule 21.02.2012
comment
Я знал это, когда устанавливал модели. Проблема возникла, когда я предположил, что, поскольку у меня есть attr_accessible методов в дочерней модели для каждого поля, которое я хотел массово назначать, в родительской модели ничего не нужно было устанавливать. - person Phil Aquilina; 22.02.2012