[英]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 回调后保留uid
、 token
等。 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_name
或description
,这两个都是必填字段,因此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.