使用accepts_nested_attributes_for保存两个Rails模型

时间:2014-05-04 00:28:27

标签: ruby-on-rails

我有两个模型:作者和个人资料。作者accepted_nested_attributes_for个人资料。我无法弄清楚如何通过作者保存配置文件模型(即:头像属性)。

author.rb

class Author < ActiveRecord::Base
  has_one :profile
  accepts_nested_attributes_for :profile
end

profile.rb

class Profile < ActiveRecord::Base
  mount_uploader :avatar, AvatarUploader
  belongs_to :author
end

authors_controller.rb

class AuthorsController < ApplicationController
  before_action :set_author, only: [:show, :edit, :update, :destroy]

  def index
    @authors = Author.all.order("last_name ASC, first_name ASC")
  end

  def new 
    @author = Author.new
  end

  def create
    @author = Author.new(author_params)

    if @author.save
      AuthorMailer.activate(@author).deliver
      flash[:notice] = "Please check your email to activate your account."
      redirect_to root_path
    else
      render :new
    end

  end

  def edit
    @profile = @author.build_profile
  end

  def update 
    if @author.update(author_params)
      flash[:notice] = "Profile has been updated."
      redirect_to @author
    else
      flash[:alert] = "Profile has not been updated."
      render :edit
    end
  end

  private

    def author_params
      params.require(:author).permit(:first_name, :last_name, :email, :password, :password_confirmation, :avatar)
    end

    def set_author
      @author = Author.find(params[:id])
    end 
end

应用/视图/作者/ edit.html.erb

<div class="center">
  <h1>Edit Author</h1>
</div>

<div class="row">
  <div class="col-xs-6 col-lg-4 center-block">
    <%= simple_form_for(@author, :defaults => { :wrapper_html => {:class => 'form-group'}, :input_html => { :class => 'form-control' } }) do |f| %>
      <%= f.input :first_name %>
      <%= f.input :last_name %>
      <%= f.fields_for [@author, @profile] do |p| %>
        <%= p.file_field :avatar %>
      <% end %>
      <%= f.submit "Submit", class: "btn small btn-default" %> 
    <% end %>
  </div>
</div>

此表单不会将任何内容保存到我的个人资料表中。

EDIT1 更新许可证参数并没有将任何内容保存到配置文件表中。但我确实注意到在更新操作中将以下内容添加到authors_controller中会将不完整的记录保存到配置文件表中(头像字段为空白):

author_controller#更新

if @author.update(author_params)
  @profile = @author.build_profile()
  @author.profile = @profile
  flash[:notice] = "Profile has been updated."
  redirect_to @author
else
  flash[:alert] = "Profile has not been updated."
  render :edit
end

我尝试在更新操作中放置pry,我的参数看起来像这样:

{"utf8"=>"✓",
 "_method"=>"patch",
 "authenticity_token"=>"EROrMzOejPmMU/wzlnC5iaoTPu4pyBXelHAs3uiPA2U=",
 "author"=>
  {"first_name"=>"Mike",
   "last_name"=>"Glaz",
   "profile"=>
    {"avatar"=>
      #<ActionDispatch::Http::UploadedFile:0x007feb48127ab0
       @content_type="image/jpeg",
       @headers=
    "Content-Disposition: form-data; name=\"author[profile][avatar]\"; filename=\"me_and_lekeziah.jpg\"\r\nContent-Type: image/jpeg\r\n",
       @original_filename="me_and_lekeziah.jpg",
       @tempfile=#<File:/tmp/RackMultipart20140504-15793-l4uu6l>>}},
 "commit"=>"Submit",
 "action"=>"update",
 "controller"=>"authors",
 "id"=>"3"}

所以我在更新操作中尝试了以下内容:

@profile = @author.build_profile(params[:author][:profile])
@author.profile = @profile

然后我收到以下错误:

ActiveModel::ForbiddenAttributesError in AuthorsController#update

2 个答案:

答案 0 :(得分:0)

当你使用&#34; fields_for&#34;对于关联模型xxx,你的params需要允许:xxx_attributes字段,其值应该是包含它的属性的数组,所以将author_params方法更改为:

def author_params
  params.require(:author).permit(:first_name, :last_name, :email, :password, :password_confirmation, profile_attributes: [:avatar])
end

答案 1 :(得分:0)

首先,您应该将params允许的字段更新为:

def author_params
  params.require(:author).permit(:first_name, :last_name, :email, :password, :password_confirmation, :profile_attributes[:id, :avatar])
end

其次,您在视图中混合了Rails form_for helper和Simple_form。

更改

<%= f.fields_for [@author, @profile] do |p| %>

为:

<%= f.simple_fields_for [@author, @profile] do |p| %>