Ruby on Rails / Devise - 将用户编辑页面拆分为2页



我正在尝试将用户编辑页面(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#showUserProfilesController#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 %>

可能会有一些错误,但希望这能让您朝着正确的方向前进(还要确保处理身份验证和授权(。

最新更新