rails 关联:用户必须存在问题
Posted
技术标签:
【中文标题】rails 关联:用户必须存在问题【英文标题】:rails associations: user must exists issue 【发布时间】:2021-07-20 19:16:56 【问题描述】:我正在关注这个tutorial,我正在开发一个应用程序,每个用户都有自己的植物列表。所以两张表:
表 A:植物:植物名称:字符串,温度:浮动,湿度:浮动,... 表 B:设计用户:默认参数来自 devise。最初,表格 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 %>
仅供参考,这显示了尝试创建新工厂的用户的正确 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 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)
【问题讨论】:
【参考方案1】:我认为这里只是有些简单的混淆。
当您键入belongs_to :user
时,rails 假定(按照惯例)该表有一个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
属于User
类,以便它知道要加入哪个表以及在返回对象时要实例化哪个模型。
现在你有了plant.creator #=> <#User ...>
,我认为这是一个更自然的阅读方式。
需要对has_many
关联进行其他类似的修改。
文档: belongs_to has_many
【讨论】:
以上是关于rails 关联:用户必须存在问题的主要内容,如果未能解决你的问题,请参考以下文章