1

여러분, 레일스 5는 레일스 4와 다른 뉘앙스를 갖고 있습니다. 제출 버튼을 클릭 할 때마다 프로필 사용자가 존재해야합니다.프로필 사용자는 비워 둘 수 없습니다.. 나는 다른 있었다 한레일 5 - 중첩 모델 상위 모델이 하위 모델보다 먼저 저장되지 않기 때문에 롤백됩니다.

Puma starting in single mode... 
* Version 3.7.0 (ruby 2.2.6-p396), codename: Snowy Sagebrush 
* Min threads: 5, max threads: 5 
* Environment: development 
* Listening on tcp://0.0.0.0:3000 
Use Ctrl-C to stop 
Started POST "/users" for 192.168.0.31 at 2017-03-09 18:51:04 -0500 
Cannot render console from 192.168.0.31! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255 
    ActiveRecord::SchemaMigration Load (0.2ms) SELECT `schema_migrations`.* FROM `schema_migrations` 
Processing by UsersController#create as HTML 
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"JPKO+ppAYqwWS8tWeXhEtbUWynXREu9jYlF0KIlyPgUaabHSzjPZocSxCvr/WEm1r6wAQyT1CvA6hNkZWfPD3Q==", "user"=>{"username"=>"test", "password"=>"[FILTERED]", "user_type_id"=>"1", "profile_attributes"=>{"first_name"=>"123", "middle_name"=>"123", "last_name"=>"123", "email"=>"[email protected]", "phone_number"=>"1234567890", "cell_number"=>"1234567890"}}, "commit"=>"Create User"} 
    (0.1ms) BEGIN 
    (0.2ms) ROLLBACK 
    Rendering users/new.html.erb within layouts/application 
    Rendered users/_form.html.erb (112.5ms) 
    Rendered users/new.html.erb within layouts/application (118.7ms) 
Completed 200 OK in 834ms (Views: 780.1ms | ActiveRecord: 2.2ms) 

: 양식로드는 잘하지만 지금은 콘솔에 다음과 같은 출력으로 하위 모델을 저장하기 전에 상위 모델을 저장 실패 추론 무엇을위한, 중첩 된 모델 형태를 포함 이 관계에서 문제가 생겨서 프로젝트를 재건해야 할 필요가 있다고 생각합니다. 다음은이 문제를 해결 관련된 모든 코드입니다 : 나는 비슷한 문제가 발생했다

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

############################################################################### 
### Profile Model 
############################################################################### 
    class Profile < ApplicationRecord 
     belongs_to :user, inverse_of: :profile 
     validates_presence_of :user 
    end 
############################################################################### 
### Users 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 
     @user.build_profile 
     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: [:id, :user_id, :first_name, :middle_name, :last_name, :phone_number, :cell_number, :email]) 
     end 
    end 

############################################################################### 
### Form 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 %> 
+0

해결 방법이없는 것 같고 아무도 도움을 제공하지 않으므로 버그라고 가정 할 것입니다. 나는 시스템이 나를 허용 할 때 이것에 현상금을 부과 할 것이다. –

답변

1

좋아요. 나는 다른 질문에 대한 질문을 다시 말하고 마침내 이것에 대한 답을 찾았습니다. 그래서 누군가가 같은 방식으로 여기에서 질문을하고있는 이슈를 검색 할 경우, 거기에서 내 대답을 붙여 넣습니다.

좋아, 나는 많은 사람들이 이것으로 고투하고있는 것을 알고 있기 때문에 나는 실제로 대답을하고 문서에 막연한 응답이 아니라는 것을 알고 있기 때문에 내 자신의 질문에 대답하고있다.

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

  • 자동 저장 :
  • 사실 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

    (중첩 된 속성으로 저장하지 않았다).

    컨트롤러에서 @user.build_profile@user.profile.build(params[:profile])으로 변경하여 문제가 해결되었습니다.

    +0

    나는 그것을 곧 이해할만한 방법으로 시도 할 것이다. 내가 물어볼 수 있다면 어떻게 알아 냈어? 나는 며칠 동안 인터넷 검색을 해왔다. –

    +0

    그 결과 ** 초기화되지 않은 상수 User :: Profile ** –

    +0

    죄송합니다. 유형이 있습니다. 그래서'@ user.profile.build (params [: profile])'대신'@ user.profiles.build (params [: profile])'을 사용할 수 있습니다. 나는 그것이 '해야하는'has_one' <==>'belongs_to' 관계의 경우 반드시 아니라는 것을 알고 http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html 에서 알았어요. profiles' 메쏘드는 테이블 사이에'has_many'<==>'belongs_to' 본드가 일반적이기 때문에 모든 사용자의 프로파일을 반환합니다 (단지 has_one). 그러나 어떻게 든 작동했습니다. – bencekiss