Ruby on rails 3 Rails 3:在创建身份验证时更新用户属性

Ruby on rails 3 Rails 3:在创建身份验证时更新用户属性,ruby-on-rails-3,omniauth,railscasts,Ruby On Rails 3,Omniauth,Railscasts,我遵循Railscasts#235和#236设置了使用omniauth创建用户身份验证。 http://railscasts.com/episodes/236-omniauth-part-2 在用户模型上有两个布尔属性:facebok_share和:twitter_share,我希望在创建新身份验证时将它们设置为true 当我创建一个新用户时,这对我来说是可行的,但是如果一个现有用户添加了一个身份验证,我就无法将布尔值更新为true 当调用apply_omniauth(omniauth)时,它会

我遵循Railscasts#235和#236设置了使用omniauth创建用户身份验证。 http://railscasts.com/episodes/236-omniauth-part-2

在用户模型上有两个布尔属性:facebok_share和:twitter_share,我希望在创建新身份验证时将它们设置为true

当我创建一个新用户时,这对我来说是可行的,但是如果一个现有用户添加了一个身份验证,我就无法将布尔值更新为true

当调用apply_omniauth(omniauth)时,它会在我的用户模型中设置self.facebook_share=true或self.twitter_share=true

我尝试添加一个名为apply_share的新方法,该方法根据提供程序更改布尔值,并尝试调用当前的_user.apply_share(omniauth),但数据库中什么也没有发生

我做错了什么?谢谢

##身份验证控制器

class AuthenticationsController < ApplicationController

  def index
    @title = "Authentications"
    @authentications = current_user.authentications if current_user
  end

  def create
    # creates omniauth hash and looks for an previously established authentication
    omniauth = request.env["omniauth.auth"]
    authentication = Authentication.find_by_provider_and_uid(omniauth['provider'], omniauth['uid'])
    # if previous authentication found, sign in user
    if authentication
      flash[:notice] = "Signed in successfully"
      sign_in_and_redirect(:user, authentication.user)
    #  for users already signed in (current_user), create a new authentication for the user
    elsif current_user
      current_user.apply_share(omniauth)
      current_user.authentications.create(:provider => omniauth['provider'], :uid => omniauth['uid'], :token => (omniauth['credentials']['token'] rescue nil),
                                           :secret => (omniauth['credentials']['secret'] rescue nil))
      flash[:notice] = "authentications successful"
      redirect_to authentications_url
    # new user is created and authentications are built through apply_omniauth(omniauth)
    else
      user = User.new
      user.apply_omniauth(omniauth)
      if user.save
        flash[:notice] = "Signed in successfully"
        sign_in_and_redirect(:user, user)
      # if validations fail to save user, redirects to new user registration page 
      # new twitter authentications redirect so user can enter their password
      else
        session[:omniauth] = omniauth
        redirect_to new_user_registration_url
      end
     end
   end

  def destroy
    @authentication = current_user.authentications.find(params[:id])
    @authentication.destroy
    flash[:notice] = "Successfully destroyed authentication."
    redirect_to authentications_url
  end

end

## user model

 # set share booleans to true depending on 'provider' type
  def apply_share(omniauth)
    case omniauth['provider']
      when 'facebook'
        self.facebook_share = true
      when 'twitter'
        self.twitter_share = true
     end
   end

 # from authentications controller, new user split into type of provider
 def apply_omniauth(omniauth)
   case omniauth['provider']
   when 'facebook'
     self.apply_facebook(omniauth)
   when 'twitter'
     self.apply_twitter(omniauth)
   end
   # builds authentication with provider, uid, token, and secret
   authentications.build(hash_from_omniauth(omniauth))
  end

 protected

 # sets new user attributes from facebook
 def apply_facebook(omniauth)
   self.name = omniauth['user_info']['name']
   self.email = omniauth['user_info']['email'] if email.blank?
   self.facebook_share = true
 end

 # sets new user attributes from twitter 
 def apply_twitter(omniauth)
   if (extra = omniauth['extra']['user_hash'] rescue false)
     # Example fetching extra data. Needs migration to User model:
     # self.firstname = (extra['name'] rescue '')
     self.name = (extra['name'] rescue '')
     self.bio = (extra['description'] rescue '') 
   end
   self.twitter_share = true

 end

 # set authentication attributes to those from 'omniauth' hash
 def hash_from_omniauth(omniauth)
   {
     :provider => omniauth['provider'],
     :uid => omniauth['uid'],
     :token => (omniauth['credentials']['token'] rescue nil),
     :secret => (omniauth['credentials']['secret'] rescue nil)
   }
 end
end


## new methid with :before add => :apply_share
def apply_share(authentication) 
  case authentication['provider'] 
    when 'facebook' 
      self.facebook_share = true 
    when 'twitter'
      self.twitter_share = true 
    end 
  self.save
end
类身份验证控制器omniauth['provider'],:uid=>omniauth['uid'],:token=>(omniauth['credentials']['token']rescue nil),
:secret=>(omniauth['credentials']['secret']rescue nil))
flash[:注意]=“身份验证成功”
将\u重定向到身份验证\u url
#通过apply_omniauth(omniauth)创建新用户并构建身份验证
其他的
user=user.new
user.apply\u omniauth(omniauth)
如果user.save
flash[:notice]=“成功登录”
登录和重定向(:用户,用户)
#如果验证未能保存用户,则重定向到新用户注册页面
#新的twitter身份验证重定向,以便用户可以输入密码
其他的
会话[:omniauth]=omniauth
将\重定向到新\用户\注册\ url
结束
结束
结束
def销毁
@authentication=当前用户.authentications.find(参数[:id])
@身份验证。销毁
flash[:notice]=“已成功销毁身份验证。”
将\u重定向到身份验证\u url
结束
结束
##用户模型
#根据“提供者”类型将共享布尔值设置为true
def应用共享(omniauth)
案例omniauth['provider']
当“脸谱”出现时
self.facebook_share=true
当“推特”
self.twitter_share=true
结束
结束
#从authentications controller,新用户拆分为提供程序类型
def apply_omniauth(omniauth)
案例omniauth['provider']
当“脸谱”出现时
self.apply_facebook(omniauth)
当“推特”
self.apply_twitter(omniauth)
结束
#使用提供程序、uid、令牌和密码构建身份验证
authentications.build(hash_from_omniauth(omniauth))
结束
受保护的
#从facebook设置新的用户属性
def apply_facebook(omniauth)
self.name=omniauth['user_info']['name']
self.email=omniauth['user_info']['email']如果email.blank?
self.facebook_share=true
结束
#从twitter设置新的用户属性
def apply_twitter(omniauth)
if(extra=omniauth['extra']['user\u hash']rescue false)
#获取额外数据的示例。需要迁移到用户模型:
#self.firstname=(额外的['name']rescue'')
self.name=(额外的['name']解救“”)
self.bio=(额外['description']rescue'')
结束
self.twitter_share=true
结束
#将身份验证属性设置为“omniauth”散列中的属性
def hash_from_omniauth(omniauth)
{
:provider=>omniauth['provider'],
:uid=>omniauth['uid'],
:token=>(omniauth['credentials']['token']rescue nil),
:secret=>(omniauth['credentials']['secret']rescue nil)
}
结束
结束
##新方法ID与:before add=>:apply\u share
def应用_共享(身份验证)
案例验证['provider']
当“脸谱”出现时
self.facebook_share=true
当“推特”
self.twitter_share=true
结束
自救
结束

我相信您从未真正保存当前用户。因此,您可以将属性设置为true,然后重定向。关联存储在身份验证模型中,因此Rails为了提供帮助,不会更新当前用户,只更新身份验证的新实例

尝试:

看看这能不能解决问题。如果是这样,我强烈建议使用回调。请看这里:

第4.5节关于关联回调。您可以在具有多个身份验证关联的服务器上执行“添加前”回调,以从控制器中删除该代码,因为它会变得非常臃肿

   class User < ActiveRecord::Base
     has_many :authentications, :before_add => :apply_share

     def apply_share(authentication)
      #update attributes
      #save model
     end
   end
class用户:应用\u共享之前
def应用_共享(身份验证)
#更新属性
#保存模型
结束
结束

我相信您从未真正保存当前用户。因此,您可以将属性设置为true,然后重定向。关联存储在身份验证模型中,因此Rails为了提供帮助,不会更新当前用户,只更新身份验证的新实例

尝试:

看看这能不能解决问题。如果是这样,我强烈建议使用回调。请看这里:

第4.5节关于关联回调。您可以在具有多个身份验证关联的服务器上执行“添加”回调以删除tha
   class User < ActiveRecord::Base
     has_many :authentications, :before_add => :apply_share

     def apply_share(authentication)
      #update attributes
      #save model
     end
   end