質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Twitter

Twitterは、140文字以内の「ツイート」と呼ばれる短文を投稿できるサービスです。Twitter上のほぼ全ての機能に対応するAPIが存在し、その関連サービスが多く公開されています。

Facebook

Facebookは、実名登録制のSNS(ソーシャル・ネットワーキング・サービス)です。開発者用のデベロッパーサイトが存在し、一般ユーザーによるFacebook向けアプリケーション開発が可能です。

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

Q&A

解決済

2回答

3960閲覧

persist?がfalseになる原因。

s.k

総合スコア423

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Twitter

Twitterは、140文字以内の「ツイート」と呼ばれる短文を投稿できるサービスです。Twitter上のほぼ全ての機能に対応するAPIが存在し、その関連サービスが多く公開されています。

Facebook

Facebookは、実名登録制のSNS(ソーシャル・ネットワーキング・サービス)です。開発者用のデベロッパーサイトが存在し、一般ユーザーによるFacebook向けアプリケーション開発が可能です。

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

0グッド

0クリップ

投稿2016/11/07 10:24

以下、①、②以外の原因を教えていただきたいです。

###前提・実現したいこと
persist?の結果をtrueにしたい。

###発生している問題・エラーメッセージ

persist?が返す値が、毎度falseになってしまいます。
調べたところ、falseを返す原因は大きく分けて2つだとわかりました。
①モデル構築しか行われていない(save or createがない)
②validationが働いて①の妨げになってしまっている。

①、②の問題が発生しているか確認をしましたが、
どうやらないようです。

persist?が他にfalseになる原因が他にもあるのかをこの質問を読んでくださった方にお聞きしたいです。

###該当のソースコード

【users_controller.rb】

def facebook user = User.from_omniauth(request.env["omniauth.auth"])←★from_omniauthに原因があるはず。★ if user.persisted? ←★falseになり、elseの処理しか行われない。★ sign_in_and_redirect user set_flash_message(:notice, :success, kind: __callee__.to_s.capitalize) if is_navigational_format? else←★いつもこの処理が実行されてしまう。★ session["devise.user_attributes"] = user.attributes redirect_to new_user_registration_url(from_omniauth_callback: "1") end end

【user.rb】

ruby

1 2 devise :database_authenticatable, :registerable, 3 :recoverable, :rememberable, :trackable, :validatable 4 5 def self.from_omniauth(auth) 6 where(provider: auth.provider, uid: auth.uid).first_or_create do |user| ←first_or_createがあるので①の問題は発生していない…? 7 user.provider = auth.provider 8 user.uid = auth.uid 9 end 10 end

【omniauth.rb】

ruby

1Rails.application.config.middleware.use OmniAuth::Builder do 2 require 'omniauth/strategies/facebook_another' 3 4 provider :facebook, "ID", "KEY" 5 6 provider :facebook_another, "ID", "KEY" 7 8end

###試したこと
①【user.rb】のself.from_omniauthメソッドでデータがきちんと保存されているかを確認するため条件分岐を書きましたが、エラーがでてできませんでした…

###補足情報(言語/FW/ツール等のバージョンなど)
①user.rbにはvalidationを書いていないので②の問題も発生していないと思われます。
②Userテーブルにはproviderとuidカラムは存在します。
③deviseで複数モデルを実装してます。deviseでのOmniAuthは単一モデルにしか対応できないそうなので。
④関連する質問はこちら

###情報追加

hana-daさんへ

見づらくて申し訳ありません((+_+))

ruby

1class User < ActiveRecord::Base 2 # Include default devise modules. Others available are: 3 4 #microposts 5 has_many :microposts, dependent: :destroy 6 7 #plugin(SNS omuniauth) 8 has_many :social_profiles, dependent: :destroy 9 10 11 ##コメント機能 12 13 #comment(user-to-micropost.user) 14 has_many :comments 15 16 #call(user-to-micropost.shop) 17 has_many :calls 18 19 #says(shop-to-micropost.shop) 20 has_many :says 21 22 #insists(shop-to-micropost.user) 23 has_many :insists 24 25 26 27 #relationship(users-to-users) 28 has_many :active_relationships, class_name: "Relationship", foreign_key: "follower_id", dependent: :destroy 29 has_many :passive_relationships, class_name: "Relationship", foreign_key: "followed_id", dependent: :destroy 30 31 has_many :following, through: :active_relationships, source: :followed #フォローしている人を表示できるメソッドを関連づける 32 has_many :followers, through: :passive_relationships, source: :follower #フォローされている人を表示できるメソッドを関連付ける 33 34 #associates(user-to-shop) 35 has_many :shops 36 has_many :associates, dependent: :destroy 37 has_many :associate_shops, through: :associates, source: :shop 38 39 #makes(shop-to-user) 40 has_many :makes, dependent: :destroy 41 has_many :make_shops, through: :makes, source: :shop 42 43 #praises(user-to-micropost) 44 has_many :praises, dependent: :destroy 45 has_many :praise_microposts, through: :praises, source: :micropost 46 47 #evaluates(user-to-micropost) 48 has_many :evaluates, dependent: :destroy 49 has_many :evaluate_microposts, through: :evaluates, source: :micropost 50 51 52 devise :database_authenticatable, :registerable, 53 :recoverable, :rememberable, :trackable, :validatable 54 55 def self.from_omniauth(auth)★★ 56 where(provider: auth.provider, uid: auth.uid).first_or_create do |user| ←first_or_create 57 user.provider = auth.provider 58 user.uid = auth.uid 59 end 60 end 61 62 user 63 end 64 65 66 def password_required? 67 super && provider.blank? # provider属性に値があればパスワード入力免除 68 end 69 70 def self.new_with_session(params, session) 71 super.tap do |user| 72 if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"] 73 user.email = data["email"] if user.email.blank? 74 end 75 end 76 end 77 78 def feed 79 following_ids = "SELECT followed_id FROM relationships WHERE follower_id = :user_id" 80 associate_shops_ids = "SELECT shop_id FROM associates WHERE user_id = :user_id" 81 Micropost.where("user_id IN (#{following_ids}) OR shop_id IN (#{associate_shops_ids}) OR user_id = :user_id", user_id: id) 82 end 83 84 #follow 85 86 def follow(other_user) 87 active_relationships.create(followed_id: other_user.id) 88 end 89 90 def unfollow(other_user) 91 active_relationships.find_by(followed_id: other_user.id).destroy 92 end 93 94 def following?(other_user) 95 following.include?(other_user) 96 end 97 98 #お気に入りしているかどうかを、返すメソッド(shop-to-user) 99 def maked_by? shop 100 makes.where(shop_id: shop.id).exists? 101 end 102 103 104 105end 106

よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

トラブルシュートの方法を書いてみます。

プログラムが思い通りの動作をしない場合は、小さい単位で1つづつ思い通りの動作をしているかを確認する必要があります。

ruby

1 def self.from_omniauth(auth) 2 where(provider: auth.provider, uid: auth.uid).first_or_create do |user| ←first_or_createがあるので①の問題は発生していない…? 3 user.provider = auth.provider 4 user.uid = auth.uid 5 end 6 end

①の問題は発生していない…?

ここ。自信が持てないんですよね。
こういうところから確認していくといいです。
(時に自信がある所が思い違いをしている場合もあります。厄介)

さて、どう確認するか?

first_or_create しているので User.from_omniauth の戻りは必ず persist? == true である事が確認できればいいわけです

本当ならテストを書いてそれが通る事を確認するのですが、テストがなくても確認はできます。

ruby

1 def self.from_omniauth(auth) 2 result = where(provider: auth.provider, uid: auth.uid).first_or_create do |user| ←first_or_createがあるので①の問題は発生していない…? 3 user.provider = auth.provider 4 user.uid = auth.uid 5 end 6 7 raise 'result.persist? == true になってないです!!!' unless result.persist? == true 8 9 return result 10 end

本当に user.persist? == true になっているのであれば例外は発生しないはずです。
例外が発生したのであれば first_or_createがあるので①の問題は発生していない は偽です。

といった感じで1つづつ潰していってください。


じゃぁ何が悪いのか persist?true でないという事は create に失敗しています。
createに失敗する理由はいくつかありますが create! にする事で create に失敗した時点で例外が発生するので

ruby

1 def self.from_omniauth(auth) 2 where(provider: auth.provider, uid: auth.uid).first_or_create! do |user| ←first_or_createがあるので①の問題は発生していない…? 3 user.provider = auth.provider 4 user.uid = auth.uid 5 end 6 end

として例外メッセージを読めばなぜ first_or_create が失敗したのかわかるはずです。

投稿2016/11/07 22:27

編集2016/11/08 01:21
hana-da

総合スコア1728

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

s.k

2016/11/08 01:25 編集

hana-daさん 教えていただいたコードを試しました。 raiseで例外が発生したので、どうやら★unless result.persisted? == true★の条件を満たしていないようです!原因の特定はこのようにできるのですね。私はまだテストコードを書けませんので非常に助かりました! はい。 first_or_create!で試したところ、Validation failed: Email can't be blank というメッセージが出てきました!
guest

0

【view/users/registration/new.html.erb】

ruby

1 <% if f.object.password_required? %>

がpersisted?をfalseにする原因になっていました。

原因を究明の過程(hana-daさんの指摘をもとに)
①first_or_create→first_or_create!に変更
【user.rb】

ruby

1 def self.from_omniauth(auth) 2 where(provider: auth.provider, uid: auth.uid).first_or_create! do |user|★変更箇所★ 3 user.provider = auth.provider 4 user.uid = auth.uid 5 end 6 end

結果、このようなエラーが発生

Validation failed: Email can't be blank

②devise :valitableのvalitableを削除
deviseでバリデーションをかけてないつもりだったので、どこにvalidationがかけられているかを確かめるために削除。
結果、以下の箇所にエラーが発生。

def password_required? super && provider.blank? # provider属性に値があればパスワード入力免除 end

どうやら、このメソッドがvalidationをかけていたようです。
削除後persited?はtrueになりましたヽ(^o^)丿

hanadaさん、ありがとうございます!

投稿2016/11/08 01:46

s.k

総合スコア423

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問