Я работаю над Railscast при внедрении Devise и OmniAuth (вместе с Devise документация) - в настоящее время у меня есть сайт, где посетители могут зарегистрироваться с помощью своих учетных записей facebook или заполнив форму.
У меня возникают проблемы, когда пользователи, которые подписываются через OmniAuth, пытаются изменить свои профили. Devise ищет текущий пароль пользователя при отправке изменений в свои профили, но те, которые вошли в систему с 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. В учебном пособии предлагается удобный пароль для пароля? метод поможет мне достичь этого результата. В частности, добавление этого метода в пользовательскую модель означает, что он должен возвращать true только в том случае, если пользователь не зарегистрировался через OmniAuth (в этом случае атрибут провайдера будет равен нулю):
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? метод возвращает false, как при регистрации пользователем через OmniAuth, так и через обычную регистрацию сайта. Даже когда я меняю его, чтобы просто запустить метод суперкласса, он возвращает false.
Любые идеи о том, что происходит с методом password_required? Я ничего не могу найти об этом в любом месте, но я чувствую, что это то, что сейчас срабатывает.
Обновление:
Это работает, но не использует метод, описанный в Railscast, который полагается на require_password? метод, тема, о которой я до сих пор ничего не знаю. Вместо этого я внедрил решение здесь, как было предложено здесь. Поэтому теперь мне требуется только пароли для обновления учетных записей без OmniAuth с кодом:
class Users::RegistrationsController < Devise::RegistrationsController
def update
@user = User.find(current_user.id)
email_changed = @user.email != params[:user][:email]
is_facebook_account = [email protected]?
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