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

| 我按照Railscasts#235和#236进行设置,以使用omniauth创建用户身份验证。 http://railscasts.com/episodes/235-omniauth-part-1 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的新方法,该方法根据提供程序来更改布尔值,并且我试图调用current_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
    
已邀请:
        我相信您从未真正保存过current_user。因此,将属性设置为true,然后重定向。关联存储在身份验证模型中,因此,Rails试图提供帮助,不会更新current_user,而只是更新身份验证的新实例 尝试:
current_user.apply_share(omniauth)
current_user.save
看看是否能解决。现在如果可以,我强烈建议您改用回调。在这里看看: http://guides.rubyonrails.org/association_basics.html 第4.5节关于关联回调。您可以在has_many身份验证关联上执行before_add回调,以从控制器中删除该代码,因为该代码变得非常肿。
   class User < ActiveRecord::Base
     has_many :authentications, :before_add => :apply_share

     def apply_share(authentication)
      #update attributes
      #save model
     end
   end
    
        设置
*_share
属性后,需要在
User
对象上调用
#save
。 将新项目添加到“ 6”集合中会自动保存该集合项目,但不会触发父项(“ 7”)上的保存操作。     

要回复问题请先登录注册