rails 关联:用户必须存在问题
rails associations: user must exists issue
我正在关注这个 tutorial 并且我正在开发一个应用程序,每个用户都有自己的植物列表。所以两个 tables:
- Table A : 植物 : plant_name:string, temp:float, humidity:float, ...
- Table B:设计用户:默认参数来自 devise。
最初 table PLANTS 没有一列来显示植物是由具有 id 的用户创建的。所以我添加了使用以下步骤:
- 在models/plant.rb中我添加了以下内容:
belongs_to :user
- 在models/user.rb中我添加了下面的
has_many :plants
- 在 GitBash 中:
rails g migration add_created_by_to_plants created_by:integer:index
- 然后在GitBash中推送迁移:
rails db:migrate
所以现在架构如下所示:
ActiveRecord::Schema.define(version: 2021_04_27_111702) do
#Table Plants
create_table "plants", force: :cascade do |t|
t.string "plant_name"
t.float "temperature"
t.float "humidity"
t.float "water"
t.string "light"
t.string "soil"
t.string "location"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "created_by"
t.index ["created_by"], name: "index_plants_on_created_by"
end
#Table User Accounts
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.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, 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
end
我在创建新工厂时更改了前端,以便它可以提交由用户 id 创建的 表单:
<%= form.number_field :created_by, id: :plant_created_by, class:"form-control", value: current_user.id, type: :hidden %>
仅供参考,这显示了尝试创建新 Plant 的用户的正确 ID,并且应用程序按预期工作,直到教程中的 2:42:00! (应该得到用户必须存在的错误,我这样做了)
现在是我出错的部分:
因为 created_by
是在之后创建的,所以我必须让我的 controllers/plants_controller.rb
知道它应该允许传递这个参数 (2:43:00)
- 在
def plant_params
中添加新参数:
def plant_params
params.require(:plant).permit(:plant_name, :temperature, :humidity, :water, :light, :soil, :location, :created_by)
end
但是当我尝试添加一个新工厂时,我仍然得到 User must exist on the front end,终端看起来像这样:
Started POST "/plants" for ::1 at 2021-04-27 15:34:18 +0300
Processing by PlantsController#create as HTML
Parameters: {"authenticity_token"=>"[FILTERED]", "plant"=>{"plant_name"=>"oregano", "temperature"=>"50", "humidity"=>"20.5", "water"=
>"150", "light"=>"Partial Shade", "soil"=>"Any", "location"=>"Anywhere", "created_by"=>"3"}, "commit"=>"Create Plant"}
Rendering layout layouts/application.html.erb
Rendering plants/new.html.erb within layouts/application
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 3], ["LIMIT", 1]]
↳ app/views/plants/_form.html.erb:43
Rendered plants/_form.html.erb (Duration: 5.7ms | Allocations: 1809)
Rendered plants/new.html.erb within layouts/application (Duration: 6.6ms | Allocations: 1892)
[Webpacker] Everything's up-to-date. Nothing to do
Rendered home/_header.html.erb (Duration: 0.2ms | Allocations: 123)
Rendered layout layouts/application.html.erb (Duration: 64.9ms | Allocations: 6287)
Completed 422 Unprocessable Entity in 68ms (Views: 65.9ms | ActiveRecord: 0.2ms | Allocations: 8046)
我认为这里只是有些简单的混淆。
当您键入 belongs_to :user
时,rails 假定(按照惯例)table 有一个 user_id
列,并且这将用于关联 Plant
-> User
.
由于 rails 推断约定并且由于 plant.attributes['user_id'] #=> nil
,当 rails 寻找“用户”时,它实际上是在查询
SELECT
"users".*
FROM
"users"
WHERE
"users"."id" IS NULL
这显然不存在。
在您的情况下,您要关联的列称为 created_by
。默认情况下 rails 无法知道这一点,但您可以将这种偏离惯例的情况告知协会。
class Plant < ApplicationRecord
belongs_to :user, foreign_key: 'created_by'
end
这里我们告诉 rails 关联称为 user
但我们想使用 created_by
列(属性)关联记录。
话虽这么说,但我认为 plant.user
读起来有点笨拙,相反,我们可以对上面的内容做一些小改动,使关联名称 creator
。
class Plant < ApplicationRecord
belongs_to :creator, foreign_key: 'created_by', class_name: 'User'
end
现在协会被称为 creator
但我们需要告诉 rails creator
属于 class User
以便它知道什么 table 连接到什么模型,当它 returns 对象时要实例化什么模型。
现在你有 plant.creator #=> <#User ...>
,我认为这更自然。
需要对 has_many
关联进行其他类似修改。
文档:
belongs_to
has_many
我正在关注这个 tutorial 并且我正在开发一个应用程序,每个用户都有自己的植物列表。所以两个 tables:
- Table A : 植物 : plant_name:string, temp:float, humidity:float, ...
- Table B:设计用户:默认参数来自 devise。
最初 table PLANTS 没有一列来显示植物是由具有 id 的用户创建的。所以我添加了使用以下步骤:
- 在models/plant.rb中我添加了以下内容:
belongs_to :user
- 在models/user.rb中我添加了下面的
has_many :plants
- 在 GitBash 中:
rails g migration add_created_by_to_plants created_by:integer:index
- 然后在GitBash中推送迁移:
rails db:migrate
所以现在架构如下所示:
ActiveRecord::Schema.define(version: 2021_04_27_111702) do
#Table Plants
create_table "plants", force: :cascade do |t|
t.string "plant_name"
t.float "temperature"
t.float "humidity"
t.float "water"
t.string "light"
t.string "soil"
t.string "location"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "created_by"
t.index ["created_by"], name: "index_plants_on_created_by"
end
#Table User Accounts
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.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, 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
end
我在创建新工厂时更改了前端,以便它可以提交由用户 id 创建的 表单:
<%= form.number_field :created_by, id: :plant_created_by, class:"form-control", value: current_user.id, type: :hidden %>
仅供参考,这显示了尝试创建新 Plant 的用户的正确 ID,并且应用程序按预期工作,直到教程中的 2:42:00! (应该得到用户必须存在的错误,我这样做了)
现在是我出错的部分:
因为 created_by
是在之后创建的,所以我必须让我的 controllers/plants_controller.rb
知道它应该允许传递这个参数 (2:43:00)
- 在
def plant_params
中添加新参数:
def plant_params
params.require(:plant).permit(:plant_name, :temperature, :humidity, :water, :light, :soil, :location, :created_by)
end
但是当我尝试添加一个新工厂时,我仍然得到 User must exist on the front end,终端看起来像这样:
Started POST "/plants" for ::1 at 2021-04-27 15:34:18 +0300
Processing by PlantsController#create as HTML
Parameters: {"authenticity_token"=>"[FILTERED]", "plant"=>{"plant_name"=>"oregano", "temperature"=>"50", "humidity"=>"20.5", "water"=
>"150", "light"=>"Partial Shade", "soil"=>"Any", "location"=>"Anywhere", "created_by"=>"3"}, "commit"=>"Create Plant"}
Rendering layout layouts/application.html.erb
Rendering plants/new.html.erb within layouts/application
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 3], ["LIMIT", 1]]
↳ app/views/plants/_form.html.erb:43
Rendered plants/_form.html.erb (Duration: 5.7ms | Allocations: 1809)
Rendered plants/new.html.erb within layouts/application (Duration: 6.6ms | Allocations: 1892)
[Webpacker] Everything's up-to-date. Nothing to do
Rendered home/_header.html.erb (Duration: 0.2ms | Allocations: 123)
Rendered layout layouts/application.html.erb (Duration: 64.9ms | Allocations: 6287)
Completed 422 Unprocessable Entity in 68ms (Views: 65.9ms | ActiveRecord: 0.2ms | Allocations: 8046)
我认为这里只是有些简单的混淆。
当您键入 belongs_to :user
时,rails 假定(按照惯例)table 有一个 user_id
列,并且这将用于关联 Plant
-> User
.
由于 rails 推断约定并且由于 plant.attributes['user_id'] #=> nil
,当 rails 寻找“用户”时,它实际上是在查询
SELECT
"users".*
FROM
"users"
WHERE
"users"."id" IS NULL
这显然不存在。
在您的情况下,您要关联的列称为 created_by
。默认情况下 rails 无法知道这一点,但您可以将这种偏离惯例的情况告知协会。
class Plant < ApplicationRecord
belongs_to :user, foreign_key: 'created_by'
end
这里我们告诉 rails 关联称为 user
但我们想使用 created_by
列(属性)关联记录。
话虽这么说,但我认为 plant.user
读起来有点笨拙,相反,我们可以对上面的内容做一些小改动,使关联名称 creator
。
class Plant < ApplicationRecord
belongs_to :creator, foreign_key: 'created_by', class_name: 'User'
end
现在协会被称为 creator
但我们需要告诉 rails creator
属于 class User
以便它知道什么 table 连接到什么模型,当它 returns 对象时要实例化什么模型。
现在你有 plant.creator #=> <#User ...>
,我认为这更自然。
需要对 has_many
关联进行其他类似修改。
文档: belongs_to has_many