0

레일 5 및 모든 것을 최신 안정 버전으로 사용하고 있습니다. 그래서 다음을 얻었습니다 :부모 모델이 먼저 저장하지 않기 때문에 Rails 5에서 중첩 된 속성을 저장하지 않는 이유

귀하의 협회는 필수로 설정되어 있지만 누락되었습니다. 협회는 당신이 선택 사양 설정해야 당신이 빈 하나를 유지 원하는 그렇다면 레일 (5)에서 기본적으로 필요한 설정됩니다 : 사실 당신의 연결에 모드에서

이 큰 내가 이해하지만 무슨 일 것입니다 내 인생에 대한 부모 모델을 먼저 저장하는 방법을 알아낼 수 없으므로 user_id는 중첩 된 모델 레코드로 변환됩니다. 그러나 아무도 위의 동일한 대답을 본다. 아무도 이니셜 라이저의 기본값을 true에서 false로 바꾸는 것 이외의 다른 방법을 설명하지 않는다. 레코드는 확실히 저장하지만 user_id는 포함되지 않으므로이 문제는 해결되지 않습니다.

아래 코드는 위 코드를 사용하여 응답하는 대신 사용자가 저장하는 동안 중첩 된 특성에 USER_ID 필드를 가져 오는 방법을 알려줍니다. 유효성 검사를 비활성화하고 수동으로 삽입을 처리하는 것을 거부합니다. 이것은 루비 방법이 아니기 때문에 표준에서 벗어났습니다! 이 질문에 직접 답할 수있는 사람과 루비 같은 방법을 모르는 어렴풋한 설명없이 미리 감사드립니다! 난 당신이 자동 저장을 포함해야한다는 것을 알아 낸 우선 들어

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

#Profiles 
class Profile < ApplicationRecord 
    belongs_to :user, inverse_of: :profile 
end 

###Controller 
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.build_profile 
    end 

    # GET /users/1/edit 
    def edit 
    @user.build_profile 
    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: [:user_id, :first_name, :middle_name, :last_name, :phone_number, :cell_number, :email]) 
    end 
end 

##View 
<%= 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 %> 
     <!--<li><%= debug f %></li>--> 
     </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, :readonly => true, :value => '2' %> 
    <% else %> 
     <%= f.label :user_type_id %> 
     <%= f.text_field :user_type_id, :readonly => true, :value => '1' %> 
    <% end %> 
    </div> 
    <h2>Account Profile</h2> 
    <%= f.fields_for :profile do |profile| %> 
     <%#= profile.inspect %> 
     <div> 
      <%= profile.label :first_name %> 
      <%= profile.text_field :first_name %> 
     </div> 
     <div> 
      <%= profile.label :middle_name %> 
      <%= profile.text_field :middle_name %> 
     </div> 
     <div> 
      <%= profile.label :last_name %> 
      <%= profile.text_field :last_name %> 
     </div> 
     <div> 
      <%= profile.label :email %> 
      <%= profile.text_field :email %> 
     </div> 
     <div> 
      <%= profile.label :phone_number %> 
      <%= profile.telephone_field :phone_number %> 
     </div> 
     <div> 
      <%= profile.label :cell_phone %> 
      <%= profile.telephone_field :cell_number %> 
     </div> 
    <% end %> 
    <div class="actions"> 
    <%= f.submit %> 
    </div> 
    <%= debug params %> 
    <%= debug user %> 
    <%= debug user.profile %> 
<% end %> 

UPDATE : 관계에 사실 너무

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

같은 그런 다음 부모 레코드는 자식 전에 저장됩니다. 지금 대해 단지 확실하지 않다 양식이 당신은 내가 profiles INTO 문이 아래 INSERT를 붙여 콘솔 출력에 알 제출 USER_ID 열 및 1의 값을 포함 할 때 홀수 또 다른 잡았다 온다 . 유효성 검사를 마치고 결과가 정상적으로 실행되는 것처럼 보이지만, user_id의 프로필 테이블은 여전히 ​​null입니다. 나는 파기를 계속할 것입니다. 저의 동료 루비스트 중 한 명이 이것을보고 고칠 방법을 알려줄 것입니다. 지금까지 Rails 5 개선점이 좋았지 만, ROR이되지는 못했을 것입니다. 다시 한번 감사드립니다! 나는 많은 사람들이 고민하는 알고 실제로 대답이 아닌 문서에 대한 막연한 응답을 가지고 있기 때문에

Started POST "/users" for 192.168.0.31 at 2017-03-12 22:28:14 -0400 
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#create as HTML 
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"YA7kQnScvlIBy5OiT+BmOQ2bR7J00ANXId38FqNwX37Cejd+6faUyD3rMF4y0qJNKBUYGaxrRZqcLrXonL6ymA==", "user"=>{"username"=>"john", "password"=>"[FILTERED]", "user_type_id"=>"1", "profile_attributes"=>{"first_name"=>"john", "middle_name"=>"r", "last_name"=>"tung", "email"=>"[email protected]", "phone_number"=>"8033207677", "cell_number"=>"8033207677"}}, "commit"=>"Create User"} 
    (0.1ms) BEGIN 
    SQL (0.3ms) INSERT INTO `users` (`username`, `password`, `user_type_id`, `created_at`, `updated_at`) VALUES ('john', '0000', 1, '2017-03-13 02:28:14', '2017-03-13 02:28:14') 
    SQL (0.4ms) INSERT INTO `profiles` (`user_id`, `email`, `first_name`, `middle_name`, `last_name`, `phone_number`, `cell_number`, `created_at`, `updated_at`) VALUES (1, '[email protected]', 'john', 'r', 'tung', '8033207677', '8033207677', '2017-03-13 02:28:14', '2017-03-13 02:28:14') 
    (10.8ms) COMMIT 
Redirected to http://192.168.0.51:3000/users/1 
Completed 302 Found in 24ms (ActiveRecord: 11.5ms) 
+0

'autosave' 옵션은 Rails 공식 문서에서 자세히 설명합니다. http://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html – jvnill

답변

2

좋아, 난 내 자신의 질문에 대답하고있다.

먼저이 예제에서는 일대일 관계를 사용합니다.

  • 자동 저장 :
  • 사실 accepts_nested_attributes_for : 여기
  • 가있는 경우에 true : 모델, allow_destroy 당신이 당신의 관계를 만들 때 당신은 상위 모델은 다음과

    1. inverse_of이 있는지 확인해야합니다 사용자 모델을 입력하면 다음과 같이 설명됩니다.

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

      레일 5에 inverse_of가 필요합니다. 이는 Rails에 외래 키를 통한 관계가 있고 양식 데이터를 저장할 때 중첩 모델에 설정해야한다는 것을 알려주기 때문입니다. 이제 자동 저장을 남겨 두려는 경우 : 관계 선에서 벗어났습니다. user_id은 유효성 검사를하지 않은 경우를 제외하고는 프로필 테이블과 다른 열에 저장되지 않습니다. 그러면 오류가 발생하지 않습니다. user_id 없이는 저장됩니다. 여기서 일어나는 일은 자동 저장입니다. true은 사용자 레코드가 먼저 저장되어 프로필 모델의 중첩 속성에 저장 될 user_id가이되도록합니다. 그 이유는 간단히 말해서 user_id이 자식에게 전달되지 않고 커밋하는 것이 아니라 롤백하는 것입니다. 또 하나의 마지막 잡았다 거기에 당신이 컨트롤러를 추가 경로에 대한 컨트롤러에 알려주 일부 게시물입니다 @ user.build_profile 내 게시물에있다. 당신이 처음부터 프로파일을 재건하고 당신이 현재 사용자를 일치하는 레코드를 null로 USER_ID를 재설정되어 보면 그들은

      Started GET "https://stackoverflow.com/users/1/edit" for 192.168.0.31 at 2017-03-12 22:38:17 -0400 
      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.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1 
          Profile Load (0.5ms) SELECT `profiles`.* FROM `profiles` WHERE `profiles`.`user_id` = 1 LIMIT 1 
          (0.1ms) BEGIN 
          SQL (0.5ms) UPDATE `profiles` SET `user_id` = NULL, `updated_at` = '2017-03-13 02:38:17' WHERE `profiles`.`id` = 1 
          (59.5ms) COMMIT 
          Rendering users/edit.html.erb within layouts/application 
          Rendered users/_form.html.erb (44.8ms) 
          Rendered users/edit.html.erb within layouts/application (50.2ms) 
      Completed 200 OK in 174ms (Views: 98.6ms | ActiveRecord: 61.1ms) 
      

      에이 결과를 콘솔 출력을 평가 한 후, DEAD 잘못하지 마 편집. 이렇게 나는이 제안을하는 다수의 게시물을 보았고 해결 방법을 찾기 위해 하루의 연구 비용이 들었습니다.

    +0

    edit 액션에서'@ user.build_profile'이 필요없는 이유는 이미'profile' 레코드를 저장하고 있기 때문입니다 귀하의 사용자. 'profile' 레코드가없는 사용자가 사용자 편집 페이지로 간다면, 그들은 프로파일의 폼을 결코 보지 못할 것입니다. 그래서'@ user.build_profile'을 호출하기 전에 프로파일이 존재하는지 확인하십시오. – jvnill

    +0

    내가 대답 한 내용에서 알 수 있듯이 인터넷에서 사람들이 잘못 조언하고 노련한 전문가가되어서 잘못된 정보로 인해 큰 문제가있는 것 같기 때문에 여기에서 설명했습니다. –

    +0

    그러나 당신은 당신이 왜 그걸 전혀 필요로하지 않는지 설명하지 못했습니다. 당신은 방금 그렇게하는 것이 잘못이라고했습니다. 내가 말했듯이, 그것은 사건을 근거로합니다. 앱에서 작동하지 않는다고해서 다른 앱에서 작동하지 않는다는 의미는 아닙니다. – jvnill

    관련 문제