railsでfacebookを用いた、ソーシャルログイン(および新規登録)を実装

自身の記憶定着用の備忘録

 

【参考にした記事】

device:gemの公式

https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview

 

実際の実装に使用させていただいた記事

https://qiita.com/keirof1892/items/4d086e5ed0872dee7dac

 

deviceを使わず実装しているため、概念的な理解に使用させていただいた記事

https://qiita.com/memetics/items/214babcebae32c52933c

 

実装の流れ

facebook divに登録

②omniauthの導入

snsからの情報を記録するテーブル(sns_credential )の作成

④userとsns_credentialアソシエーションの設定

facebookから情報を取得することを許可するための環境変数の設定

⑥userモデルのdeviseに:omniauthable,omniauth_providers:の追加

self.find_oauth(auth)メソッドをuserモデルに設定

 facebookから得た情報はauth.info.〇〇で表現できる。

 メソッド内の条件分岐は

 1.自身のアプリにすでにsns_credentialの登録があるユーザーかどうか

 2.自身のアプリにすでにuserの登録があるかどうか

 分ける。

 条件分岐の意図は  userがない場合は新規作成(sing_up)、

           userある場合は(sign_in)させるため.

      sns_credentialのテーブルにすでに、データが存在する場合は、

  そのデータを用い て、ログインする。sns_credentialの情報がない場合は、

  facebookから取得した情報を登録し、その情報を持ってログインする。

  それぞれの情報を帰り値として返し、メソッドの呼び出し元に返す。

 

 

omniauth_callbacks_controller.rbの作成。

 ⑦の条件分岐によって取得した値を用いて、アクションを設定する。

  すでにuserがある場合はログイン、

     userがない場合は新規登録画面に遷移する。

  新規登録に遷移の場合はnicknameとmailアドレスをfacebook側から取得して

  いるので、そのデータを新規登録画面にデフォルトで反映させておく。

 

⑨コールバック、facebookwを用いた新規登録の際のルーティングを設定。

 

⑩新規登録の実装。facebookからの登録の場合はパスワード設定することなく、

 新規登録を完成させる。sns_credentialテーブルにuid(ユーザーの識別番号)と

 いうカラムを設定し、新規登録のアクションでuser_idと紐つけることで、

 ユーザーとfacebookの情報を紐つけてデータベースに登録する。

 

 

 

facebook登録のボタンは、任意のところにlink_toで設定すればok

 

 

結構詰まりました。

 

しっかりdeviceのreadmeを読んで、「facebookから得た情報はauth.info.〇〇で表現できる。」などを理解する必要がある。

 

前提条件が違うため、コピペでは動かない。

 

自分のコピーしようとしているコードを1行づつ理解し、実装することが大切。

 

 

 

railsでfacebookを用いた、ソーシャルログイン(および新規登録)を実装

自身の記憶定着用の備忘録

 

【参考にした記事】

device:gemの公式

https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview

 

実際の実装に使用させていただいた記事

https://qiita.com/keirof1892/items/4d086e5ed0872dee7dac

 

deviceを使わず実装しているため、概念的な理解に使用させていただいた記事

https://qiita.com/memetics/items/214babcebae32c52933c

 

実装の流れ

facebook divに登録

②omniauthの導入

snsからの情報を記録するテーブル(sns_credential )の作成

④userとsns_credentialアソシエーションの設定

facebookから情報を取得することを許可するための環境変数の設定

⑥userモデルのdeviseに:omniauthable,omniauth_providers:の追加

self.find_oauth(auth)メソッドをuserモデルに設定

 facebookから得た情報はauth.info.〇〇で表現できる。

 メソッド内の条件分岐は

 1.自身のアプリにすでにsns_credentialの登録があるユーザーかどうか

 2.自身のアプリにすでにuserの登録があるかどうか

 分ける。

 条件分岐の意図は  userがない場合は新規作成(sing_up)、

           userある場合は(sign_in)させるため.

      sns_credentialのテーブルにすでに、データが存在する場合は、

  そのデータを用い て、ログインする。sns_credentialの情報がない場合は、

  facebookから取得した情報を登録し、その情報を持ってログインする。

 

 

 

 

 

データ型を正しく理解し、意図した実行結果を得る

rubyでプログラムを書く際、何故かデータが取れない、、、

 

よく見てみると、エラー文に型が違うとの表示がされていることがよくある。。

 

実際、ポートフォリオ作成の際に数値計算のアプリを作ったため、floatで計算し、表示する際はintegerに変換するという作業を何度もした。

 

 

コントローラーでparamsのなかの値を取得する際は、正しいデータ型で取得しないと、

意図した実行結果が得られない。

 

使うデータ型は主に以下の通り、、

 

datetime 日時

date  日付

text  文字列(長い)

string 文字列(短い)

float (浮動少数点数)

integer (符号付整数)

boolean (真偽値)

 

 

以上、備忘録

 

 

 

form_forで複数のレコードを一括登録する

やりたいこと。

 

 

logsテーブル(カラムは 名前、タンパク質、脂質、炭水化物、記録時間)を一つのボタンで一括登録する。

 

お米と牛肉など別々のlogとして登録したい場合に、一括で登録できる方が利便性が高いと考えました。

 

.form.collection-item
 = form_for [@log] do |f|
  .main_content
   .card.text_form.log_new_form
   %p 食品名
   = f.text_field :name, index: 0, placeholder: ' food'
   %p タンパク質
   = f.text_field :protein, index: 0, placeholder: ' protein(g)'
   %p 脂質
   = f.text_field :fat, index: 0, placeholder: ' fat(g)'
   %p 炭水化物
   = f.text_field :carbohydrate ,index: 0, placeholder: ' carbohydrate(g)'
   .datetime
    = f.datetime_select :start_time, index: 0, class:"datepicker"

 

form_forのfieldにインデックスナンバー(0..10等)を入力し複数の入力フォームを作成。

indexを付与することでname値を区別して飛ばすことができます。(name値が同じだと、複数のlogのうち、最後のlogのみ保存されることになります。)

 

log (index=0)の卵

log(index=1)のお米

を入力し、binding.pryで止めてみる

 

[1] pry(#<LogsController>)> params[:log]

=> <ActionController::Parameters {"0"=>{"name"=>"", "protein"=>"1", "fat"=>"1", "carbohydrate"=>"2", "start_time(1i)"=>"2019", "start_time(2i)"=>"5", "start_time(3i)"=>"2", "start_time(4i)"=>"12", "start_time(5i)"=>"39"}, "1"=>{"name"=>"お米", "protein"=>"1", "fat"=>"11", "carbohydrate"=>"1", "start_time(1i)"=>"2019", "start_time(2i)"=>"5", "start_time(3i)"=>"2", "start_time(4i)"=>"08", "start_time(5i)"=>"13"}}

 

インデックスナンバーで区別された、入れ子構造のハッシュが飛んでいることがわかる。

 

def log_params(i)
params.require(:log).require(i.to_s.to_sym).permit(:name,。。。省略
end

 

params[:log][:"1"]でお米のデータが取れるため上記のようにシンボル化して値を取得できるようにする。

 

def create
i = 0
while params[:log][i.to_s.to_sym] != nil do
@log=Log.new(log_params(i))
@log.save!
i = i + 1
end
if @log.save
redirect_to new_log_path ,notice: '食事管理登録をしました'
else
flash.now[:notice] = '食事情報を入力してください'
render :new
end
end

 

インデックス番号をiと定義し、params[:log][i.to_s.to_sym]がnil出ない場合に繰り返し、

保存するロジックを組む。

 

 

 

できた。。

 

 

 

結構詰まりました。fields_forとか使ってもできるのだろう、、

 

 

 

 

%p! ! と  %Q! !で文字列を作る

今日の記事は%p!  ! と  %Q! !で文字列を作ります。

 

puts  %p!hello!    は

puts   'hello'

 

と同じ実行結果になり

 

puts  %Q!hello!    は

puts   "hello"

 

と同じ実行結果になります。

 

 

 

 

 

 

 

 

なら『''』『""』を用いたクオーテーションで表現すればよくない?

 

と思うところですが

puts を用いた実行結果にクオーテーションを使いたい状況が発生した場合、つまり実行結果を

 

"hello"としたい場合は

puts  %p!"hello"!

とすることで、期待している実行結果を生むことができます。

 

 

ちなみにダブルクオーテーションとシングルクオーテーションの違いは

式展開 #{name}     (nameは変数です)

を利用したい場合はダブルクオーテーションで書く必要があります。

 

 

 

<参考文献>

プロを目指す人のためのRuby入門

 

 

 

!の意味を考えれば、間違わない ( != or =! )

if分の中で、if  a == b  (aとbが等しいとき)

                    if   a != b(aとbが等しくない時)

のように条件を設定することができますが、=!としてしまうことがあったり、どっちが先だったっけ、、と考えてしまうことがありました。

 

そんな時に意識してすべきなのが!の意味です。

!は真偽を逆転させる意味を持つ演算子です。

 

x + y  → 真   が成立している時

!(x +y) → 偽 となります。

 

=の前に置いて真偽値を逆転させる

と覚えておけば迷わず「!=」が正しいと判断できるようになるのではないでしょうか。

 

 

 

では、本日も学習頑張ります。

 

 

 

 

<参考文献>

プロを目指す人のためのRuby入門

 

nilガードって何?

Rubyにはnilガードなるものが存在する。

それが何なのかというと、、

 

 

 

 

 

 

 

 

 

 

 

 

 

nilをガードするもの。。

 

 

 

 

それが結局何だというところだと思いますので、簡単にご説明を。。

 

 

 

例えば@sumというインスタンス変数を設定するとして、@sumに該当する数値がない状況(nilが返ってしまう)の時、

エラーが出るのを防ぐことができるのが、nilガードです。

具体例を用いて説明します。

 

 

@sum | | = 10

@sum | |  (@sum = 10 )

 

上の二つの記述は同じ意味を示しており、

@sumに該当するものが存在する(@sumが真)の時、@sumを

@sumに該当するものがない状況(@sumが偽、つまりfalseもしくはnil)であれば@sumに10を代入する

 

という意味になります。

 

 

変数にnilが入っているかもしれない状況で、あらかじめデフォルトの値を設定しておくことができる便利な機能です。

 

 

開発における具体的な使用例としては、

カレンダーに日付に対して、該当の変数を表示する場合等に、

該当のものがなくても、nilが返るのを防ぐことができます。

 

 

 

 

いまいちピンとこない方もいらっしゃると思いますが、個人開発等を進めていくと、nilが返り、エラーとなることが発生することがあると思いますので、そんな時に「そういえばnilガードという機能があった気がする」と、思い出していただき、その時に改めて、学習するのが良いかと思います。

 

実際に自分の開発で使用することが、一番のスキル定着につながると思いますので、自分も積極的に手を動かしていきたいと思います。

 

 

 

以上