2016-08-03 33 views
2

Ich bin in einem Rails-Projekt festgefahren, das versucht, ein has_one-Modell zu speichern, wenn der Benutzer sich mit Devise anmeldet.Speichern Sie ein has_one-Modell mit einem verschachtelten Formular mit Devise - Rails 4

Meine App speichert das untergeordnete Modell sowie den neuen Benutzer, aber das Problem besteht darin, dass die untergeordnete ID nicht in der Benutzertabelle gespeichert wird.

Ich habe viele Optionen auf Stackoverflow ohne Erfolg ausprobiert. Mache ich etwas falsch?

User-Modell:

class User < ActiveRecord::Base 
    # Include default devise modules. Others available are: 
    # :confirmable, :lockable, :timeoutable and :omniauthable 
    devise :database_authenticatable, :registerable, 
     :recoverable, :rememberable, :trackable, :validatable, :omniauthable, :omniauth_providers => [:linkedin] 

    # Associations 
    has_one :build, inverse_of: :user 
    # Allow saving of attributes on associated records through the parent, 
# :autosave option is automatically enabled on every association 
    accepts_nested_attributes_for :build, allow_destroy: true 
end 

build Modell

class Build < ActiveRecord::Base 
    belongs_to :user, inverse_of: :build 
    has_one :template 
    # validates_presence_of :user 
end 

Registrations-Controller

class Users::RegistrationsController < Devise::RegistrationsController 
before_action :sign_up_params, only: [:create] 
before_action :account_update_params, only: [:update] 
# before_filter :configure_permitted_parameters 

    # GET /resource/sign_up 
    def new 
    # super 

    # Override Devise default behaviour and create a build as well 
    build_resource({}) 
    resource.build_build 
    respond_with self.resource 

    # @build = @user.builds.build(template_id: params[:template_id], domain_url: params[:domain_url]) 
    end 

    # POST /resource 
    def create 
    super 
    # @build = current_user.build.build(params[:post]) 

    # @build = @user.build.build(template_id: sign_up_params[:template_id], domain_url: sign_up_params[:domain_url]) 
    # @build.save 
    UserMailer.welcome_email(@user).deliver unless @user.invalid? 
    end 

    # GET /resource/edit 
    # def edit 
    # super 
    # end 

    # PUT /resource 
    # def update 
    # super 
    # end 

    # DELETE /resource 
    # def destroy 
    # super 
    # end 

    # GET /resource/cancel 
    # Forces the session data which is usually expired after sign 
    # in to be expired now. This is useful if the user wants to 
    # cancel oauth signing in/up in the middle of the process, 
    # removing all OAuth session data. 
    # def cancel 
    # super 
    # end 

    # protected 
    # 
    # def configure_permitted_parameters 
    # devise_parameter_sanitizer.for(:sign_up) { |u| 
    #  u.permit(:first_name, :last_name, :email, :password, :password_confirmation, :builds_attributes => [:template_id, :domain_url]) 
    # } 
    # end 

    # If you have extra params to permit, append them to the sanitizer. 
    # def configure_sign_up_params 
    # devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute]) 
    # end 

    # If you have extra params to permit, append them to the sanitizer. 
    # def configure_account_update_params 
    # devise_parameter_sanitizer.permit(:account_update, keys: [:attribute]) 
    # end 

    # The path used after sign up. 
    # def after_sign_up_path_for(resource) 
    # super(resource) 
    # end 

    # The path used after sign up for inactive accounts. 
    # def after_inactive_sign_up_path_for(resource) 
    # super(resource) 
    # end 

    private 

    def sign_up_params 
    devise_parameter_sanitizer.sanitize(:sign_up) 
    params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, build_attributes: [:template_id, :domain_url]) 
    end 

    def account_update_params 
    params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :current_password) 
    end 
end 

New User Form - Ansicht

<div class="container"> 
<h4 class="center-align">Sign up</h4> 

<div id="signup-row" class="row z-depth-2"> 
    <div id="signup" class="col s6"> 

     <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> 
     <%= devise_error_messages! %> 

     <div class="field"> 
      <%= f.label :first_name %><br/> 
      <%= f.text_field :first_name, autofocus: true %> 
     </div> 

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

     <div class="field"> 
      <%= f.label :email %><br/> 
      <%= f.email_field :email %> 
     </div> 

     <div class="field"> 
      <%= f.label :password %> 
      <% if @minimum_password_length %> 
      <em>(<%= @minimum_password_length %> 
       characters minimum)</em> 
      <% end %><br/> 
      <%= f.password_field :password, autocomplete: "off" %> 
     </div> 

     <div class="field"> 
      <%= f.label :password_confirmation %><br/> 
      <%= f.password_field :password_confirmation, autocomplete: "off" %> 
     </div> 

     <div class="actions"> 
      <%= f.submit "Sign up", :class => 'btn black' %> 
      <%= render "devise/shared/links" %> 

     </div> 

     <%= f.fields_for :build do |o| %> 
     <%= o.hidden_field :template_id, value: params["template"] %> 
     <%= o.hidden_field :domain_url, value: params["domain"] %> 
     <% end %> 
     <% end %> 
    </div> 

    <div id="linkedin-signup" class="col s6"> 
     <div class="center-align"> 
     <h5>Sign up with LinkedIn </h5> <br> 
     <a href="http://localhost:3000/login/li/oauth2"><%= image_tag('linkedin.png', :class => "linkedIn-logo") %></a> 
     </div> 
    </div> 
    </div> 


</div> 

Server/Postprotokoll

Started POST "/users" for 127.0.0.1 at 2016-08-03 13:31:22 +1000 
Processing by Users::RegistrationsController#create as HTML 
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"11DgWCU07EXLJKXbhWah0gREdBiN2PLkF/WxWsuqW5rgQdCUrRH9rLBrKpbusRhtsCzSAQT0ADlxhQxMvWAD6A==", "user"=>{"first_name"=>"john", "last_name"=>"maksksk", "email"=>"[email protected]", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "build_attributes"=>{"template_id"=>"1", "domain_url"=>"dddddd.com.au"}}, "commit"=>"Sign up"} 
    (0.1ms) BEGIN 
    User Exists (0.6ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = '[email protected]' LIMIT 1 
    SQL (0.5ms) INSERT INTO "users" ("first_name", "last_name", "email", "encrypted_password", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["first_name", "john"], ["last_name", "maksksk"], ["email", "[email protected]"], ["encrypted_password", "$2a$11$WgJJ.uM2DfaqQhUYatUZnuIJmaqIDVfIuYEkl/U3zSbm.h/OH/yGa"], ["created_at", "2016-08-03 03:31:22.796589"], ["updated_at", "2016-08-03 03:31:22.796589"]] 
    SQL (0.2ms) INSERT INTO "builds" ("template_id", "domain_url", "user_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["template_id", 1], ["domain_url", "dddddd.com.au"], ["user_id", 30], ["created_at", "2016-08-03 03:31:22.800033"], ["updated_at", "2016-08-03 03:31:22.800033"]] 
    (1.3ms) COMMIT 
    (0.1ms) BEGIN 
    SQL (0.4ms) UPDATE "users" SET "last_sign_in_at" = $1, "current_sign_in_at" = $2, "last_sign_in_ip" = $3, "current_sign_in_ip" = $4, "sign_in_count" = $5, "updated_at" = $6 WHERE "users"."id" = $7 [["last_sign_in_at", "2016-08-03 03:31:22.804259"], ["current_sign_in_at", "2016-08-03 03:31:22.804259"], ["last_sign_in_ip", "127.0.0.1/32"], ["current_sign_in_ip", "127.0.0.1/32"], ["sign_in_count", 1], ["updated_at", "2016-08-03 03:31:22.805380"], ["id", 30]] 
    (1.2ms) COMMIT 

Danke für Ihre Hilfe !!

ps: build war kein kluger Name für eine Tabelle Ich denke, ...

Thomas

Antwort

0

Das Problem besteht darin, dass Benutzer zuerst gespeichert und dann gespeichert Sie bauen für Beziehung Zweck können Sie sparen User_id Tabelle statt des Sparens build_ID an Benutzer sollte

+0

Dank zu machen. Das könnte es sein. Irgendeine Idee, wie ich alles auf einmal speichern kann? – apwn

+0

Sie halten Ihr wirkliches Modell spannend und fragen nach Antworten Sie müssen alle drei Modelle teilen und was Sie klar erreichen wollen. Dann könnte ich helfen. –

0
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, build_attributes: [:id, :template_id, :domain_url]) 

build_attributes hat :id

zu bauen

ein Test

def create 
    user = User.new(sign_up_params) 
    user.save 
end 
+0

Danke Breno. Es funktioniert jedoch nicht, da es die ID aus dem Formular nicht erhält. Ich denke, es speichert den Benutzer zuerst und hat nicht die Build-ID. 'Parameter: { "UTF-8"=> "✓", "authenticity_token"=> "Atu7B4voCs8T1Rtz82zc3MRABSUfqQa9374ogg1WVBL5W0Kicc9DLrigggOuVJL + rb0FXjHJ5Yu5Bvfo05 + NXA ==", "user"=> { "first_name"=> "ophk", "last_name"=> "kddkd", "email" => "[email protected]", "passwort" => "[FILTERED]", "password_confirmation" => "[FILTERED]", "build_attributes" => {"template_id" => "1", "domain_url" => "khljgjjff.com"}}, "commit" => "Registrieren"} ' – apwn

+0

Aber fügen Sie eine binding.pry ou debug ein, um den Benutzer zu verifizieren.Fehler 'zu identifizieren, das Objekt erstellt hat oder mit Fehlern –

+1

Verwendung von binding.pry ist eine nette Idee, aber was ist das Problem bereits erkannt. Problem ist, dass Benutzer zuerst gespeichert und dann Build, aber er will ID in Benutzer-Tabelle erstellen. Was nicht möglich ist. –

0
Modell User.rb
has_one :build 
accepts_nested_attributes_for :build, allow_destroy: true 
Schienen Konsole
user = User.new(name: 'example', build_attributes:{template_id:1, domain_url: 'test'}) 

user.save # this will create user and after that will create has_one build association 
user.errors unless user.save