简体   繁体   English

Devise + Omniauth Twitter + Twitter Gem 更新属性

[英]Devise + Omniauth Twitter + Twitter Gem updating attributes

I need some help.我需要帮助。 I used Devise to setup my user model.我使用Devise来设置我的user模型。 A user has many accounts .一个user有多个accounts An account belongs to a user .一个account属于一个user I want to be able to update an account 's attributes with some hash values that I obtain from the Twitter API after a callback.我希望能够使用回调后从 Twitter API 获取的一些哈希值更新account的属性。 With what I have, after the callback from Twitter, the account attributes don't get updated at all, They remain nil .使用我所拥有的,在 Twitter 回调之后, account属性根本没有更新,它们仍然是nil How can I update an account so that it keeps the uid , token , etc after the Twitter callback.如何更新account以便在 Twitter 回调后保留uidtoken等。 This is what I have been trying to do.这就是我一直在努力做的。 twitter_accounts_controller.rb twitter_accounts_controller.rb

class TwitterAccountsController < ApplicationController
  def create
    @account = Account.find_or_create_from_auth_hash(auth_hash)
    @account.user = current_user
    redirect_to root_path
  end

  protected
  def auth_hash
    request.env['omniauth.auth']
  end
end


accounts_controller.rb
class AccountsController < ApplicationController
  before_action :authenticate_user!
  before_action :set_account, only: [:edit, :update, :destroy, :show]

  def index
    @accounts = Account
    @user = current_user
  end

  def new
    @account = Account.new
  end

  def create
    @account = Account.new(account_params)
    @account.user = current_user

    if @account.save
      $twitter.update("@someone from Rails app on Heroku")
      flash[:success] = "Account succesfully created."
      redirect_to @account
    else
      flash.now[:warning] = "Oops, something went wrong!"
      render 'new'
    end
  end

  def show
  end

  def edit
  end

  def update
    if @account.update_attributes(account_params)
      flash[:success] = "Account changes succesfully commited."
    else
      render 'edit'
    end
  end

  def destroy
    if @account.destroy
      flash[:success] = "Account is gone!"
      redirect_to root_path
    end
  end

  private
  def account_params
    params.require(:account).permit(:account_name, :description, posts_attributes: [:tweet])
  end

  def set_account
    @account = Account.find(params[:id])
    rescue ActiveRecord::RecordNotFound
    flash[:danger] = "The account you are looking for doesn't even exist! 😂"
    redirect_to accounts_path
  end
end

account.rb账号.rb

class Account < ActiveRecord::Base
    before_save :capitalize_name

    belongs_to :user
    has_many :posts, dependent: :destroy

    accepts_nested_attributes_for :posts

    validates :account_name, :description, presence: :true

    default_scope { order('created_at DESC') }

    def self.find_or_create_from_auth_hash(auth_hash)
        account = where(provider: auth_hash.provider, uid: auth_hash.uid).first_or_create
        account.update_attributes(
            name: auth_hash.info.name,
            profile_image: auth_hash.info.image,
            token: auth_hash.credentials.token,
            secret: auth_hash.credentials.secret
        )
        account
    end

    private
    def capitalize_name
        self.account_name = self.account_name.split.map { |name| name.capitalize }.join(" ")
    end
end

schema.rb模式文件

ActiveRecord::Schema.define(version: 20160322001131) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "accounts", force: :cascade do |t|
    t.string   "account_name"
    t.string   "description"
    t.datetime "created_at",    null: false
    t.datetime "updated_at",    null: false
    t.integer  "user_id"
    t.string   "provider"
    t.string   "uid"
    t.string   "token"
    t.string   "secret"
    t.string   "profile_image"
    t.string   "name"
  end

  add_index "accounts", ["user_id"], name: "index_accounts_on_user_id", using: :btree

  create_table "posts", force: :cascade do |t|
    t.text     "tweet"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer  "account_id"
  end

  add_index "posts", ["account_id"], name: "index_posts_on_account_id", using: :btree

  create_table "users", force: :cascade do |t|
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.inet     "current_sign_in_ip"
    t.inet     "last_sign_in_ip"
    t.datetime "created_at",                          null: false
    t.datetime "updated_at",                          null: false
  end

  add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
  add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree

  add_foreign_key "accounts", "users"
  add_foreign_key "posts", "accounts"
end

user.rb用户名

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  has_many :accounts
end

Heroku console shows these nil attributes after the callback. Heroku 控制台在回调后显示这些nil属性。

irb(main):013:0> Account.first
  Account Load (1.2ms)  SELECT  "accounts".* FROM "accounts"  ORDER BY created_at DESC LIMIT 1
  Account Load (1.2ms)  SELECT  "accounts".* FROM "accounts"  ORDER BY created_at DESC LIMIT 1
=> #<Account id: 7, account_name: "Fadsa Adafda", description: "adfasdf", created_at: "2016-03-22 01:29:47", updated_at: "2016-03-22 01:29:47", user_id: 1, provider: nil, uid: nil, token: nil, secret: nil, profile_image: nil, name: nil>

In your Account model, you have the following:在您的Account模型中,您有以下内容:

validates :account_name, :description, presence: :true

def self.find_or_create_from_auth_hash(auth_hash)
  account = where(provider: auth_hash.provider, uid: auth_hash.uid).first_or_create

  account.update_attributes(
    name: auth_hash.info.name,
    profile_image: auth_hash.info.image,
    token: auth_hash.credentials.token,
    secret: auth_hash.credentials.secret
  )

  account
end

Since you're always creating a new record at first in your find_or_create_from_auth_hash method, and you never set account_name or description , both of which are required fields, update_attributes will fail validations, and fail silently.由于您总是首先在find_or_create_from_auth_hash方法中创建新记录,并且您从未设置account_namedescription ,这两个都是必填字段,因此update_attributes将无法通过验证,并且会静默失败。 However, you're returning the Account object (not persisted), which could make it appear in other methods that an Account does "exist", but is not in the database.但是,您正在返回Account对象(未持久化),这可能会使其出现在Account确实“存在”但不在数据库中的其他方法中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM