Rails 5嵌套表单属性不保存

时间:2017-03-01 17:18:47

标签: ruby-on-rails ruby ruby-on-rails-5

好的我有一个与配置文件表相关的User表,我相信我已经完成了我想要做的所有事情,以便保存嵌套的表单属性,但是它们不会保存到数据库中。我已阅读其他帖子,似乎没有一个适合或解决方案不起作用。要明确我在基于Linux的系统上使用Rails 5和MySQL。 我已将相关文件包括在下面

用户模型

class User < ApplicationRecord
  has_one :profile, inverse_of: :user
  accepts_nested_attributes_for :profile, allow_destroy: true
end

个人资料模型

   class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]

  # GET /users
  # GET /users.json
  def index
    @users = User.all
  end

  # GET /users/1
  # GET /users/1.json
  def show
  end

  # GET /users/new
  def new
    @user = User.new
    @user.create_profile
    @user.build_profile
  end

  # GET /users/1/edit
  def edit

  end

  # POST /users
  # POST /users.json
  def create
    @user = User.new(user_params)

    respond_to do |format|
      if @user.save
        format.html { redirect_to @user, notice: 'User was successfully created.' }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render :new }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /users/1
  # PATCH/PUT /users/1.json
  def update
    respond_to do |format|
      if @user.update(user_params)
        format.html { redirect_to @user, notice: 'User was successfully updated.' }
        format.json { render :show, status: :ok, location: @user }
      else
        format.html { render :edit }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /users/1
  # DELETE /users/1.json
  def destroy
    @user.destroy
    respond_to do |format|
      format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_user
      @user = User.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def user_params
      params.require(:user).permit(:username, :password, :user_type_id, profile_attributes: [:id, :user_id, :first_name, :middle_name, :last_name, :phone_number, :cell_number, :email])
    end
end

用户构成部分

<%= form_for(user) do |f| %>
      <% if user.errors.any? %>
        <div id="error_explanation">
          <h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>

          <ul>
          <% user.errors.full_messages.each do |message| %>
            <li><%= message %></li>
          <% end %>
          </ul>
        </div>
      <% end %>

      <div class="field">
        <%= f.label :username %>
        <%= f.text_field :username %>
      </div>

      <div class="field">
        <%= f.label :password %>
        <%= f.text_field :password %>
      </div>

      <div class="field">
        <% if params[:trainer] == "true" %>
        <%= f.label :user_type_id %>
        <%= f.text_field :user_type_id %>
        <% else %>
        Nota trainer
        <% end %>
      </div>
        <h2>Account Profile</h2>
        <%= f.fields_for :profiles do |client_profile| %>
          <%#= client_profile.inspect %>
            <div>
              <%= client_profile.label :first_name %>
              <%= client_profile.text_field :first_name %>
            </div>
            <div>
              <%= client_profile.label :middle_name %>
              <%= client_profile.text_field :middle_name %>
            </div>
            <div>
              <%= client_profile.label :last_name %>
              <%= client_profile.text_field :last_names %>
            </div>
            <div>
              <%= client_profile.label :email %>
              <%= client_profile.text_field :email %>
            </div>
            <div>
              <%= client_profile.label :phone_number %>
              <%= client_profile.text_field :phone_number %>
            </div>
            <div>
              <%= client_profile.label :cell_phone %>
              <%= client_profile.text_field :phone_number %>
            </div>
        <% end %>
      <div class="actions">
        <%= f.submit %>
      </div>
    <% end %>

新视图

New User

    <%= render 'form', user: @user %>

    <%= link_to 'Back', users_path %>

参数调试输出

{
"utf8"=>"✓",
"_method"=>"patch", 
"authenticity_token"=>"oZwa3K5QJRKlWGf176/fOOmrANd07KUyXUJa8Ig9CtEq+OilF73R9CzWVXwE2+K/crSFfm5p3yaeW+u2KSEF7w==",
 "user"=>{
           "username"=>"vitago", 
           "password"=>"[FILTERED]", 
           "profiles"=>{
                         "first_name"=>"John", 
                         "middle_name"=>"B", 
                         "last_names"=>"Doe",            
                         "email"=>"johnbdoe@gmail.com", 
                         "phone_number"=>"1002223333"
                        }
          },
 "commit"=>"Update User",
 "id"=>"1"}

在development.log中记录输出

   Started PATCH "/users/1" for 192.168.0.31 at 2017-03-02 01:28:22 -0500
    Cannot render console from 192.168.0.31! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
    Processing by UsersController#update as HTML
      Parameters: {
        "utf8"=>"✓",      
     "authenticity_token"=>"GRKhJuTuytcwr4ycCBi0KiFNkmRCstPAnaP0Z8UucWZFp5JdfmosqOvIQ7WpgYUN8yHvEcmMcmYOPLX1iDUwAA==", 
        "user"=>{
        "username"=>"vitago", 
        "password"=>"[FILTERED]", 
        "profiles"=>{
            "first_name"=>"John", 
            "middle_name"=>"B", 
            "last_names"=>"Doe", 
            "email"=>"johnbdoe@gmail.com", 
            "phone_number"=>"1002223333"
         }
    }, 
    "commit"=>"Update User", 
    "id"=>"1"
}
      User Load (0.5ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
    Unpermitted parameter: profiles
       (0.1ms)  BEGIN
       (0.1ms)  COMMIT
    Redirected to http://192.168.0.51:3000/users/1
    Completed 302 Found in 7ms (ActiveRecord: 0.7ms)


    Started GET "/users/1" for 192.168.0.31 at 2017-03-02 01:28:22 -0500
    Cannot render console from 192.168.0.31! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
    Processing by UsersController#show as HTML
      Parameters: {"id"=>"1"}
      User Load (0.6ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
      Rendering users/show.html.erb within layouts/application
      Rendered users/show.html.erb within layouts/application (1.4ms)
    Completed 200 OK in 43ms (Views: 29.8ms | ActiveRecord: 0.6ms)


    Started GET "/users/1/edit" for 192.168.0.31 at 2017-03-02 01:28:24 -0500
    Cannot render console from 192.168.0.31! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
    Processing by UsersController#edit as HTML
      Parameters: {"id"=>"1"}
      User Load (0.5ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
      Rendering users/edit.html.erb within layouts/application
      Rendered users/_form.html.erb (7.1ms)
      Rendered users/edit.html.erb within layouts/application (12.5ms)
    Completed 200 OK in 43ms (Views: 35.6ms | ActiveRecord: 0.5ms)

2 个答案:

答案 0 :(得分:2)

:profile是嵌套模型的名称,因此在您的user_params中请尝试profile_attributes

def user_params
  params.require(:user).permit(:username, :password, :user_type_id, profile_attributes: [:id, :first_name, :middle_name, :last_name, :email, :phone_number, :cell_number])
end

此外,您似乎忘记了嵌套配置文件参数中的:email

表格中的这一行:

<%= f.fields_for :profiles do |client_profile| %>

它应该是:

<%= f.fields_for :profile do |client_profile| %>

User has_one profile,因此配置文件在您的嵌套表单中应该是单数。

更新:

新操作和编辑操作都需要在其中内置空配置文件,以便显示嵌套表单:

def new
  @user = User.new
  @user.build_profile
end

# GET /users/1/edit
def edit
  @user.build_profile
end

答案 1 :(得分:1)

你做的改动很少,有些已经在@Ren的答案中给出了,

1)新操作,@user.create_profile不需要。

def new
    @user = User.new
    @user.build_profile
end

2) <%= form_for(user) do |f| %>应为 <%= form_for @user do |f| %>

3) <%= f.fields_for :profiles do |client_profile| %>应为 <%= f.fields_for :profile do |client_profile| %>

<%= form_for @user do |f| %>
    <% if user.errors.any? %>
      <div id="error_explanation">
            <h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>
            <ul>
                    <% user.errors.full_messages.each do |message| %>
                    <li><%= message %></li>
                    <% end %>
            </ul>
       </div>
    <% end %>

    <div class="field">
    <%= f.label :username %>
    <%= f.text_field :username %>
    </div>

    <div class="field">
    <%= f.label :password %>
    <%= f.text_field :password %>
    </div>

    <div class="field">
    <% if params[:trainer] == "true" %>
    <%= f.label :user_type_id %>
    <%= f.text_field :user_type_id %>
    <% else %>
    Nota trainer
    <% end %>
    </div>
    <h2>Account Profile</h2>
    <%= f.fields_for :profile do |client_profile| %>
        <%#= client_profile.inspect %>
        <div>
            <%= client_profile.label :first_name %>
            <%= client_profile.text_field :first_name %>
        </div>
        <div>
            <%= client_profile.label :middle_name %>
            <%= client_profile.text_field :middle_name %>
        </div>
        <div>
            <%= client_profile.label :last_name %>
            <%= client_profile.text_field :last_names %>
        </div>
        <div>
            <%= client_profile.label :email %>
            <%= client_profile.text_field :email %>
        </div>
        <div>
            <%= client_profile.label :phone_number %>
            <%= client_profile.text_field :phone_number %>
        </div>
        <div>
            <%= client_profile.label :cell_phone %>
            <%= client_profile.text_field :phone_number %>
        </div>
    <% end %>
    <div class="actions">
    <%= f.submit %>
    </div>
<% end %>