IT技術にまつわる実験ノート

「長編を書くより、短編を数多く完成させてください。それが上達への近道です」 by 手塚治虫

Rails で「いいね」機能を作ってみる

はじめに

以下の記事を参考にして、Rails で「いいね」機能を作ってみる。

 

作ってみる

サンプル用のプロジェクトを作成する。

  • rails new likes_sample
  • cd likes_sample

 

devise をインストールする。

  • echo 'gem "devise"' >> Gemfile
  • bundle

 

devise の初期設定をする。

  • bin/rails g devise:install
  • bin/rails g devise User

 

サンプル用に Post モデルを作成する。

  • bin/rails g scaffold Post title:string body:text user:references

 

app/models/post.rb で、Post が複数のいいねを持てるにする。

f:id:matt-note:20190715131305p:plain

 

app/models/user.rb で User が複数回いいねできるようにする。

f:id:matt-note:20190715225334p:plain

 

「いいね」を表現する Likes モデルを作成する。

  • bin/rails g model Like post:references user:references

 

データベースに反映させる。

 

config/routes.rb を編集する。

f:id:matt-note:20190715130714p:plain

 

いいね機能のコントローラを作成する。

  • bin/rails g controller likes

f:id:matt-note:20190715225739p:plain

 

app/views/posts/show.html.erb で「いいね数」と「いいねボタン」を表示する。

f:id:matt-note:20190715221603p:plain

 

app/views/layouts/application.html.erb にユーザー登録・ログアウトのリンクを追加する。

f:id:matt-note:20190715130806p:plain

 

コンソールからサンプル用のデータを作成する。

  • User.create(email: "likes@example.com", password: "password", password_confirmation: "password")
  • Post.create(title: "タイトル", body: "本文", user_id: 1)

 

サーバーを起動して、サインインする。

f:id:matt-note:20190715130631p:plain

 

個別の投稿ページにアクセスすると、いいねボタンといいね数が表示される。いいねボタンを押すと、いいね数を増やすことができる。

f:id:matt-note:20190715221625p:plain


一人のユーザーは1つの投稿に対して1回だけ「いいね」できるようにしてみる。

app/controllers/likes_controller.rb に以下のコードを追加する。

f:id:matt-note:20190715230005p:plain

 

これでユーザーが複数回いいねをできないように作成できた。

f:id:matt-note:20190715221827p:plain

 

いいねの取り消し機能を作ってみる。

app/controllers/likes_controller.rb に destroy アクションを作成する。

f:id:matt-note:20190715230213p:plain

 

app/views/posts/show.html.erb で条件分岐して「いいね・いいね取り消し」ボタンを表示する。

f:id:matt-note:20190715230745p:plain

 

サーバーを起動してアクセスしてみる。

f:id:matt-note:20190715231005g:plain

-> いいねといいね取り消し機能を作成できた。

 

Rails で独自Validator クラスを作ってみる

使ってみる

サンプル用のリポジトリを作成する。

  • rails new custom_validator_sample
  • cd custom_validator_sample

 

サンプル用に User モデルを scaffold して作成する。

 

独自Validator を作成する。

ここでは Twitter アカウントを持つ人だけが登録できるようにしたい。

  • mkdir app/validators
  • touch app/validators/user_validator.rb

f:id:matt-note:20190711192604p:plain

 

app/models/user.rb でバリデーターを読み込む。

f:id:matt-note:20190711192657p:plain

 

サーバーを起動して、http://localhost:3000/users/new にアクセスして、存在しなさそうなユーザー名を入力してみる。

f:id:matt-note:20190711192837p:plain

-> 存在しないTwitterアカウントは登録できないようにバリデーションすることができた。

 

Google Cloud Functions を使って express アプリを動かしてみる

はじめに

Google Cloud Functions を使って express アプリを動かしてみる。

 

使ってみる

サンプル用のリポジトリを作成する。

  • mkdir pokemon-api
  • cd pokemon-api

 

npm init コマンドを実行する。

  • npm init -y

 

json データをダウンロードする。

 

express をインストールする。

  • npm install express

 

サーバーを作成する。

  • touch index.js

f:id:matt-note:20190711134326p:plain

 

ローカルでサーバーを動かして、localhost:4000/pokemons/1 にアクセスしてみる。

f:id:matt-note:20190711134425p:plain

-> JSON データを返すサーバーを作成できた。

 

GCP を設定する

新しいプロジェクトを作成する。

ここでのプロジェクト名は pokemon-api とした。

f:id:matt-note:20190711135014g:plain

 

Cloud Functions API を有効化する。

f:id:matt-note:20190711135817g:plain

 

Cloud Functions 用に index.js を編集する。以下のコードをファイルの末尾に追加する。

f:id:matt-note:20190711140043p:plain

 

gcloud コマンドでデプロイする。

デプロイ前にデプロイ先のプロジェクトを確認しておくと、安心してデプロイできる。

  • gcloud config list

f:id:matt-note:20190711142804p:plain

-> project でデプロイ先のプロジェクトがわかる。

 

プロジェクト名を変更する場合は、以下のようにする。

  • gcloud config set project <project_id>

 

デプロイ先が確認できたら、以下のコマンドでデプロイできる。

  • gcloud functions deploy pokemon-api --runtime nodejs8 --trigger-http --entry-point app

f:id:matt-note:20190711142955p:plain

-> この URL から API にアクセスできる。

 

f:id:matt-note:20190711143024p:plain

-> API サーバーを Cloud Functions にデプロイできた。

Rails の fixture で ERB を使ってループ処理してみる

はじめに

Rails の fixture では ERB を使ってループ処理することができる。

 

使ってみる

サンプル用のリポジトリを作成する。

  • rails new fixture_erb_sample
  • cd fixture_erb_sample

 

サンプル用に Product モデルを scaffold して作成する。

  • bin/rails g scaffold Product name:string price:integer
  • bin/rails db:migrate

 

test/fixtures/products.yml を編集する。(ここでは明示的にidを指定)

f:id:matt-note:20190711130448p:plain

 

DB にフィクスチャの値を読み込ませる。

  • bin/rails db:fixtures:load

 

サーバーを起動して、http://localhost:3000/products にアクセスする。

f:id:matt-note:20190711130609p:plain

-> まとめてサンプル用のデータを登録することができた。

 

fixture をまとめて登録できるので、一覧ページでページャーを確認したい時などに便利。

 

なお、以下のようにすると、うまくいかないので注意。

f:id:matt-note:20190711131039p:plain

 

git で fetch + rebase してみる

はじめに

git の fetch と rebase コマンドで、リモートブランチの変更をローカルに取り込むことができる。git pull --rebase と同じことが実現できるわけだが、fetch + rebase の場合は、rebase 前にリモートブランチの変更を確認してから rebase することができる。

 

使ってみる

GitHubリポジトリを作成する。

f:id:matt-note:20190711111042p:plain

 

ローカルで GitHubリポジトリを clone する。

  • git clone <your_repository>
  • cd fetch-rebase-sample

 

コミットを作成する。

  • echo "# fetch-rebase-sample" >> README.md
  • git add README.md
  • git commit -m "first commit"

 

このリポジトリに初のコミットが作成されたので、master ブランチが作成される。

  • git branch

 

GitHub のリモートリポジトリ(origin)にローカルの master ブランチを push する。

  • git push origin master

 

これでリモートリポジトリに push できる。

f:id:matt-note:20190711111502p:plain

 

ここでは fetch コマンドを使いたいので、リモートブランチを編集する。GitHub で右にある鉛筆ボタンを押すと、編集画面に移動できる。

f:id:matt-note:20190711111834p:plain

 

リモートブランチでコミットを作成する。

f:id:matt-note:20190711111938p:plain

 

リモートブランチ(origin)のコミットを fetch してみる。明示的にコマンドを実行する場合は、以下のようにする。

  • git fetch origin

 

ローカルブランチとリモートブランチの差分を見てみる。

  • git diff origin/master

f:id:matt-note:20190711112245p:plain

-> ローカルブランチとリモートブランチの差分を表示できた。

 

リモートブランチをリベースする前に、ブランチを作成してローカルにコミットを作成してみる。

  • git checkout -b develop
  • echo "second commit" >> second.md
  • git add second.md
  • git commit -m "second commit in local"

 

これでローカルリポジトリの履歴は以下のようになる。

  • git log --oneline

f:id:matt-note:20190711114827p:plain

 

push する前に、origin/master ブランチをリベースして、リモートのコミットをローカルに取り込む。

  • git rebase origin/master

 

これで origin/master ブランチのコミットをローカルブランチに取り込むことができた。

  • cat README.md

f:id:matt-note:20190711113439p:plain

 

origin/master ブランチを取り込んだローカルブランチの履歴は以下のようになる。

  • git log --oneline

f:id:matt-note:20190711114947p:plain

-> second commit の下に origin/master の変更履歴がリベースされる。

 

あとはローカルの develop ブランチを push すれば良い。

  • git push origin develop

 

GitHub のリモートブランチで pull request を作成して、マージする。

f:id:matt-note:20190711115121p:plain

 

これでローカルブランチのコミットをリモートの origin/master ブランチに取り込むことができた。

 

develop ブランチでリモートブランチでマージしたコミットを取り込んでみる。

  • git fetch origin
  • git rebase origin/master

 

履歴を見てみる。

  • git log --oneline

f:id:matt-note:20190711115539p:plain

-> リモートブランチの変更をローカルの develop ブランチに取り込むことができた。

 

rebase でコンフリクトを起こしてみる

GitHub で README.md を編集して、origin/master ブランチにコミットする。

f:id:matt-note:20190711121627p:plain

 

ローカルで README.md を編集してコミットする。

  • echo "edit in local" >> README.md
  • git add README.md
  • git commit -m "third commit"

 

リモートブランチを fetch して rebase してローカルに取り込む。

  • git fetch origin
  • git rebase origin/master

 

コンフリクトが発生する。

f:id:matt-note:20190711121912p:plain

 

ここでのブランチは以下のようになる。

  • git branch

f:id:matt-note:20190711122002p:plain

 

Atom エディタで README.md を開くと、以下のようにコンフリクトが可視化される。

f:id:matt-note:20190711122235p:plain

 

ここでは下の edit in local を使うことにする。ファイルを変更して保存する。

コンフリクトを解消できたら、変更したファイルを add する。

  • git add README.md

 

リベースを続行して、origin/master ブランチのコミットをローカルに取り込む。

  • git rebase --continue

 

これで元の develop ブランチに戻ることができる。

  • git branch

f:id:matt-note:20190711122705p:plain

 

変更履歴は以下のようになる。

  • git log --oneline

f:id:matt-note:20190711122853p:plain

-> rebase して origin/master ブランチをローカルに取り込むことができた。

 

Rails で boolean型の属性でソートしてみる

 

使ってみる

サンプル用のプロジェクトを作成する。

  • rails new boolean_sort_sample
  • cd boolean_sort_sample

 

サンプル用のモデルを scaffold して作成する。

ここでは、棒にあたりが書いているアイスキャンディーをモデルにする。なお、アイスキャンディーは和製英語なので、Popsicle モデルを作成する。また、lottery の値で当たりかはずれかを管理することにする。

  • bin/rails g scaffold Popsicle flavor:string lottery:boolean
  • bin/rails db:migrate

f:id:matt-note:20190710231857p:plain

 

コンソールを起動して、サンプル用のデータを作成する。

  • bin/rails c
  • Popsicle.create(flavor: "ソーダ", lottery: false)
  • Popsicle.create(flavor: "コーラ", lottery: true)
  • Popsicle.create(flavor: "グレープフルーツ", lottery: false)
  • Popsicle.create(flavor: "コーラ", lottery: false)
  • Popsicle.create(flavor: "コーラ", lottery: true)

 

サーバーを起動して、http://localhost:8888/popsicles にアクセスすると、以下のようになる。

f:id:matt-note:20190710231105p:plain

 

app/controllers/popsicles_controller.rb を編集する。

f:id:matt-note:20190710232316p:plain

 

ブラウザをリロードしてアクセスすると、以下のように boolean 型でソートできる。

f:id:matt-note:20190710231753p:plain

-> 普通にソートできた。

 

まとめ

Rails の order メソッドで、普通にboolean型の属性でもソートできる。

true を上に持っていきたい場合は、:desc オプションを付与する。

 

sorcery で GitHub ログインしてみる

はじめに

以下のリンクを参考に sorcery で GitHub ログインを実装してみる。

 

使ってみる

サンプル用のプロジェクトを作成する。

 

gem をインストールする。

  • echo 'gem "sorcery"' >> Gemfile
  • echo 'gem "figaro"' >> Gemfile
  • bundle

 

sorcery の初期設定を実行する。

  • bin/rails g sorcery:install
  • bin/rails g sorcery:install external --only-submodules

 

User モデルに name 属性を追加して、コントローラとビューを作成する。

  • bin/rails g migration AddNameToUsers name:string
  • bin/rails g scaffold User --migration false

 

マイグレーションを実行する。

 

GitHub でアプリの登録を行う。

 

上記の URL でアクセスしたら、右上の「New OAuth App」ボタンをクリックして、アプリの登録を行う。

f:id:matt-note:20190707230510p:plain

 

これで Client ID と Client Secret を取得できる。

f:id:matt-note:20190707200850p:plain

 

環境変数の管理用に figraro の初期設定をする。

  • bundle exec figaro install

 

config/application.yml で環境変数の設定を行う。

f:id:matt-note:20190707201207p:plain

-> ここで設定した値は、アプリから ENV["GITHUB_ID"] のようにして取得できるようになる。

 

config/initializers/sorcery.rb に設定を追加する。

f:id:matt-note:20190707200328p:plain

f:id:matt-note:20190708123859p:plain

f:id:matt-note:20190707201716p:plain

 

Authenticationモデルを作成する。

  • bin/rails g model Authentication --migration=false


app/models/user.rb に設定を追加する。

f:id:matt-note:20190707203332p:plain

 

app/models/authentication.rb に関連を追加する。

f:id:matt-note:20190707231934p:plain

 

app/views/layouts/application.html.erb にログイン用のリンクを配置する。

f:id:matt-note:20190707233951p:plain
 

あとは、公式の Wiki を参考にすれば作成できる。[ link ]

oauth用のコントローラーを作成する。

  • bin/rails g controller Oauths oauth callback

 

app/controllers/oauths_controller.rb

f:id:matt-note:20190707230632p:plain

 

config/routes.rb

f:id:matt-note:20190707234256p:plain

 

サーバーを起動して、「GitHubログイン」のリンクをクリックする。

f:id:matt-note:20190707234448p:plain

-> sorcery で GitHub ログインを実装できた。

 

user_info_mapping がうまくいかない?

コンソールを起動して、User を確認してみる。

f:id:matt-note:20190708124101p:plain

-> email に名前が入りこんで、name が nil になる。

 

User に name 属性を作成して、config/initializers/sorcery.rb で email に email、name に name を割り当てたが、うまくいかない。

 

この点を解決できなかった。