所以,我是RoR4的初学者,我以为我会参加一个练习项目。我正在使用Devise作为用户模型,我继续为它添加一个Profile模型:
class User < ActiveRecord::Base
has_one :profile, dependent: :destroy
before_create :build_profile # Creates profile at user creation
accepts_nested_attributes_for :profile
...
end
和
class Profile < ActiveRecord::Base
belongs_to :user
validates :user_id, presence: true
end
配置/ routes.rb中:
devise_for :users, controllers: { sessions: 'users/sessions', registrations: 'users/registrations' }
resources :users, only: [:index, :show, :destroy]
resources :profiles, only: [:update]
namespace :admin do
root "base#index"
resources :users
end
authenticated do
root to: 'pages#menu', as: :authenticated
end
我基本上希望允许在Devise生成的相同Edit窗体中编辑配置文件。所以我把它添加到application_controller:
def configure_permitted_parameters
...
devise_parameter_sanitizer.for(:account_update) do |u| u.permit(
:email,
:password,
:password_confirmation,
:current_password,
:name,
profile_attributes: [:birthday, :phone, :address, :about, :restrictions, :avatar]
)
end
end
我按照this page on Devise's wiki上的说明限制仅在电子邮件和密码更改时要求输入密码,如下所示:
def update
@user = User.find(current_user.id)
successfully_updated = if needs_password?(@user, params)
@user.update_with_password(devise_parameter_sanitizer.sanitize(:account_update))
else
# remove the virtual current_password attribute
# update_without_password doesn't know how to ignore it
params[:user].delete(:current_password)
@user.update_without_password(devise_parameter_sanitizer.sanitize(:account_update))
end
if successfully_updated
set_flash_message :notice, :updated
# Sign in the user bypassing validation in case his password changed
sign_in @user, :bypass => true
redirect_to after_update_path_for(@user)
else
render "edit"
end
end
private
# check if we need password to update user data
# ie if password or email was changed
# extend this as needed
def needs_password?(user, params)
user.email != params[:user][:email] ||
params[:user][:password].present?
end
然后我更新了嵌套表单,一切都按预期进行,直到我在更改电子邮件或密码时尝试不提供旧密码。我收到了通知消息,但与Profile
相关联的User
只是转向了nil
,而且它已经消失了。这是服务器日志消息:
Processing by Users::RegistrationsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"L1i+uV0LFvyVs3xLOMYUJyqeZLnFSWV6R0igyG4+W7E=", "user"=>{"name"=>"Foo Bar1", "profile_attributes"=>{"birthday"=>"", "phone"=>"", "address"=>"", "about"=>"Lorem ipsum dolor", "restrictions"=>"", "avatar"=>"", "id"=>"13"}, "email"=>"user@example.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "current_password"=>"[FILTERED]"}, "commit"=>"Update"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 2 ORDER BY "users"."id" ASC LIMIT 1
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]]
Unpermitted parameters: id
Profile Load (0.2ms) SELECT "profiles".* FROM "profiles" WHERE "profiles"."user_id" = ? ORDER BY "profiles"."id" ASC LIMIT 1 [["user_id", 2]]
(0.1ms) begin transaction
SQL (0.4ms) DELETE FROM "profiles" WHERE "profiles"."id" = ? [["id", 13]]
(13.4ms) commit transaction
User Exists (0.5ms) SELECT 1 AS one FROM "users" WHERE ("users"."email" = 'user@example.com' AND "users"."id" != 2) LIMIT 1
User Exists (0.6ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."username") = LOWER('user1') AND "users"."id" != 2) LIMIT 1
有什么可能出错的建议吗?如何解决?
更新
重新阅读@RichPeck和@KirtiThorat的整个讨论,特别是服务器日志,我设法通过添加配置文件ID作为Devise&中允许的参数之一来解决重新创建配置文件对象和删除旧配置文件的问题。 #39; s :account_update
清洁剂,如下:
devise_parameter_sanitizer.for(:account_update) do |u| u.permit(
:email,
:password,
:password_confirmation,
:current_password,
:name,
profile_attributes: [:id, :birthday, :phone, :address, :about, :restrictions, :avatar]
)
end
我不知道这对安全性的影响是什么,所以我仍然会感谢您的反馈。
答案 0 :(得分:0)
首先,如果您设置了Devise以允许用户在不提供密码的情况下编辑其帐户,那么您需要从视图中删除current_password
字段以及configure_permitted_parameters
方法。
def configure_permitted_parameters
...
devise_parameter_sanitizer.for(:account_update) do |u| u.permit(
:email,
:password,
:password_confirmation,
## :current_password, ## REMOVE THIS LINE
:name,
profile_attributes: [:birthday, :phone, :address, :about, :restrictions, :avatar]
)
end
end
通过指定current_password
,您允许account_update
进行批量分配。
<强>更新强>
class User < ActiveRecord::Base
has_one :profile, dependent: :destroy, inverse_of :user
before_create :build_profile # Creates profile at user creation
accepts_nested_attributes_for :profile
...
end
class Profile < ActiveRecord::Base
belongs_to :user, inverse_of :profile
validates :user_id, presence: true
end