使用Rails 5,当我尝试保存这两个模型之间的关联时,我遇到了一个问题:用户和提供商
我的模特:
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
控制器:
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
表格:
= simple_form_for @provider do |f|
= f.error_notification
= f.input :name, required: false
= f.button :submit
在创建操作上,创建了一个新提供程序,但它未链接到当前用户。 (连接表中没有数据插入)
我不知道为什么会有这种行为。 在控制台中,如果我做了类似的事情:
@user = User.create(email: "user@test.com", password: "password")
@provider = @user.providers.create(name: "Provider1", status: "name")
@provider.save
然后正确保存关联。
> @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">]>
感谢您的任何想法!
有关信息,我的架构:
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
这是日志
È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 :(得分:1)
我知道也许这不是最好的解决方案,但它是我想到的最快的
def create
@provider = current_user.providers.create(provider_params)
if @provider.id
redirect_to root_path
else
render :new
end
end
这将创建连接表记录,当你只使用new时,为什么在属于if的情况下提供者属于用户并且在迁移中有user_id current_user.providers.new将在新实例中添加user_id,以防有和属于许多你可以这样做,也许有更好的方法,但这是我首先想到的。
或类似的东西
def create
@provider = Provider.new(provider_params)
if @provider.save
current_user.providers << @provider
redirect_to root_path
else
render :new
end
end
还有一行,但我觉得看起来更干净。
答案 1 :(得分: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
我建议使用has_many through
关系而不是has_many_and_belongs_to
,因为您可以查询连接表,如果需要,可能会在此连接表中添加更多列。
P.S。这对我来说就像一个Rails bug /功能改进。不再需要@provider.users = [current_user]
,因为@provider = current_user.providers.new(provider_params)
已经可以推断出@provider
对象已经与current_user
相关联,因此应该已经自动分配了has_many
。这已经适用于itertools
。似乎仅在HABTM中它不会自动分配。