我正在关注Railscast#235 Devise和OmniAuth。我不明白如何从表单中动态隐藏password和password_confirmation的表单字段。
在表单上,行f.object.password_required?
评估是否包含该密码字段(并且password_required?
方法也用于覆盖验证)。 但是,f.object
的设置方式和位置是什么?
据我了解代码,用户点击"通过Twitter注册"。然后设置会话,存储Twitter OmniAuth信息,并将用户重定向到Devise Registration页面。某种程度上" f.object"设置了,password_required?方法在它上面运行。如果f.object
不需要密码,则会隐藏字段。
f.object
如何设定?
我已经包含了Railscast中的相关代码。
用户对象
class User < ActiveRecord::Base
# Apply OmniAuth hash to model
def self.from_omniauth(auth)
where(auth.slice(:provider, :uid)).first_or_create do |user|
user.provider = auth.provider
user.uid = auth.uid
user.username = auth.info.nickname
end
end
# Override Devise hook
def self.new_with_session(params, session)
if session["devise.user_attributes"]
new(session["devise.user_attributes"], without_protection: :true) do |user|
user.attributes = params
user.valid?
end
else
super
end
end
# Override Devise password_required?
def password_required?
super && provider.blank?
end
end
OmniauthCallbacks控制器
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def all
user = User.from_omniauth(request.env["omniauth.auth"])
if user.persisted?
sign_in_and_redirect user
else
session["devise.user_attributes"] = user.attributes
redirect_to new_user_registration_url
end
end
alias_method :twitter, :all
end
设计注册视图
<h2>Sign up</h2>
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :username, required: true, autofocus: true %>
<%= f.input :email %>
<% if f.object.password_required? %>
<%= f.input :password, required: true %>
<%= f.input :password_confirmation, required: true %>
<% end %>
</div>
<div class="form-actions">
<%= f.button :submit, "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>