更新方法不更新用户对象,参数或 form_for 没有问题?

Update method not updating user object, no issue with params or form_for?

我正在通过构建论坛网站来学习 rails,并且有两个主要模型:用户和主题。他们通过第三个模型 subscribed_topic 使用 has_many_through 建立多对多关系。

在用户展示中,我有以下 form_for,允许用户通过复选框选择 select 主题。我正在尝试使用它来将 selected 主题保存给特定用户。

<%= form_for @user do |f| %> 
<%= f.collection_check_boxes(:topic_ids, 
Topic.all.sample(50).each, :id, :topic_name) %> 
<%= f.submit %>
<% end %>

我的用户控制器中有这个更新方法,在提交表单时调用。

def update
  @user = User.find(params[:id])
  if @user.update_attributes(user_params)
    flash[:success] = "Success!"
  else
    flash[:warning] = "Failed!"
  end
end

这些是我的用户参数:

def user_params
  params.require(:user).permit(
  :name, :email, :password,
  :password_confirmation, topic_ids: [])
end

这些是供参考的各自架构:

create_table "subscribed_topics", force: :cascade do |t|
  t.integer  "user_id"
  t.integer  "topic_id"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

create_table "topics", force: :cascade do |t|
  t.string   "topic_name"
  t.integer  "user_id"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.index ["user_id"], name: "index_topics_on_user_id"
end

create_table "users", force: :cascade do |t|
  t.string   "name"
  t.string   "email"
  t.datetime "created_at",      null: false
  t.datetime "updated_at",      null: false
  t.string   "password_digest"
  t.index ["email"], name: "index_users_on_email", unique: true
end

编辑:我将 topic_ids: [] 添加到我的用户参数中,但更新没有完成。

日志显示:

User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
 (0.1ms)  begin transaction
Topic Load (0.2ms)  SELECT "topics".* FROM "topics" WHERE "topics"."id" = 41 ORDER BY "topics"."created_at" DESC
Topic Load (0.2ms)  SELECT "topics".* FROM "topics" INNER JOIN "subscribed_topics" ON "topics"."id" = "subscribed_topics".
"topic_id" WHERE "subscribed_topics"."user_id" = ? ORDER BY "topics"."created_at" DESC  [["user_id", 1]]
SQL (0.4ms)  INSERT INTO "subscribed_topics" ("user_id", "topic_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["user_id", 1], ["topic_id", 41], ["created_at", "2019-03-03 19:49:43.212973"], ["updated_at", "2019-03-03 19:49:43.212973"]]
User Exists (0.1ms)  SELECT  1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER(?) AND ("users"."id" != ?) LIMIT ?  [["email", "user.email@gmail.com"], ["id", 1], ["LIMIT", 1]]

(0.3ms)  rollback transaction

编辑:用户和主题模型验证

用户的验证是:

validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
validates :password, presence: true, length: { minimum: 6 }

主题中唯一的验证是:

validates :topic_name, presence: true, length: {maximum: 255}

编辑:特定验证错误来自用户模型

Validation failed: Password can't be blank, Password is too short (minimum is 6 characters)

我不明白为什么通过这个主题集合会触发密码验证并通过姓名和电子邮件验证,但为此我会问一个新问题。

你的参数 missiong topic_ids 你可以像下面的示例代码一样添加它

def user_params
  params.require(:user).permit(
  :name, :email, :password,
  :password_confirmation, topic_ids: [])
end

编辑:

我认为您的更新控制器已经正确,您可以使用其他供用户选择主题的替代方案collection_select

 <%= f.collection_select :topic_ids, Topic.all.sample(50), :id, :topic_name, {}, { multiple: true } %>