2017-07-25 5 views
1

Mit Rails 5, Ich habe ein Problem, wenn ich versuche, meine Verbindung zwischen diesen zwei Modellen zu speichern: User und ProviderVerband nicht zwischen zwei Modellen speichert

Meine Modelle:

class User < ApplicationRecord 
    # Relations 
    has_and_belongs_to_many :providers 
end 


class Provider < ApplicationRecord 
    # Relations 
    has_and_belongs_to_many :users 
    accepts_nested_attributes_for :users 
end 

der Controller:

class ProvidersController < ApplicationController 
    def new 
    @provider = current_user.providers.new 
    end 

    def create 
    @provider = current_user.providers.new(provider_params) 
    if @provider.save 
     redirect_to root_path 
    else 
     render :new 
    end 
    end 

    private 

    def provider_params 
     params[:provider][:status] = 'name' 
     params.require(:provider).permit(:name, :status) 
    end 

Form:

= simple_form_for @provider do |f| 
    = f.error_notification 
    = f.input :name, required: false 
    = f.button :submit 

Bei der Erstellungsaktion wird ein neuer Anbieter erstellt, der jedoch nicht mit dem aktuellen Benutzer verknüpft ist. (in der Join-Tabelle sind keine Daten eingetragen)

Ich habe keine Ahnung, warum ich dieses Verhalten habe. In Konsole, wenn ich so etwas wie:

@user = User.create(email: "[email protected]", password: "password") 
@provider = @user.providers.create(name: "Provider1", status: "name") 
@provider.save 

dann wird der Verein korrekt gespeichert.

> @user.providers 
=> #<ActiveRecord::Associations::CollectionProxy [#<Provider id: 17, name: "Provider1", status: "name", created_at: "2017-07-25 09:37:19", updated_at: "2017-07-25 09:37:19">]> 

Vielen Dank für eine Idee!

Für Informationen, mein Schema:

create_table "providers", force: :cascade do |t| 
    t.string "name" 
    t.string "status" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
end 

create_table "providers_users", id: false, force: :cascade do |t| 
    t.bigint "provider_id", null: false 
    t.bigint "user_id", null: false 
    t.index ["provider_id", "user_id"], name: "index_providers_users_on_provider_id_and_user_id" 
    t.index ["user_id", "provider_id"], name: "index_providers_users_on_user_id_and_provider_id" 
end 

create_table "users", force: :cascade do |t| 
    t.string "email", default: "", null: false 
    t.string "encrypted_password", default: "", null: false 
    t.string "reset_password_token" 
    t.datetime "reset_password_sent_at" 
    t.datetime "remember_created_at" 
    t.integer "sign_in_count", default: 0, null: false 
    t.datetime "current_sign_in_at" 
    t.datetime "last_sign_in_at" 
    t.inet "current_sign_in_ip" 
    t.inet "last_sign_in_ip" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    t.index ["email"], name: "index_users_on_email", unique: true 
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true 
end 

Hier ist das Protokoll

ÈStarted POST "/providers" for 127.0.0.1 at 2017-07-25 11:49:27 +0200 
    Processing by ProvidersController#create as HTML 
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"27O2Tz4bbqhfRmcuq+0DIZMebSaYVc6IO/uy889Z48fF1l3c8GfIZ+WcQvZKfUeEIB5+YbrM9dON2RH47p3TIQ==", "provider"=>{"name"=>"My new provider"}, "commit"=>"Sauvegarder"} 
    User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 5], ["LIMIT", 1]] 
    (0.2ms) BEGIN 
    SQL (0.4ms) INSERT INTO "providers" ("name", "status", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["name", "My new provider"], ["status", "name"], ["created_at", "2017-07-25 09:49:27.837165"], ["updated_at", "2017-07-25 09:49:27.837165"]] 
    (4.0ms) COMMIT 
    Redirected to http://localhost:3000/providers/18/steps.location 
    Completed 302 Found in 12ms (ActiveRecord: 5.0ms) 


    Started GET "/providers/18/steps.location" for 127.0.0.1 at 2017-07-25 11:49:27 +0200 
    Processing by Providers::StepsController#index as 
    Parameters: {"provider_id"=>"18"} 
    Redirected to http://localhost:3000/providers/18/steps/registration 
    Completed 302 Found in 2ms (ActiveRecord: 0.0ms) 


    Started GET "/providers/18/steps/registration" for 127.0.0.1 at 2017-07-25 11:49:27 +0200 
    Processing by Providers::StepsController#show as HTML 
    Parameters: {"provider_id"=>"18", "id"=>"registration"} 
    Provider Load (0.3ms) SELECT "providers".* FROM "providers" WHERE "providers"."id" = $1 LIMIT $2 [["id", 18], ["LIMIT", 1]] 
    Rendering providers/steps/registration.html.haml within layouts/provider 
    User Load (0.3ms) SELECT "users".* FROM "users" INNER JOIN "providers_users" ON "users"."id" = "providers_users"."user_id" WHERE "providers_users"."provider_id" = $1 [["provider_id", 18]] 
    Rendered providers/steps/registration.html.haml within layouts/provider (13.2ms) 
    Rendered shared/_head.html.haml (30.6ms) [cache miss] 
    User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 5], ["LIMIT", 1]] 
    Rendered shared/_header.html.haml (9.7ms) [cache miss] 
    Completed 200 OK in 69ms (Views: 64.7ms | ActiveRecord: 1.1ms) 
+0

Zeigen Sie uns Ihre Protokolle, die generiert werden, wenn das Senden ausgelöst wird. – Pavan

+0

@Pavan bitte zeigen Sie mein Protokoll, die Weiterleitung ist ein bisschen anders. Vielen Dank ! – benoitr

+0

Halten Sie an! Gemäß Ihrem Formular und dem Controller senden Sie nur Eingaben für Provider! – Pavan

Antwort

1

Ich weiß, vielleicht ist es nicht die beste Lösung ist, aber es ist die schnellste, die

mir in den Sinn kommt
def create 
    @provider = current_user.providers.create(provider_params) 
    if @provider.id 
     redirect_to root_path 
    else 
     render :new 
    end 
    end 

Dies wird Join-Tabelle Datensatz erstellen, wenn Sie nur neue verwenden, warum dies funktioniert im Falle von gehört, wenn Provider gehört zu user und hat user_id in der migration current_user.providers.new wird user_id in der neuen instanz hinzufügen, für den fall hat und gehört zu vielen kannst du es so machen, vielleicht gibt es einen besseren weg aber das ist, was mir zuerst kam.

oder so etwas wie dieses

def create 
    @provider = Provider.new(provider_params) 
    if @provider.save 
     current_user.providers << @provider 
     redirect_to root_path 
    else 
     render :new 
    end 
    end 

eine weitere Zeile, aber ich denke, sieht sauberer.

+0

Was versuchst du zu sagen? – Pavan

+0

Ich habe versucht, diese Lösung auf meinem Projekt und hatte Ergebnis, dass OP erwartet, dass es erstellt in einer Linie Anbieter und auch beitreten Tabelle Anbieter und Benutzer. –

+0

Diese Lösung funktioniert, Sedad :) Meiner Meinung nach ist es ein bisschen komisch. Ich warte etwas, wenn es eine bessere Lösung gibt. Vielen Dank ! – benoitr

1
def create 
    @provider = current_user.providers.new(provider_params) 
    @provider.users = [current_user] 
    if @provider.save 
    redirect_to root_path 
    else 
    render :new 
    end 
end 

Ich schlage vor, eine has_many through Beziehung statt has_many_and_belongs_to verwenden, weil Sie die Join-Tabelle abfragen können, und möglicherweise einige weitere Spalten in der Zukunft in dieser Tabelle beitreten hinzufügen, sollte die Notwendigkeit entstehen.

P.S. Das fühlt sich für mich wie eine Rails Bug/Feature Verbesserung an. @provider.users = [current_user] sollte nicht mehr benötigt werden, da @provider = current_user.providers.new(provider_params) bereits abgeleitet werden kann, dass das Objekt @provider bereits mit current_user verknüpft ist und daher automatisch bereits zugewiesen werden sollte. Dies funktioniert bereits mit has_many. Scheint nur hier in HABTM, dass es nicht automatisch zuweist.

Verwandte Themen