2016-03-22 20 views
1

Ich brauche etwas Hilfe. Ich habe Devise verwendet, um mein Modell user einzurichten. A user hat viele accounts. Ein account gehört zu einem user. Ich möchte in der Lage sein, die Attribute eines account mit einigen Hashwerten zu aktualisieren, die ich nach einem Rückruf von der Twitter-API erhalte. Mit dem, was ich habe, nach dem Rückruf von Twitter, werden die account Attribute überhaupt nicht aktualisiert, sie bleiben nil. Wie kann ich ein account aktualisieren, so dass es die uid, token usw. nach dem Twitter-Rückruf behält. Das habe ich versucht zu tun. twitter_accounts_controller.rbDevise + Omniauth Twitter + Twitter Gem aktualisieren Attribute

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 Konsole zeigt diese nil Attribute nach dem Rückruf.

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> 
+0

Ändern Sie 'update_attributes' in' update_attributes! '. Und debuggen was in 'request.env ['omniauth.auth']' 'ist. –

Antwort

1

In Ihrem Account Modell haben Sie die folgenden Schritte aus:

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 

Da Sie immer einen neuen Datensatz zunächst in Ihrem find_or_create_from_auth_hash Methode erstellen, und Sie setzen nie account_name oder description, die beide Welche Felder erforderlich sind, update_attributes wird Validierungen fehlschlagen und im Hintergrund fehlschlagen. Sie geben jedoch das Objekt Account zurück (nicht persistent), wodurch es möglicherweise in anderen Methoden angezeigt wird, die Account "exist" aber nicht in der Datenbank ist.

Verwandte Themen