Rails嵌套表单不能保存孩子

use*_*309 7 ruby-on-rails has-many nested-forms

我的用户模型has_many响应.我正在尝试创建一个嵌套表单来创建一个具有三个子响应的新用户.我的代码看起来与Rails强制转换相同,但是虽然它会保存用户,但它不会保存它们的响应.任何人都可以看到有什么问题?

users_controller.rb

class UsersController < ApplicationController
  def new
    @user = User.new
    3.times{@user.responses.build}
    @responses = @user.responses
  end

  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to @user #todo: where do we want to redirect?
    else
      render 'new'
    end
  end

  def show
    @user = User.find(params[:id])
    @responses = @user.responses
  end

  def index
    @users = User.all
  end

  private

    def user_params
      params.require(:user).permit(:username, :email, :responses)
    end
end
Run Code Online (Sandbox Code Playgroud)

user.rb

class User < ActiveRecord::Base
  attr_accessor :responses_attributes
  has_many :responses, :dependent => :destroy
  accepts_nested_attributes_for :responses#, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true

  before_save { self.email = email.downcase }

  validates :username,  length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX } ,
            uniqueness: {case_sensitive: false};

  validates :responses, presence: true
end
Run Code Online (Sandbox Code Playgroud)

response.rb

class Response < ActiveRecord::Base
  belongs_to :user
  validates_presence_of :user_id, :content
end
Run Code Online (Sandbox Code Playgroud)

users/new.html.erb(表单)

<h1>This is a test form for adding Users with child Responses</h1>

<%= form_for @user do |f| %>
    <%= render 'shared/error_messages' %>

    <%= f.label :username %>
    <%= f.text_field :username %>

    <%= f.label :email %>
    <%= f.text_field :email %>
    <p>
    <%= f.fields_for :responses do |builder| %>
          <%= builder.label :content, "Response" %>
          <%= builder.text_field :content %>
    <% end %>
    </p>
    <%= f.submit "Submit" %>
<% end %>
Run Code Online (Sandbox Code Playgroud)

编辑:

我已将Users控制器中的强参数更改为:

def user_params
  params.require(:user).permit(:username, :email, responses_attributes: [:content])
end
Run Code Online (Sandbox Code Playgroud)

我已将用户模型更新为:

class User < ActiveRecord::Base
  has_many :responses, :dependent => :destroy
  accepts_nested_attributes_for :responses#, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true

  before_save { self.email = email.downcase }

  validates :username,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX } ,
            uniqueness: {case_sensitive: false};

  validates_associated :responses, presence: true
end
Run Code Online (Sandbox Code Playgroud)

现在它仍然无法通过我的响应验证,也无法验证用户名和电子邮件的验证.

Blu*_*ith 6

问题出在您的Response类中:

validates_presence_of :user_id, :content
Run Code Online (Sandbox Code Playgroud)

此验证需要存在user_id,这意味着必须在Response之前创建用户.为了使它工作,你可以尝试几件事:

  • 更改validates_presence_of :user_idvalidates_presence_of :user使其验证User对象而不是用户的ID.

  • 使用inverse_of选项.请参阅Rails API文档.

更新的代码.

user.rb

class User < ActiveRecord::Base
  attr_accessible :responses_attributes
  has_many :responses, :dependent => :destroy, :inverse_of => :user
  accepts_nested_attributes_for :responses

  # ...
end
Run Code Online (Sandbox Code Playgroud)

response.rb

class Response < ActiveRecord::Base
  belongs_to :user, :inverse_of => :responses
  validates_presence_of :user, :content
end
Run Code Online (Sandbox Code Playgroud)