ruby-on-rails - 使用 Devise 和 Omniauth 编辑用户

标签 ruby-on-rails devise ruby-on-rails-3.2 omniauth

我正在通过 Railscast 实现 Devise 和 OmniAuth(以及 Devise documentation)——目前,我有一个网站,访问者可以使用他们的 Facebook 帐户或填写表格进行注册。
但是,当通过 OmniAuth 注册的用户尝试编辑他们的个人资料时,我遇到了麻烦。当用户提交对其个人资料的更改时,设计会查找用户的当前密码,但那些使用 facebook 登录的人不知道他们的密码(它们在用户模型中自动设置):

  def self.find_for_facebook_oauth(auth, signed_in_resource=nil)
    user = User.where(:provider => auth.provider, :uid => auth.uid).first
    unless user
      user = User.create(first_name:auth.extra.raw_info.first_name,
                         last_name:auth.extra.raw_info.last_name,
                           provider:auth.provider,
                           uid:auth.uid,
                           email:auth.info.email,
                           password:Devise.friendly_token[0,20]
                           )
    end
    user
  end
当用户编辑他的信息时,如果他通过 OmniAuth 设置他的帐户,应用程序应该不需要密码确认。该教程建议使用方便的 password_required?方法将帮助我实现这个结果。具体来说,将这个方法添加到用户模型意味着它应该只在用户没有通过 OmniAuth 注册时才返回 true(在这种情况下 provider 属性将为 nil):
def password_required?
  super && provider.blank?
end
因此,一段代码如下:
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
  <%= devise_error_messages! %>
    <%= render :partial => "essential_user_info_inputs", :locals => { :f => f } %>
    <%= render :partial => "inessential_user_info_inputs", :locals => { :f => f } %>
    <% if f.object.password_required? %> 
        <%= render :partial => "password_inputs", :locals => { :f => f } %>
        <%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
        <%= f.password_field :current_password %>
    <% end %>
  <%= f.submit "Update" %>
<% end %>
理论上只会在需要时显示密码输入。它还表明,Devise 内置了逻辑,说 OmniAuth 用户不需要使用密码来编辑他们的帐户。我不知道这是否属实,但教程看起来像那样。但是当 OmniAuth 用户尝试编辑他的帐户时,我收到“当前密码不能为空”。与非 OmniAuth 用户相同(这是有道理的,因为密码字段也不会显示在这些用户的编辑页面上)。
一些探查确认password_required?方法在用户通过 OmniAuth 和网站的常规用户注册时都返回 false。即使我将其更改为简单地运行父类(super class)方法,它也会返回 false。
关于 password_required 方法发生了什么的任何想法?我在任何地方都找不到关于它的任何信息,但我觉得这就是现在绊倒事情的原因。
更新:
这现在有效,但不使用 Railscast 中概述的方法,该方法依赖于 requires_password?方法,一个我仍然一无所知的话题。相反,我实现了概述 here 的解决方案,如建议 here .所以我现在只需要密码来使用代码更新非 OmniAuth 帐户:
class Users::RegistrationsController < Devise::RegistrationsController
def update
    @user = User.find(current_user.id)
    email_changed = @user.email != params[:user][:email]
    is_facebook_account = !@user.provider.blank?

    successfully_updated = if !is_facebook_account
      @user.update_with_password(params[:user])
    else
      @user.update_without_password(params[:user])
    end

    if successfully_updated
      # Sign in the user bypassing validation in case his password changed
      sign_in @user, :bypass => true
      redirect_to root_path
    else
      render "edit"
    end
  end
end

最佳答案

最简单的方法是覆盖 RegistrationsController 中的 update_resource 方法。 .这是由设计在他们自己的 Controller 实现中建议的:

  # By default we want to require a password checks on update.
  # You can overwrite this method in your own RegistrationsController.
  def update_resource(resource, params)
    resource.update_with_password(params)
  end

所以解决方案是在你自己的 Controller 中覆盖这个方法,如下所示:
class Users::RegistrationsController < Devise::RegistrationsController

  # Overwrite update_resource to let users to update their user without giving their password
  def update_resource(resource, params)
    if current_user.provider == "facebook"
      params.delete("current_password")
      resource.update_without_password(params)
    else
      resource.update_with_password(params)
    end
  end

end

关于ruby-on-rails - 使用 Devise 和 Omniauth 编辑用户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13436232/

相关文章:

mysql - rails 3.1 - 将数据从本地数据处理服务器移动到 heroku 生产服务器

ruby-on-rails - 通过 sprockets 动态渲染一个 sass 文件

ruby-on-rails - rails 模型 : includes method on self

ruby-on-rails - 比我目前正在做的更好的错误处理?

ruby-on-rails - 如何以敏捷的方式部署 Web 应用程序

ruby-on-rails - 添加您自己的自定义路线来设计

ruby-on-rails - 设计对基于 Rails 的 Web 服务有意义吗?

ruby-on-rails - 目录 : Forgot Password & Sign In - in same page

mysql - 如何向依赖于另一个模型的 Rails 模型添加验证

ruby-on-rails - 嵌套 Controller 和子文件夹的 Rails 3 路由