Devise + Omniauth Twitter + Twitter Gem 更新属性
Devise + Omniauth Twitter + Twitter Gem updating attributes
我需要一些帮助。我使用 Devise
来设置我的 user
模型。一个user
有很多accounts
。一个 account
属于一个 user
。我希望能够使用回调后从 Twitter API 获得的一些哈希值更新 account
的属性。据我所知,在 Twitter 回调之后,account
属性根本没有更新,它们仍然是 nil
。我如何更新 account
以便它在 Twitter 回调后保留 uid
、token
等。这就是我一直在努力做的。
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
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 控制台在回调后显示这些 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>
在您的 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
由于您总是首先在 find_or_create_from_auth_hash
方法中创建新记录,并且您从未设置 account_name
或 description
,这两个都是必填字段,update_attributes
将无法通过验证,并且会静默失败。但是,您返回的是 Account
对象(未持久化),这可能会使它出现在 Account
执行 "exist" 但不在数据库中的其他方法中。
我需要一些帮助。我使用 Devise
来设置我的 user
模型。一个user
有很多accounts
。一个 account
属于一个 user
。我希望能够使用回调后从 Twitter API 获得的一些哈希值更新 account
的属性。据我所知,在 Twitter 回调之后,account
属性根本没有更新,它们仍然是 nil
。我如何更新 account
以便它在 Twitter 回调后保留 uid
、token
等。这就是我一直在努力做的。
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
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 控制台在回调后显示这些 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>
在您的 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
由于您总是首先在 find_or_create_from_auth_hash
方法中创建新记录,并且您从未设置 account_name
或 description
,这两个都是必填字段,update_attributes
将无法通过验证,并且会静默失败。但是,您返回的是 Account
对象(未持久化),这可能会使它出现在 Account
执行 "exist" 但不在数据库中的其他方法中。