我正在尝试将用户编辑页面(app/views/devise/registrations/edit.html.erb(拆分为2个页面以获得更好的UI,例如:
/settings
/settings/profile
我对 Rails 相当陌生,做了 Michael Hartl 的教程,并阅读了更多我拿到手的东西,只是构建我的第一个应用程序,即使我有一些 php 的经验
这是我尝试拆分为 2 的视图,它是 Devise gem 提供的视图(app/views/devise/registrations/edit.html.erb(
<h2>Login Details</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
<%= devise_error_messages! %>
<%# sensitive info %>
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %>
....
<%= f.label :current_password %> <i>(to confirm changes)</i><br />
<%= f.password_field :current_password, autocomplete: "off" %>
<h2>Profile Details</h2>
<%# non-sensitive info %>
<%= f.label :name %><br />
<%= f.text_field :name %>
<%= f.submit "Update" %>
<% end %>
它使用自定义注册控制器(app/controllers/registrations_controller.rb(
class RegistrationsController < Devise::RegistrationsController
def update
....
end
end
此外,可通过以下路线访问此视图:
edit_user GET /users/:id/edit(.:format) users#edit
我的主要问题是,如何将此页面拆分为 2:
- /包含登录详细信息的设置 /
- 设置/包含个人资料详细信息的配置文件
并且都由同一控制器或同一操作处理
我是否需要创建一个新的控制器/路由/视图,例如:
- 控制器:设置配置文件
- 路由:获取"设置/配置文件" => "settings_profile#新">
- 查看:应用/视图/settings_profile/新建.html.erb
如果是这样,我如何传递视图"资源"信息或任何事实信息:
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
在这一点上,事情很模糊,请耐心等待我
一个单独的控制器,特别是因为你已经扩展了默认的Devise RegistrationsController,它已经可以很好地更新用户属性。
编辑:如果这些不仅仅是扩展的用户属性,并且profile
是具有自己的逻辑和行为的自己的对象,请考虑创建自己的控制器来管理该对象的 CRUD。
如果您使用 devise 的用户/编辑页面作为第一部分,您需要做的就是在自定义控制器中添加一个profile
操作,并创建一个视图文件来配合它。
# this is all that's in the edit action from Devise
def edit
render :edit
end
# add this to your custom RegistrationsController
def profile
render :profile
end
然后,您可以摆弄您的路由(请参阅此处和此处(,直到它们将要使用的 URL 路由到正确的控制器:
# you probably have this, which covers your current user/edit route
devise_for :users
# but you can add this to extend these routes
devise_scope :user do
# will route /profile to the profile action on User::RegistrationsController
get :profile, to: 'users/registrations'
# or if you want more control over the specifics
get 'users/settings/profile', to: 'users/registrations#profile', as: :user_profile
end
对于第二个视图/窗体以从另一个非设计控制器更新用户属性,您可以使用form_for current_user, { url: user_registration_path }
如果确实要使用资源,则必须将其添加到注册控制器的顶部,以便资源也在配置文件操作中定义:
prepend_before_filter :authenticate_scope!, only: [:edit, :profile, :update, :destroy]
查看 devise 有关强参数的文档,了解如何确保要添加到用户的任何其他属性都被您的自定义RegistrationsController
列入白名单。
正如您所建议的,一种方法是创建一个新的控制器、路由和视图来处理这个问题。
我可能会创建一个具有两个操作的UserProfilesController
控制器:UserProfilesController#show
和 UserProfilesController#edit
。
然后正如您所建议的,一条路线,例如,
get 'user_profiles/:id' => 'user_profiles#show'
get 'user_profiles/:id/edit' => 'user_profiles#edit'
在Devise的说法中,resource
指的是用户。因此,上面传递的:id
当然必须是User
id。如果您不想这样做,您可以随时假设您指的是current_user
在这种情况下,您可以跳过在路由中使用:id
,而只需通过 current_user.id
在控制器中检索它。
最后,您只需要从 Devise 视图中拆分出配置文件详细信息,并在 app/views/user_profiles/new.html.erb
下创建一些类似的edit.html.erb
。请记住从 Devise 视图中删除配置文件位,我认为您正在路上。
附录
@AmrNoman提出了一个很好的建议:更新方法。如果您按照我的解决方案进行操作,您将在routes.rb
文件中添加另一个操作UserProfilesController#update
和一个新路由:
put 'user_profiles/:id/update' => 'user_profiles#update'
此外,如果您打算稍后重构User
以删除配置文件详细信息并在单独的模型中处理它们,则谨慎的做法可能是将我在上述代码中对:id
的引用替换为:user_id
。这样,如果您在某个时候创建一个名为UserProfile
的模型,那么:id
不是UserProfile#id
而是外键UserProfile#user_id
会更清楚。这将使你能够使用:id
直接引用UserProfile.id
,而不会影响应用中的任何 API 使用者。
这可能有点矫枉过正,但我认为这是很好的做法。
克里斯·卡梅隆的回答是对的,但我认为这更接近你想要的:
首先在routes.rb中创建路由:
# this gets the edit page for login details
get "settings" => "user_profiles#edit_credentials", as: "edit_credentials"
# this gets the edit page for other profile info
get "settings/edit" => "user_profiles#edit_profile", as: "edit_profile"
# update method shared by both forms
# (you can create another one to handle both forms separately if you want)
put "settings" => "user_profiles#update"
然后您的控制器user_profiles_controller.rb:
class UserProfilesController < ApplicationController
# fill the methods as you need, you can always get the user using current_user
def edit_credentials
end
def edit_profile
end
def update
end
end
最后,您的视图,首先 views/user_profiles/edit_credentials.erb.html,在这里显示登录详细信息的表单:
<%= form_for(current_user, url: settings_path) do |f| %>
<% end %>
然后在 views/user_profiles/edit_profile.erb.html 中同样的事情,只需更改表单内容:
<%= form_for(current_user, url: settings_path) do |f| %>
<% end %>
可能会有一些错误,但希望这能让您朝着正确的方向前进(还要确保处理身份验证和授权(。