20210123のRailsに関する記事は20件です。

Railsのマイグレーション関連のコマンドをまとめてみた

開発環境

・Rails6.0.0

マイグレーションファイルの生成とテーブル作成

マイグレーションファイルの生成は次の2パターン

①モデルを生成して自動で作られる場合

【コマンド】rails generate model モデル名
これにより、「db/migrate」の中に自動的にマイグレーションファイルが生成される。

②自分で作る

既存のテーブルにカラムを追加したい場合など。
(例)usersテーブルにnameカラム(型:string)を追加したい場合
【コマンド】rails generate migration add_name_to_users name:string

テーブルの作成

【コマンド】rails db:migrate
これでマイグレーションファイルの内容がテーブルに反映される。
結果はSequel Proなどでデータベースを更新して確認できる。

ちなみにターミナル上でマイグレーションファイルがテーブルに反映されているか確認することもできる。
【コマンド】rails db:migrate:status
実行結果
「Status」が「up」になっていればテーブルに反映されている状態、「down」になっていればまだmigrateされていない状態です。

マイグレーションを取り消したい時

開発中に、マイグレーションファイルの編集が完了していないのにrails db:migrateを先走って実行してしまった場合など。
パニックにならずに以下のコマンドを実行しましょう。
【コマンド】rails db:rollback

これにより上の画像の「Status」の部分が「up」から「down」に変更され、migrateする前の状態に戻ります。これでマイグレーションファイルを再度編集できるようになります。

※厳密にはマイグレーションファイルは編集しようと思えばいつでも編集できますが、「up」状態のマイグレーションファイルを編集してしまうとエラーの原因になるので必ずrollbackしてから編集し、再度migrateしましょう。

「up」状態のマイグレーションファイルを削除してしまったら?

①削除されたファイルの代わりとなる仮のマイグレーションファイルを生成

rails db:migrate:statusを実行し、削除済みファイルの「Migration ID」を確認したうえで同じIDを持つマイグレーションファイルを作成。
ファイル名: 「(MigrationID).sample.rb」など

②以下のコマンドが実行できるようになるので、実行。

【コマンド】rails db:rollback

③以下のコマンドでマイグレーションの状態を確認。

【コマンド】rails db:migrate:status
①で仮作成したマイグレーションファイルの「Status」が「down」になっていることが確認できる。
この時点で、仮作成したファイルは削除してしまいましょう。

これでテーブルとマイグレーションの状態の整合が取れました!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

findメソッドとfind_byメソッドはどう違うのか

プログラミングスクールの課題アプリ開発の過程で、findメソッドとfind_byメソッドを勘違いしてまる1日エラーに悩まされた経験から、findメソッドとfind_byメソッドについて整理します。

findメソッド

IDを指定してレコードを取得します。
指定したIDの中に存在しないIDが1つでもあると例外(エラー)が発生します。

Fruit.find(1)
# 複数のIDを指定して、該当するレコードを取得できる
Fruit.find(1,4,6)
# 配列でも指定できる
Fruit.find([1,4,6])
# 同一ファイル内にidの情報を含むインスタンスがあれば、以下のような書き方ができる
Fruit.find(@fruit.id)

find_byメソッド

条件を指定してヒットした最初の1件を取得します。IDも条件に指定できます。
条件にヒットするレコードが存在しない場合はnilを返します。

Fruit.find_by(name: "strawberry")

Fruitsテーブルに以下のようにデータが入っているとします。

Fruitsテーブル
| id | name       | color  |
| 1  | apple      | red    |
| 2  | strawberry | red    |
| 3  | orange     | orange |
| 4  | banana     | yellow |

この場合、次のように記述して該当するデータを取得できます。

Fruit.find_by(name: "apple")
Fruit.find_by(name: "orange")
Fruit.find_by(color: "yellow")

個人的なミス経験で恐縮ですが、ぼくはfindメソッドとfind_byメソッドを混同して以下のように記述してエラーに悩まされていました。

Fruit.find(id: @fruit.id)

findメソッドを使っているのに、カッコ()の中はfind_byメソッドの文法で記述していました。

どう違うのか

Railsドキュメントを読んでみると、findメソッドはRailsのバージョン1.0.0から、find_byメソッドはRailsのバージョン4.0.2から適用されているので、歴史的にはfind_byメソッドの方が後から登場したメソッドのようです。

機能的には次のような違いがあります。

  • findメソッドもfind_byメソッドもIDを指定してレコードを取得することができる
  • findメソッドはIDを複数指定していれば複数の値を取得できるが、find_byメソッドは1つのレコードしか取得できない
  • find_byメソッドはID以外の条件を指定してレコードを取得できる

結論としては、こんな感じでしょうか。

取得したいレコード 使用するメソッド
1つ findメソッド・find_byメソッド
1つ&IDを指定 findメソッド・find_byメソッド
複数&IDを指定 findメソッドのみ
1つ&ID以外を指定 find_byメソッドのみ
複数&ID以外を指定 ???

最後のパターンで???が出ました。
このパターンは、findメソッドでもfind_byメソッドでも取得できません。
このときはどうすればよいでしょうか?

Whereメソッド

取得したいレコードが「複数&ID以外を指定」の場合はWhereメソッドを使用することで実行可能です。

whereメソッドは条件に当てはまる値を全て取得します。

@fruit = Fruit.where(name: "strawberry")

ここまでみるとwhereメソッドがなんでもできて最強じゃないかとも思いますが、findとfind_byメソッドにはできて、whereメソッドにはできないことがあります。

# findとfind_byメソッドで取得した値は、特定のカラムを取得できる
@fruit = Fruit.find(1) # もしくは、@fruit = Fruit.find_by(name: "strawberry")
@fruit.name
# 実行結果 => "strawberry"

# whereメソッドで取得した値は特定のカラムを取得できない
@fruit = Fruit.where(name: "strawberry")
@fruit.name
# 実行結果 => NoMethodErrorになる

findメソッドとfind_byメソッドはモデルのインスタンスを返すのに対し、whereメソッドは範囲をしぼるだけなので、インスタンスがありません。

そこで以下のような方法で、範囲を絞った中でどれを使うか指定することで特定のカラムを取得できるようになります。

@fruit = Fruit.where(name: "strawberry").first(1)
@fruit.name
# 実行結果 => "strawberry"

@fruit = Fruit.where(name: "strawberry").take(1)
@fruit.name
# 実行結果 => "strawberry"

@fruit = Fruit.where(name: "strawberry")
@fruit.each do |fruit|
 fruit.name
end
# 実行結果 => "strawberry"

参考資料

Railsドキュメント モデルについて
Qiita【Rails初心者必見!】ひたすら丁寧にデータ取得を説明(find, where)
Qiita【Rails】findとfind_byの違い
Qiita【Rails】find・find_by・whereについてまとめてみた

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsアプリのための環境構築

構築済の環境

  • Homebrewのインストール
  • rbnevのインストール
  • Rubyのインストール(2.7.2)
  • node.jsのインストール

RubyGemsのアップデート

Rubyのサードパーティライブラリの利用で、プログラミングが楽になるようです。
これらは「gem」という形式で配布されています。
「RubyGems」というパッケージ管理ツールはRubyインストール時に同梱されるようです。

最新版へのアップデートは以下のコマンド。

$ gem update --system

Bundlerのインストール

開発現場では、gemの管理が重要になってきます。
そこで登場するのが「Bundler」プロジェクトで用いるgemをまとめ、互換性を保ちながらパッケージの種類やバージョンを管理してくれます。
プロジェクトのディレクトリに「Gemfile」というファイルを作成し,gemの名前を記載しておくと、うまくやってくれます。

以下のコマンドでインストール

$gem install bundler

今後はBundler経由でgemに関する操作をすることで、メンバーとの環境を同様にすることができます。
(gemコマンドで直接操作してしまうと、Bundlerの管理環境から逸脱してしまうようです)

データベース(MySQL)のインストール

今回はMySQlを利用します。

brew install mysql

インストール後、起動させます。

mysql.server start

(以下でもOK?)

brew services start mysql@バージョン

「SUCCESS」と表示されれば起動完了です。

データベース(MySQL)のインストール

今回はMySQlを利用します。

brew install mysql

インストール後、起動させます。

mysql.server start

(以下でもOK?)

brew services start mysql@バージョン

「SUCCESS」と表示されれば起動完了です。

MySQLの初期設定

起動状態で以下のコマンド入力をして、初期設定をおこないます。

mysql_secure_installation

いくつか設定項目が続きます。順番は以下の通りです。

1.パスワード設定を行うか問われるのでyを入力。

2.パスワードの強度を設定。練習なので「0」のLowを選択。

3.パスワードを2回入力し、設定完了。

4.「匿名ユーザー」を削除するかの質問。これはMySQLをインストールした際に自動で作成されるユーザーアカウントで、パスワード不要でMySQLに接続することが可能。
セキュリテイ上のリスクがあるためyを入力。

5.「root」ユーザー(初期設定)へのログインをリモートサーバーから可能にするかの確認。
同様にセキュリテイ上のリスク回避のためyを入力。

6.デフォルトのテストデータベースを削除するかの確認。使用しないのでyを入力。

7.これまでの設定内容を即時にデータベースに反映するかの確認。yを入力。

これで設定は完了です。

MySQLへのログイン・ログアウト・停止

設定したパスワードでログインします。

mysql -uroot -p

ログアウトは、

exit;

「Bye」と表示されればログアウト完了です。

MySQL自体の停止は、

brew services stop mysql@バージョン名

「Successfully stopped msyql@」と表示されれば停止完了です。

ここまで、環境構築は終了です。長かった…
次回はRailsアプリの新規作成までを記事にしていきます。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails 検索機能の実装

1.ルーティングの指定

ルーティングの中に検索したいテーブルの中にserchを記述します。以下を例とします。collectionを使うことによって生成されるルーティングのURLと実行されるコントローラーを任意でカスタムできます。

config/routes.rb
resources :posts do
      collection do
        get 'search'
      end
  end

2.モデルの指定

モデルを指定します。以下のようにwhereメソッドとLIKE句を使い、検索をかけたいカラムを記述します。

post.rb
def self.search(search)
        if search != ""
          Post.where('text LIKE(?)', "%#{search}%" )
        else
          Post.all
        end
      end

3.この他に検索のカラムを追加したいとき

もしいくつかのカラムを検索につかしたいときは、orを使い"%#{search}%"以下のように記述しましょう。

post.rb
def self.search(search)
        if search != ""
          Post.where('text LIKE(?) or title LIKE(?)', "%#{search}%", "%#{search}%")
        else
          Post.all
        end
      end

4 コントローラーにserchアクションを記述

コントローラーにsearchアクション記述をします。この記述でバックエンドの記述は終了です。あとはビューに反映させるだけなので、お好みの形でデザインしましょう。

controllers/posts_controller.rb
def search
 @post = Post.search(params[:keyword])
end

5.最後に

検索機能自体は他のアクションと同じように設定できますので、モデルの指定だけ特徴をつかめば簡単に実装できます。是非実装してみましょう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

$ rails db:seedを用いて初期データを格納

この記事/メモについて(はじめに)

Twitterの呟きやそれに対するリプライ・コメントは、「ユーザーが送信した情報」をデータとしてデータベースに保存する、と言った仕組みのものです。
しかし、データベースへ格納するデータは必ずしもユーザーや第三者が投稿・送信してきたものだけとは限りません。

例えば、自分が行ったことのあるおすすめの国について紹介するWebサイトを制作しようとした時。
このサイトでは、ユーザーが「ここの国はおすすめだよ!」「この地域の料理、とても美味しかった!」と呟いたものではなく、開発者のみなさんが現地で感じた思いやおすすめのポイントなどを掲載したいですよね。

本記事では、そんな方々のために、開発者が裏側からデータを格納する方法についてご紹介しようと思います。

手順 (2Stepで簡単にできます!)

裏側からのデータの格納は、

①seedファイルに保存したい初期データを記述
②「$ rails db:seed」というコマンドを入力する

という実に簡単な方法で行うことができます。
①番の記述の仕方を抑えてしまえば、特に難しい内容はありません。以下で詳しく説明していきます。

Step1 seedファイルに保存したい初期データを記述

例として、Countries(プロダクトに合わせて変更)テーブルに開発者側からデータを入れる場合を考えます。
Countriesテーブルには、nameカラムと、説明のためのbodyカラム、さらに滞在日数を表すdayカラムとその予算(万円)を示すbudgetカラムが存在しているとします。

ここでは、表のような情報を開発者が入れる初期データとして保存していこうと思います。

ID name   body day budget
1 韓国   低予算で初海外旅行におすすめ! 3日 5
2 スペイン   自然より建物好きならヨーロッパ! 1週間 15
3 シンガポール チキンライスは外せない! 4日半 10

保存形式は以下の通りです。文字列と整数が混在している場合を考えます。
・name → 文字列(string型)
・body → 長い文字列(text型)
・day → 文字列(string型)
・budget → 整数(integer型)

このようなデータをCountriesテーブルに保存したい時、まずdb/seeds.rb内に以下のように記述します。

db/seeds.rb
Country.create!(name: '韓国', body: '低予算で初海外旅行におすすめ!', day: '3日', budget: 5)
Country.create!(name: 'スペイン', body: '自然より建物好きならヨーロッパ!', day: '1週間', budget: 15)
Country.create!(name: 'シンガポール', body: 'チキンライスは外せない!', day: '4日半', budget: 10)

レコード1つにつき1行分必要となるイメージです。(たくさんのレコードを保存させたい場合に合わせて、より効率の良い書き方もあります。他にも様々な書き方があるので、是非調べてみてください!)

?1point豆知識?
整数(integer型)で保存するbudgetについて、値を「""」や「''」で囲っていないことに注意してください。
→seedsファイルに限らず、プログラミングの世界ではダブル/シングルクオーテーションを用いて囲ったものは基本的に文字列として認識されてしまうので、エラーが生じてしまいます。

Step2 seedファイルに記述した内容をデータベースに反映させる

ターミナル、またはコマンドプロンプトで以下のコマンドを実行することで、db/seeds.rbに記した内容をデータベースに反映することができます。

$ rails db:seed

以上です!簡単でしたね!

Step3 データベース内のデータを確認/削除する

データベースに保存されているデータについて確認/削除したいとき、$ rails cというコマンドを実行します。($ rails cを終わりにする際はexitと入力してEnterを押してください。)

こちらの内容はseeds.rbを用いて初期データを格納する場合以外でも頻出のコマンドとなるので、別記事に軽くまとめるつもりです。(気が向いたら。。)

======

$ rails cは頻出のコマンドとなるので、データの確認/削除は「$ rails c」!!と自分に三回言い聞かせましょう。

データの確認

以下のようにコマンドを入力してください。Countriesテーブルに保存されているデータが出力されるはずです。

$ rails c
irb(main):001:0> Country.all

# => 保存されているデータの出力(確認)

データの削除

以下のようにコマンドを入力すると、今度はCountriesテーブルに保存されているデータを全て削除することができます。

$ rails c
irb(main):001:0> Country.delete_all

# => 保存されているデータの削除

参考

railsのseedの書き方いろいろ
https://qiita.com/takehanKosuke/items/79a66751fe95010ea5ee

【Rails】CarrierWave + seedで初期データに画像ファイルを投入する
(CarrierWaveをすでに実装している方のうち、初期データに画像を入れたい方はこちらの記事が大変わかりやすいのでぜひ見てください!)
https://remonote.jp/rails-carrierwave-seed

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby on RailsでWebpackerのエイリアスを設定する方法

config/webpack/environment.js
const { resolve } = require('path')

environment.config.merge({
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('app/javascript/packs'),
      '&': resolve('app/javascript/packs/components'),
    },
  },
})

サーバーの再起動が必要です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

オリアプの要件定義

要件定義

前回は、オリアプの企画を考えてました。
今回からは、実際にアプリケーションの仕様や要件を洗い出して行きます。

ここで要件定義の説明です。↓
要件定義とは、開発者などがアプリケーションの仕様を把握するために、詳細まで言語化することです。
ユーザーストーリーの段階では、人によってそれぞれの機能の「完成形のイメージ」が異なります。
このままでは、数人で開発する場合に上手くいきません。したがって、開発に関わる人全員で共通認識を持つために、要件を定義していく必要があります。

私はアプリケーションの詳細を言語化することは容易ではないと思い、画面遷移図を書き出してみました。
オリアプ遷移図.png
多分ツッコミどころ万歳な遷移図ですが、ひとまずこれで、
これを元に言語化していこうと思います。

・ログイン、サインイン
 ・ログインする入力フォーム
 ・サインイン(新規登録)をするページへのリンク
 (・アカウントを持ってるユーザーのみトップページに)
 ・SNSからログインするボタン

・トップページ
 【ボタン】
   ・userの情報の詳細ページに遷移するボタン
   ・projectsの内容を表示するボタン
   ・projectsに情報を追加するフォーム
   ・projectsの内容に対するチェックボックス

 【表示】
   ・ログインしているuserの名前の表示
   ・参加しているprojects名の一覧の表示
   ・projectsの内容の表示

・サインインページ
 【ボタン】
   ・ユーザー登録できるボタン(SEND)

 【表示】
   ・ユーザーの情報を入力するフォーム

とりあえずこんな感じでいいでしょう。
次は設計と言われるDBの設計をしていこうと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【画像付き】RailsでDeviseを利用してLINEログイン機能を実装

はじめに

自作アプリでLINEBotを作成する際にLINEログイン機能を実装しました。

実装するに当たって様々な記事を参考にさせて頂きましたが, 記事によって記述が異なったり, ここはもう少し簡潔に書けるのでは?と思ったり, 記事通りに書いてもエラーが出たり, そもそも記事が古かったりで苦労しました。。

今後また実装する時に自分の記事さえ見れば導入できるように画像付きでまとめていきたいと思います!

基本的にRailsを想定していますが, LINE Developersの登録などはRails以外の言語でも参考になる部分があるかと思いますので, 少しでも参考になれば幸いです?

0.導入方法

導入方法はおおまかに以下の4つです。順を追って説明します。

1.Railsアプリを作成
2.Deviseを導入
3.LINE Developersに登録
4.LINEログイン機能を導入
5.LINEログイン詳細設定

1. Railsアプリを作成

  • 以下の前提で進めていきます。(アプリやコントローラー名は任意の名前にして下さい)
  • postgresqlに設定していますが, データベースはお好みで。
ターミナル
rails new linelogin_sample -d postgresql
rails db:create
rails g controller homes index
config/routes.rb
Rails.application.routes.draw do
  root 'homes#index' 
end

ここまで出来たら rails s でサーバーを起動して http://localhost:3000 にアクセスし, 動作確認を行ってみて下さい。エラーが表示されていなければOKです!

2.Deviseを導入

LINEログイン機能の前に, まずはDeviseでログイン機能を実装していきます。

2-1.Gemfileの編集とインストール

Gemfile
# ログイン機能
gem 'devise'

Gemfileを編集したらターミナルで bundle install を実行

2-2.Deviseをインストール

【公式】 plataformatec/devise

ターミナル
rails g devise:install
rails g devise User
rails db:migrate

(※ userの箇所は,任意のモデル名でOKです)

問題がなければ rails s でサーバーを立ち上げ,http://localhost:3000/users/sign_in にアクセスすると,ログイン画面が表示されます。
(すでにサーバーを起動している場合は再起動して下さい。)

スクリーンショット 2020-10-21 16.55.41.png

3.LINE Developersに登録

LINEログイン機能を実装するには LINE Developersに登録する必要があります。
まだ登録されてない方はこちらのURL ( https://developers.line.biz/ja/ ) からログイン画面に遷移し, LINEの登録時に設定したメールアドレスとパスワードでログインします。

登録が完了するとこのような画面が表示されるので, LINEログインを選択し, 今すぐはじめよう というボタンをクリックしてください。
スクリーンショット 2020-10-21 17.04.16.png

今すぐはじめよう をクリックすると新規プロバイダーを作成する画面が出てきますので, 必要な項目を入力し, プロバイダーを作成してください。

例えば, アンケートBotというアプリにLINEログイン機能を導入する場合は画像のように入力していきます。

スクリーンショット 2020-10-21 17.30.26.png

スクリーンショット 2020-10-21 17.30.35.png

スクリーンショット 2020-10-21 17.30.44.png

上記はあくまで一例です。

プロバイダー名, チャネルアイコン, チャネル名, アプリタイプなどは任意のものにしてください。

4.LINEログイン機能を導入

LINE Developersで新規プロバイダーを作成したら, いよいよLINEログイン機能を実装していきます!

4-1.Omniauthのインストール

Gemfileに以下を追加し, bundle install を実行。

Gemfile
gem 'omniauth-line'

4-2.環境変数を設定

次にChannel IDとChannel Secretの設定を行います。
今度はGemfileに以下のgemを追加し, bundle install を実行してください。

Gemfile
gem 'dotenv-rails'

gemを追加したら, アプリのルート配下に .env ファイルを作成し, 以下の2つを追加してください。

.env
LINE_KEY='自身のChannel ID'
LINE_SECRET='自身のChannel Secret'

▼環境変数の確認
スクリーンショット 2020-10-21 22.13.55.png

スクリーンショット 2020-10-21 22.14.10.png

【注意!】
このファイルを公開してしまうと悪用されてしまう可能性があるので, 必ずGitの管理下から外してください。
.gitignore に以下を追加

.gitignore
/.env

4-3.DeviseとLINEログインの設定

次にDeviseの設定ファイルにLINEログインの設定を行います。

  • 以下を追加
devise.rb
config.omniauth :line, ENV['LINE_KEY'], ENV['LINE_SECRET']
  • :omniauthableomniauth_providers: %i[line] を追加 (TwitterやFacebookログインなども導入する場合は %i[line] の配列に追加してください)
user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :omniauthable, omniauth_providers: %i[line]
end

4-4.コントローラーの設定

  • omniauth_callbacks_controllerを作成します。
ターミナル
rails g controller omniauth_callbacks

【注】OmniAuthのバージョンが原因でエラーが出ることがあります。

▼バージョンエラーが出た場合の対処

Gemfile
gem 'omniauth', '~> 1.9.1'

Gemfileに上記のコードを追加し, ターミナルで bundle update

bundle update でomniauthのバージョンが変わったのを確認したら, bundle install を実行。
再度 rails g コマンドでコントローラーを作成して下さい。

  • 以下を修正
omniauth_callbacks_controller.rb
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def line; ; end
end

4-5.ルーティングの設定

  • 以下のようにルーティングを設定します。
routes.rb
devise_for :users, controllers: {
  omniauth_callbacks: "omniauth_callbacks"
}

ルーティングを rails routes で確認し、

user_line_omniauth_authorize GET|POST /users/auth/line(.:format)               omniauth_callbacks#passthru
user_line_omniauth_callback GET|POST /users/auth/line/callback(.:format)       omniauth_callbacks#line

このような表示がされていたらルーティングの設定は完了です!

4-6.モデルの変更

DeviseでUserモデルを作成しているのでそのままUserモデルに変更を加えてLINEログインができるようにしたいと思います。

  • 以下のコマンドでマイグレーションファイルを作成
ターミナル
rails g migration add_column_to_users
  • 作成されたマイグレーションファイルに以下を追加
db/migrate/20201022073739_change_column_to_user.rb
class ChangeColumnToUser < ActiveRecord::Migration[6.0]
  def change
  # 以下を追加
    add_column :users, :provider, :string
    add_column :users, :uid, :string
    add_column :users, :name, :string
  end
end

マイグレーションファイルを編集したら rails db:migrate でマイグレーションを実行してください。

4-7.Userモデルの編集

  • 以下を追加
user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :omniauthable,
         omniauth_providers: %i[line]

  # 以下を追加
  def social_profile(provider)
    social_profiles.select { |sp| sp.provider == provider.to_s }.first
  end

  def set_values(omniauth)
    return if provider.to_s != omniauth["provider"].to_s || uid != omniauth["uid"]
    credentials = omniauth["credentials"]
    info = omniauth["info"]

    access_token = credentials["refresh_token"]
    access_secret = credentials["secret"]
    credentials = credentials.to_json
    name = info["name"]
    # self.set_values_by_raw_info(omniauth['extra']['raw_info'])
  end

  def set_values_by_raw_info(raw_info)
    self.raw_info = raw_info.to_json
    self.save!
  end
  # 以上を追加
end

4-8.コントローラーを編集

  • classの ApplicationControllerDevise::OmniauthCallbacksController に変更するのを忘れないように!
omniauth_callbacks_controller.rb
# ApplicationController を Devise::OmniauthCallbacksController に変更
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
  # 以下を追加
  def line; basic_action end

  private
  def basic_action
    @omniauth = request.env["omniauth.auth"]
    if @omniauth.present?
      @profile = User.find_or_initialize_by(provider: @omniauth["provider"], uid: @omniauth["uid"])
      if @profile.email.blank?
        email = @omniauth["info"]["email"] ? @omniauth["info"]["email"] : "#{@omniauth["uid"]}-#{@omniauth["provider"]}@example.com"
        @profile = current_user || User.create!(provider: @omniauth["provider"], uid: @omniauth["uid"], email: email, name: @omniauth["info"]["name"], password: Devise.friendly_token[0, 20])
      end
      @profile.set_values(@omniauth)
      sign_in(:user, @profile)
    end
    flash[:notice] = "ログインしました"
    redirect_to root_path
  end

  def fake_email(uid, provider)
    "#{auth.uid}-#{auth.provider}@example.com"
  end
  # 以上を追加
end

これで設定は完了です!
http://localhost:3000/users/sign_in にアクセスすると Sign in with Line が追加されていると思います。

スクリーンショット 2020-10-24 18.01.47.png

ただし, 今の状態ではクリックしてもログインできません。LINE Developers側の詳細設定をしていきましょう!

5.LINEログイン詳細設定

5-1. コールバックURL

ログイン時のコールバックURLを設定していきます。

LINE Developersの任意のプロバイダーからLINEログイン設定を開いてください。
コールバックURLを設定するフォームがありますので, そこに入力していきます。

スクリーンショット 2020-10-26 16.43.38.png

基本は https://アプリ名/users/auth/line/callback で大丈夫です!
念のため rails routes で URI Pattern を確認してみてください。
スクリーンショット 2020-10-26 17.10.47.png

ここで注意して欲しいのが, LINEログインを使用する際のURLは https でないといけないということです!
http://localhost3000/users/auth/line/callback のようには設定できません。

なので開発環境で動作確認を行う際は一工夫しなければなりません。
開発環境でも動作確認を行いたい場合は次の ngrok を参考にしてください。
(ngrokはあくまで一例ですので, 他にも色々やり方はあります。必要のない方は読み飛ばして下さい!)

5-2.ngrok

ngrok はlocalhostに外部から接続できるようにするというサービスです。
簡単に導入できますので説明していきます。

  • 以下のコマンドで ngrok をインストールしてください
ターミナル
brew cask install ngrok

インストールが終了したらバージョン確認をしてみてください。
以下のようにバージョンが表示されればOKです!

❯ ngrok -v
ngrok version 2.3.35

ngrokのインストールが終わったら、外部アクセス用 https のURLを発行しましょう。
以下のコマンドを実行してください。

ターミナル
ngrok http 3000

( 3000 はポート番号なので適宜変更してください。)

コマンドを実行するとこのような感じで表示されると思います。

スクリーンショット 2020-10-26 17.37.25.png

こちらで表示された http://xxxxxxxx.ngrok.io で外部からlocalhostのWebサーバーにアクセスすることが可能になります。

今回は https で接続したいので下の方の https://xxxxxxxx.ngrok.io をコールバックURLに指定してください。

スクリーンショット 2020-10-26 17.48.10.png

【注】ngrokで作成したURLには使用制限があり, 発行して8時間が経過すると, 設定したURLではアクセスできなくなってしまいます。その際は再度 ngrok http 3000 を実行し, 発行されたURLでコールバック先を指定し直してください。

→ 以前は8時間だったのですが, 2時間に短縮されているかも。。LINEログインの動作確認だけだと2時間で十分かと思いますが, 他に便利なサービスがあれば追記します?

【Rails6の場合】

Rails6から保護機能が強化され, ngrokで発行したホスト名ではアクセスできないので, 許可したいホスト名をRailsアプリ側に登録しなければなりません。
(Rails5を使用されている方はこちらは読み飛ばして頂いて大丈夫です。)

それではngrokで作成したホストをRailsのアプリに登録していきます。

config/environments/development.rb に下記を記載し、ホワイトリストに許可したいhostを追加すればOKです!
許可したいホスト名には xxxxxxxx.ngrok.io の部分を追加してください。

config/environments/development.rb
Rails.application.configure do
  # 以下を追加
  config.hosts << "許可したいホスト名"
end

ただ先ほど説明したように, ngrokは期限が切れるたびに違うURLを発行し直さなければなりません。

そうすると許可したいホスト名も毎回書きかえないといけなくなりますので, 以下の方法も紹介しておきます。

config/environments/development.rb
Rails.application.configure do
  # 以下を追加
  config.hosts.clear
end

これにより, すべてのホスト名に対するリクエストを通過させることができます。
(ただしせっかくRails6で追加された保護機能を無効化してしまうため、どちらを選択するかはお任せします。)

ここまでの設定が完了したらngrokで発行したURLにアクセスできるようになります!
すでにサーバーを起動している場合は再起動し, 実際にURLにアクセスして確認してみてください。

スクリーンショット 2020-10-26 23.01.06.png

【注】ngrokとlocalhostのサーバーは同時に起動させてください。終了させる時はどちらも Ctrl + C で終了できます。

5-3.チャネルの公開

最後に, 作成したチャネルを公開していきます!

上の方に表示されている 非公開 ボタンをクリックすると「チャネルを公開しますか?」という表示が出てきますので, 公開をクリックしてください。
スクリーンショット 2020-10-26 17.52.55.png

きちんと公開できていれば 公開済み に切り替わります。
スクリーンショット 2020-10-26 17.53.04.png

ここまで設定したらLINEログインの設定は終了です!!!
ログイン画面の Sign in with Line をクリックするとログイン画面が表示されますので, そちらからログインできるようになります!
(初回ログインの際は, LINE登録時のメールアドレスとパスワードを求められる場合があります)

スクリーンショット 2020-10-26 22.03.12.png

Messaging API を利用してLINEBotなどを作る場合, LINEログイン機能は大変便利だと思いますので, 少しでも導入する際の参考になれば幸いです。

仕様の変更や補足があれば随時更新していきたいと思います!
お疲れさまでした〜!✨

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ubuntu Rails Widowsで環境構築をしたよ(2021年版)

経緯

DockerやCloud9での環境構築しかしてこなかったためUbuntuでも作りたいなと思い
この記事を書くことを決めました。

【環境】
・Windows10 home
・Ruby 2.5.1
・Rails 5.2.1
・PostgeSQL

WSLの有効とUbuntuのインストール

1 WindowsでLinux環境を利用するためにWSLを有効
設定>「Windowsの機能の有効化または無効化」を入力>Windows Subsystem for Linux に☑

2 Ubuntuのインストール
「Microsoft Store」を開いて「Ubuntu」を検索 > インストールをし起動

起動時には「Installing,this may take a few minutes...」と表示されるのでしばらく待ちます。
その後、ログインユーザの作成のためにユーザ名とパスワードを求められるので入力しましょう!
入力を終えたら最新の状態にするために以下のコマンドを入力します。

ターミナル
sudo apt update
sudo apt upgrade -y

rbenvをインストールしよう

rbenvを使うことでRubyの管理が簡単になるほか複数のバージョンのRubyを
自在に切り替えることができます。

ターミナル
git clone https://github.com/rbenv/rbenv.git ~/.rbenv

次にrbenvコマンドを利用できるようにするため、パス設定と初期化処理を.bash_profileに追加します。

ターミナル
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc

Ubuntuを終了して、再度立ち上げ以下のコマンドでバージョンが表示されたらインストールできています。

ターミナル
rbenv -v

次にrbenvでのRubyのインストールを簡単にするプラグイン、ruby-buildをセットアップします。

ターミナル
git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build

最後にRubyのインストールのために必要なパッケージをインストールしましょう。

ターミナル
sudo apt-get install autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm6 libgdbm-dev libdb-dev

Rubyのインストール

今回のRubyのバージョンは2.5.1なので以下のコマンドを入力します。

ターミナル
rbenv install 2.5.1
rbenv global 2.5.1
ruby -v
=>ruby 2.5.1とでればOK

Bundlerのインストール

ターミナル
gem install bundler

Railsのインストール

ターミナル
gem install rails -v 5.2.1
rails -v
=>Rails 5.2.1とでればOK

Node.jsのインストール

ターミナル
sudo curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt install nodejs

データベースのインストールとセットアップ

ターミナル
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list
wget --quiet -0 - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt-get update
sudo apt install postgresql

次にインストールの確認、Postgresqlを起動、開発環境用のユーザを作成します。

ターミナル
psql -v
sudo service postgresql start
sudo su postgres -c 'createuser -s ubuntuのログインユーザ名'
sudo apt install libpq-dev

以上です。ありがとうございました!

今後の予定

・ubuntuで作った環境をVscodeで再現

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Railsチュートリアル】第2章 Toyアプリケーション 演習と回答

演習と回答

2.2.1 ユーザーページを探検する

2.2.1 - 1

CSSを知っている読者へ: 新しいユーザーを作成し、ブラウザのHTMLインスペクター機能を使って「User was successfully created.」の箇所を調べてみてください。ブラウザをリロードすると、その箇所はどうなるでしょうか?

<p id="notice">User was successfully created.</p>

リロード前は上のようになっていて

<p id="notice"></p>

リロードしたあとはUser was successfully created.が消えて空白になっていた。

2.2.1 - 2

emailを入力せず、名前だけを入力しようとした場合、どうなるでしょうか?

名前だけでも登録ができる。

2.2.1 - 3

「@example.com」のような間違ったメールアドレスを入力して更新しようとした場合、どうなるでしょうか?

更新できる。

2.2.1 - 4

上記の演習で作成したユーザーを削除してみてください。ユーザーを削除したとき、Railsはどんなメッセージを表示するでしょうか?

User Destroy (1.1ms)  DELETE FROM "users" WHERE "users"."id" = ?  [["id", 3]]

などと表示される。

2.2.2 MVCの挙動

2.2.2 - 1

図 2.11を参考にしながら、/users/1/edit というURLにアクセスしたときの振る舞いについて図を書いてみてください。

割愛。

2.2.2 - 2

図示した振る舞いを見ながら、Scaffoldで生成されたコードの中でデータベースからユーザー情報を取得しているコードを探してみてください。Hint: set_userという特殊な場所の中にあります。

private
  # Use callbacks to share common setup or constraints between actions.
  def set_user
    @user = User.find(params[:id])
  end

2.2.2 - 3

ユーザーの情報を編集するページのファイル名は何でしょうか?

edit.html.erb

2.3.1 マイクロポストを探検する

2.3.1 - 1

CSSを知っている読者へ: 新しいマイクロポストを作成し、ブラウザのHTMLインスペクター機能を使って「Micropost was successfully created.」の箇所を調べてみてください。ブラウザをリロードすると、その箇所はどうなるでしょうか?

<p id="notice">Micropost was successfully created.</p>

リロード前は上のようになっていて

<p id="notice"></p>

リロードしたあとはMicropost was successfully created.が消えて空白になっていた。

2.3.1 - 2

マイクロポストの作成画面で、ContentもUserも空にして作成しようとするどうなるでしょうか?

作成できる。

2.3.1 - 3

141文字以上の文字列をContentに入力した状態で、マイクロポストを作成しようとするとどうなるでしょうか?(ヒント: WikipediaのRubyの記事にある設計思想の引用文が140文字を超えているので、これをコピペしてみましょう)

作成できる。

2.3.1 - 4

上記の演習で作成したマイクロポストを削除してみましょう。

それぞれ削除しました。

2.3.2 マイクロポストをマイクロにする

2.3.2 - 1

先ほど2.3.1.1の演習でやったように、もう一度Contentに141文字以上を入力してみましょう。どのように振る舞いが変わったでしょうか?

作成できず、エラーメッセージが出るようになった。

2.3.2 - 2

CSSを知っている読者へ: ブラウザのHTMLインスペクター機能を使って、表示されたエラーメッセージを調べてみてください。

<textarea name="micropost[content]" id="micropost_content">Ruby には Perl や Python とは決定的に違う点があり、それこそが Ruby の存在価値なのです。それは「楽しさ」です。私の知る限り、Ruby ほど「楽しさ」について焦点を当てている言語は他にありません。Ruby は純粋に楽しみのために設計され、言語を作る人、使う人、学ぶ人すべてが楽しめることを目的としています。しかし、ただ単に楽しいだけではありません。Ruby は実用性も十分です。実用性がなければ楽しめないではありませんか。
— まつもとゆきひろ、Ruby プログラミング入門 まえがき 監修者よりのページ</textarea>

2.3.3 ユーザーはたくさんマイクロポストを持っている

2.3.3 - 1

ユーザーのshowページを編集し、ユーザーの最初のマイクロポストを表示してみましょう。同ファイル内の他のコードから文法を推測してみてください(コラム 1.2で紹介した技術の出番です)。うまく表示できたかどうか、/users/1 にアクセスして確認してみましょう。

first_user.microposts
  Micropost Load (0.1ms)  SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? LIMIT ?  [["user_id", 1], ["LIMIT", 11]]
 => #<ActiveRecord::Associations::CollectionProxy [#<Micropost id: 7, content: "hi!", user_id: 1, created_at: "2021-01-23 06:05:27", updated_at: "2021-01-23 06:05:27">]> 
2.6.3 :006 > 

2.3.3 - 2

リスト 2.18は、マイクロポストのContentが存在しているかどうかを検証するバリデーションです。マイクロポストが空でないことを検証できているかどうか、実際に試してみましょう(図 2.17のようになっていると成功です)。

できたので割愛。

2.3.3 - 3

リスト 2.19のFILL_INとなっている箇所を書き換えて、Userモデルのnameとemailが存在していることを検証してみてください(図 2.18)。

user.rb
class User < ApplicationRecord
  has_many :microposts
  validates :name, presence: true
  validates :email, presence: true
end

2.3.4 継承の階層

2.3.4 - 1

Applicationコントローラのファイルを開き、ApplicationControllerがActionController::Baseを継承している部分のコードを探してみてください。

application_controller.rb
class ApplicationController < ActionController::Base #この行
  def hello
    render html: "hello, world"
  end
end

2.3.4 - 2

ApplicationRecordがActiveRecord::Baseを継承しているコードはどこにあるでしょうか? 先ほどの演習を参考に、探してみてください。ヒント: コントローラと本質的には同じ仕組みなので、app/modelsディレクトリ内にあるファイルを調べてみると...?)

app/models/application_record
class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end

2.3.5 アプリケーションをデプロイする

2.3.5 - 1

本番環境で2〜3人のユーザーを作成してみましょう。
作成できました。

2.3.5 - 2

本番環境で最初のユーザーのマイクロポストを作ってみましょう
作れました。

2.3.5 - 3

マイクロポストのContentに141文字以上を入力した状態で、マイクロポストを作成してみましょう。リスト 2.14で加えたバリデーションが本番環境でもうまく動くかどうか、確認してみてください。

うまく動きました。

さいごに

Railsチュートリアル第2章をクリアしました!
エラーに遭遇しましたが、きちんと文章を読む、検索する、めげない、で解決へたどり着けました。これからもっと難しくおもしろくなってくるようで、楽しみです。

  • MVCモデルを知った
  • RESTアーキテクチャを知った
  • データモデルを作成した
  • Twitterっぽい何かを作ることができた
  • エラーに遭遇しても検索して解決へたどり着けた
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

railsでbootstrapを使う

bootstrapとは

洗練されたWebデザインとユーザーインターフェイス要素を簡単に導入できるCSSのフレームワーク。
最大の特徴はアプリケーションをレスポンシブデザインにできること。

公式サイト

導入

①gemファイルを記入

Gemfile
source 'https://rubygems.org'

gem 'bootstrap', '~> 4.5.0'
.
.
.

スクリーンショット 2021-01-23 17.22.39.png

②ターミナルでbundleをインストールする

$ bundle install

③scssファイル作成

/app/assets/stylesheets/application.scss のファイルを作成。

/app/assets/stylesheets/application.scss
@import "bootstrap-sprockets";
@import "bootstrap";
.
.
.

④コードの記入

bootstrapはclassを特定のコードに書き変えると自動で色や大きさを変えてくれます。

今回はこのボタンにbootstrapを当ててみます。

スクリーンショット 2021-01-23 17.34.29.png

公式サイトのCompornents → buttons の中のこのコードを使います。

スクリーンショット 2021-01-23 17.34.48.png

classの部分をコピーしてコードに貼り付ける。

スクリーンショット 2021-01-23 17.44.48.png

スクリーンショット 2021-01-23 17.44.56.png

サーバーを再起動すると、、、

スクリーンショット 2021-01-23 17.47.02.png

指定したボタンに早変わり!!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[rails]繰り返した処理の回数をclassにインデックスとして付与する方法

初めに

eachメソッドでテーブルから取得してきた値に対してそれぞれ違った処理をしたい!ときってありませんか?

例えば、、、

vegtables = [キャベツ,トマト,なす]

がデータベース上のテーブルに保存されていて、これをeachメソッドを使って値を取得し、"トマト"だけ赤色にしたい、boxの形を変更したい時など。

実装中にハマったので共有します。

結 論

each.with_indexメソッドを使う。

詳 細

コントローラーの記述は以下の通り

vegtables_controller.rb
class VegtablesController < ApplicationController
  def index
    @vegtables = Vegtable.all
  end

なお、vegtablesテーブルのveg_nameカラムには
veg_name=[キャベツ,レタス,きゅうり,トマト,なす,ホウレンソウ,タマネギ,ジャガイモ]
が入っています。

これにそれぞれ異なるclassを与えたいとき

index.html.erb
  <% i=0 %>
  <% @vegtables.each.with_index do |v, i| %>
    <div class="wrapper_<%= ++i %>">
      <%= v.veg_name %>
    </div>
  <% end %>

とすることで実装できました!

因みに、scssに書いたclassのnameは
.wrapper_0{}
.wrapper_1{}
.wrapper_2{}
・・・
などです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails generate scaffoldをしたときに打ち間違いをしてしまったらどうするか

はじめに

Railsチュートリアル第2章で/usersが開けなかったので、原因を調べたら、scaffoldを作成したときに打ち間違いをしていたためでした。

エラーの原因

rails generate scaffold Usser name:string email:string

Userと打ちたかったところをUsserと打ち間違いをしていますね。

エラー解決までの道のり

打ち間違えに気づいたときには、すでにrails db:migrateを実行していたため、まずは変更を取り消しからはじめました。

rails db:rollback

上記のコマンドを実行すると、以下の表示がターミナルに表示されます。

== 20210123005915 CreateUssers: reverting =====================================
-- drop_table(:ussers)
   -> 0.0047s
== 20210123005915 CreateUssers: reverted (0.0122s) ============================

そして、scaffoldを削除します。

rails destroy scaffold Usser

これでrails generate scaffold Usser name:string email:stringを実行する前まで戻ったはずなので、もう一度rails generate scaffoldをします。今度はうち間違えないように慎重に。

rails generate scaffold User name:string email:string

忘れずにmigrateします。

rails db:migrate
== 20210123041232 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0116s
== 20210123041232 CreateUsers: migrated (0.0129s) =============================

無事に表示されました!

さいごに

打ち間違えって怖いですね。一文字でも違っていればアウトですもんね。
でもまぁ確かに、私の名前は「え"ま"」でも「え"も」でもなく「え"む"」ですもんね。
さて、Usserってなんと読むのでしょう。「ゆーずずずぁー」って感じでしょうか。どうでもええがな。

参考にした記事

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

A server is already running. すでにサーバーが動いています。

はじめに

Railsチュートリアル第2章を学習中にRails serverしたあと、誤ってターミナルを閉じてしまい、再度Rails serverをするとエラーがでたのでその解決方法を書いていきます。

エラー内容

=> Booting Puma
=> Rails 6.0.3 application starting in development 
=> Run `rails server --help` for more startup options
A server is already running. Check /home/ubuntu/environment/toy_app/tmp/pids/server.pid.
Exiting

【翻訳】
=> プーマを起動する
=> 開発中のRails6.0.3アプリの開発開始
=> rails server --help を実行すると、起動時のオプションが増えます。
すでにサーバーが動いています。/home/ubuntu/environment/toy_app/tmp/pids/server.pidを確認してください。
終了する

翻訳サイト: DeepL

エラー解決までの道のり

/home/ubuntu/environment/toy_app/tmp/pids/server.pidを確認してください。
とあるので、確認してみるとポート番号が書いてあったので、強制終了します。

kill -9 [ポート番号]

rails serverで再起動をして、無事解決できました!

参考にした記事

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails × Ajaxでクリックする度booleanが反転するボタンを実装する

はじめに

Railsで非同期通信をする際、リロードせずにbooleanを反転させたいケースがあり、やり方がわからず時間を費やしてしまったので自戒の意味を込めて記事に残させていただきます。

やりたいこと

↓画像のようなボタンを作り、非同期でbooleanが反転するようにしたい。
スクリーンショット 2021-01-22 9.13.23.png

完成版パラメーター

【ボタンクリック1回目】

Parameters: {"user_groups"=>{"subscribed"=>"false"}}

【ボタンクリック2回目(非同期なのでリロードはしない)】

Parameters: {"user_groups"=>{"subscribed"=>"true"}}

ルーティング・コントローラー・ビュー

前提

以下の画像のようにuserとuser_groupは1対多の関係になっています。今回boolean反転させるのはuser_groupsテーブルのsubscribedカラムです。
スクリーンショット 2021-01-23 8.27.43.png

ルーティング

今回はユーザーが複数所属するグループが『グループ単位でメルマガを購読するかどうか』を変更するオプション(そんなのあまりないかもしれませんが、例としてです・・)をユーザー側で変更できる実装をする前提で、update_optionsというアクション名にします。

update_subscribed等の名前の方が良いかもしれませんが、今後同じような操作をするボタンを他にも作ることを想定して共通化された名前としています。
また今回使用するのはPATCHアクションのみなので、ルーティングもPATCHの部分のみ記載しています。

routes.rb
resources :user_groups do
  member { patch 'update_options' => 'user_groups#update_options' }
end

コントローラー

user_groups_controller.rb
class UserGroupsController < ApplicationController
  before_action :set_group

  def index #set_groupで定義した@groupをviewファイルで使用
  end

  def update_options
    @group.update_attributes(user_group_params)
  end

  private

  def user_params
    params.require(:user_group).permit(:subscribed)
  end

  def set_group
    @group = current_user.user_group.find_by(id: params[:id])
  end
end

ログイン中のユーザーは以下でcurrent_userとして定義しています。

shared.rb
def current_user
  @current_user ||= User.find(session[:user_id]) if session[:user_id]
end

ビュー

スタイリングは本題とは外れるので大変恐縮ですが今回は触れずに行きます。

index.slim
= link_to update_options_user_path(user_group: {subscribed: !@group.subscribed}), remote: true, method: :patch do
 .btn
  | 変更

以上で大体実装ができましたが、このままだとボタンを複数回押した際にパラメーターが切り替わりません。
実際に押してみると、

【ボタンクリック1回目】

Parameters: {"user_groups"=>{"subscribed"=>"false"}}

【ボタンクリック2回目】

Parameters: {"user_groups"=>{"subscribed"=>"false"}}

このように非同期でbooleanが反転されません。もちろんリロードすれば成功します。

解決法①

原因は、index.slimの= link_to部分がボタンを押した際に書き換えられていないので、パラメーターに変化がありませんでした。
ですので、update_optionsアクション側でDBの値を得て変更させれば『非同期で複数回クリックしてもboolean値が切り替わる』ことは実現できました。

user_groups_controller.rb
class UserGroupsController < ApplicationController
  def update_options
    @group.update_attributes(subscribed: !@group.subscribed)
  end
end
index.slim
= link_to update_options_user_path, remote: true, method: :patch do
 .btn
  | 変更

このようにすれば、クリックを押すたびにDBのboolean値が切り替わります。
しかし、ユーザーが同時に複数人ログインしていてこのボタンを一斉に押されると、DBの値がユーザーの意図しない値に書き換わってしまうことも考えられるので、やはり『パラメーターの値によってDBの値が変更される』方が良さそうです。

解決法②(私はこちらを採用しました)

こちらの方法ではJavaScriptを使って= link_toのvalue(今回はURL部分のみ)部分を、クリックするたびに書き換える実装をします。

index.slim
= link_to update_options_user_path(user_group: {subscribed: !@group.subscribed}), id: "change-subscribed-link", remote: true, method: :patch do
 .btn
  | 変更

まずは先程のslimファイルの= link_to部分にidを付与します。

index.slim
id: "change-subscribed-link"

としました。
次にupdate_optionsアクションが走った時にJavaScriptが走るようにしたいので、update_options.js.erbファイルをindex.slimと同ディレクトリに作成し、以下をファイルに記載します。

update_options.js.erb
$("#change-subscribed-link").attr("href", "<%= update_options_user_path(subscribed: {has_filed: !@group.subscribed}) %>")

このようにすることで、複数回クリックしても非同期でbooleanのパラメーターが反転するようになります。
こちらのコードではjQueryのセレクターで該当する= link_toを持ってきて、中身のURL部分だけを上書きしています。

少し見にくいですが、検証ツールでどういう挙動なのか確認できます。
スクリーンショット 2021-01-23 8.44.18.png
このaタグのhref部分をupdate_options.js.erbファイルで書き換えたということです。

【ボタンクリック1回目】

Parameters: {"user_groups"=>{"subscribed"=>"false"}}

【ボタンクリック2回目(非同期なのでリロードはしない)】

Parameters: {"user_groups"=>{"subscribed"=>"true"}}

パラメーターも無事反転しました!
また今後別のボタンを作り、booleanのみを切り替える動作をさせたい場合は、update_optionsアクションを使用すれば良いので、一からルーティング、コントローラーを追加する必要もなくなりました!

さいごに

誤っている箇所がありましたらご指摘いただきたく存じます。
また、他にも何か良いやり方等ありましたらご教示いただければ幸いです!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

コントローラー

コントローラー

MVCの役割の一つ
ルーティングから振り分けられたリクエストを処理してレスポンスとして返す役割
必要なデータがあればビューやモデルとやりとりして取得して返します。

image.png

ここでコントローラーの役割の一部にフォーカスしてみていきましょう。
image.png

コントローラーを作っていきましょう。

rails g コマンド

railsで追加したいファイルなどを作るコマンドです。
ファイルの種類と作るファイル名を入力して使います。

rails g ファイルの種類 作るファイル名

さて、ここでpostsコントローラーを作ってみましょう。

rails g controller posts

注意点としてはコントローラー名を指定する時には複数形を使ってください。
❇︎これは命名規則という物でファイルの種類などによって名前の付け方に一定のルールがあるためです。

rails d コマンド

作ったデータを消したい時はこのコマンドを使います。
関連するファイルをまとめて消去してくれます。

rails d ファイルの種類 削除するファイル名

アクション

コントローラー内における、処理のことです。
アクションは、コントローラーにインスタンスメソッドとして定義します。
どの動作を行うかによって、種類が分かれます。

アクション名 動き(例)
index 一覧表示
new 新規投稿
create データの投稿
show 詳細
edit データの編集
update データの編集
destroy データの削除
#ファイルの場所(app/controllers/posts_controller.rb)

class PostsController < ApplicationController

 def index  # indexアクションを定義
 end

end

以上です。次回はビューをやっていきましょう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby on Railsでアプリを作ってみよう③

コントローラー

MVCの役割の一つ
ルーティングから振り分けられたリクエストを処理してレスポンスとして返す役割
必要なデータがあればビューやモデルとやりとりして取得して返します。

image.png

ここでコントローラーの役割の一部にフォーカスしてみていきましょう。
image.png

コントローラーを作っていきましょう。

rails g コマンド

railsで追加したいファイルなどを作るコマンドです。
ファイルの種類と作るファイル名を入力して使います。

rails g ファイルの種類 作るファイル名

さて、ここでpostsコントローラーを作ってみましょう。

rails g controller posts

注意点としてはコントローラー名を指定する時には複数形を使ってください。
❇︎これは命名規則という物でファイルの種類などによって名前の付け方に一定のルールがあるためです。

rails d コマンド

作ったデータを消したい時はこのコマンドを使います。
関連するファイルをまとめて消去してくれます。

rails d ファイルの種類 削除するファイル名

アクション

コントローラー内における、処理のことです。
アクションは、コントローラーにインスタンスメソッドとして定義します。
どの動作を行うかによって、種類が分かれます。

アクション名 動き(例)
index 一覧表示
new 新規投稿
create データの投稿
show 詳細
edit データの編集
update データの編集
destroy データの削除
#ファイルの場所(app/controllers/posts_controller.rb)

class PostsController < ApplicationController

 def index  # indexアクションを定義
 end

end

以上です。次回はビューをやっていきましょう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

routeを設定する際にpathを使えば任意のパスを作れる

実装したクラス名とは異なるパスをつけたい

 例えば、hoge_controllerを実装していたが、パスだけhuga/indexにしたい時があったとする。
 こんな時、コントローラー名を変えて、クラス名をいろいろ変えて、、などとする必要はない。routes.rbの設定で何とかなる。(ただし、ファイルの管理はややこしくなってしまうかもしれない。。)

パスだけを任意の形にしたいならpathを使う

  resources :クラス名, path: 実現したいパス do
    collection do
      get :メソッド
    end
  end

もっとカスタムしたい場合は以下を参照

[rails5]routes.rbでprefix・URI・controller#actionの値を任意にカスタマイズできる
https://qiita.com/og3/items/d814bf1a81cce2af633a

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

form_withを使って、ユーザーが新規作成される仕組みを理解する

webサービスで新規登録やユーザログインのときに使われる、form_withというヘルパーメソッド。

Railsチュートリアルなどで突然登場して、なんとなく使い方が分かってるけど説明はできない「曖昧状態」になっていませんか。

ぼくもまさにそのひとり。

今回は、form_withを使って、ユーザーが新規作成される仕組みを理解する記事を書いていこうと思います!

そもそも「フォーム」とは?

  • nameとvalueがペアになってサーバに送られる

  • nameとvalueはinputやselectやradioなどに付与される

  • action属性に指定されたURLに対して入力値が送られる

引用記事:
[https://qiita.com/DaichiSaito/items/cd66115569b0a75f1bfa#11-%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E3%81%A8%E3%81%AF%E3%81%8C%E6%9B%96%E6%98%A7]

この3つをはじめてみたとき???という感じでした。

例を挙げて説明してみます。

railsチュートリアルから以下のコードを引っ張ってきました。

<%= form_with(model: @user, local: true do |f| %>
      <%= f.label :name %>
      <%= f.text_field :name %>

      <%= f.submit "Create" %>
    <% end %>

これがHTMLソースに変換されると

<form accept-charset="UTF-8" action="/users" class="new_user"
      id="new_user" method="post">

  <label for="user_name">Name</label>
  <input id="user_name" name="user[name]" type="text" />

  <input  name="commit" type="submit"
         value="Create" />
</form>

※local: trueとは?
local: trueがない場合、Rails5ではAjaxによる送信という意味になる。
HTMLとしてフォームを送信する場合にlocal: trueが必要になります。

例えば、フォームの名前に「たろう」と入力されると

<input id="user_name" name="user[name]" type="text" value="たろう" />

このようになります。

そしてformタグのaction属性に指定されたURL("/users" )に対して、nameとvalueが送られます。

コントローラ

@user = User.new(params[:user])

params[:user]というのは、送られてきたnameに対応しています。今回であればname="user[name]" value="たろう"が送られてきているので、@userというインスタンスにname:"たろう"が格納されます。

form_withのしていること

<%= form_with(model: @user, local: true do |f| %>
      <%= f.label :name %>
      <%= f.text_field :name %>

整理すると、

  • model: @user・・・入力値を格納するインスタンスとaction属性を指定("/users")

  • local: true・・・HTMLとしてフォームを送信する場合にlocal: true必要

  • <%= f.label :name %>・・・フォームのラベルを決めている

  • <%= f.text_field :name %>・・・HTMLに変換されるとname="user[name]" type="text"になる

何が起きているかわからないとなってしまうform_withですが、
HTMLコードに分解して考えると、理解しやすいですね。
ブラウザの開発者ツールからHTMLソースを見る癖をつけていきましょう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

gem gretelの使い方 ~パンくずリストを作ってみよう~

gem 'gretel'

このgemを使って、パンくずリストを作っていこうと思います。

パンくずリストってなんぞや??

Image from Gyazo

ホームページのすみっこで見られる、ページの階層ですね。Webサイト内で、どの位置にいるのかがわかる機能です。

「ユーザー」を押すとユーザーページへ、「ホーム」を押すと最初のページへ飛ぶことができます。(ハンバーガーメニューとかパンくずリストとか、プログラミングの世界は、遊び心があって良いですよね。)

gem 'gretel'を使う

こちらのGithubのREADMEをご覧ください↓↓

[https://github.com/kzkn/gretel:embed:cite]

gem 'gretel'をbundle installしたあと、

$ rails generate gretel:install

こちらのgenerateコマンドを使って、config配下にbreadcrumb.rbというファイルが生成されます。

それではbreadcrumb.rbに作りたいパンくずリストの設定を記述していきます。

breadcrumb.rbにパンくずリストの設定を記述

Image from Gyazo

先ほどのリストを試しに作っていきます。

#breadcrumb.rb

crumb :dashboard do
  link ' Home', dashboard_path
end

crumb :users do
  link 'ユーザー', users_path
  parent :dashboard
end

crumb :user do |user|
  link 'プロフィール', user_path(user)
  parent :users
end

上記のような記述になります。書き方としては、

crumb :"シンボル名" do
  link 'パンクズに表示したい名前', URL
  parent :"一つ上の階層名"
end

このように当てはめていきます。parentは一つ上の階層がなければ(今回ならHome)記述しなくてOKです。

breadcrumb.rbの設定をこれで完了です。

viewファイルに記述していく

それぞれのviewファイルにbreadcrumbを記述していきます。

#Homeのviewファイル
<% breadcrumb :dashboard %>
#ユーザーのviewファイル
<% breadcrumb :users %>
#プロフィールのviewファイル
<% breadcrumb :users, @user %>

プロフィールのviewファイルで気をつけることは、

breadcrumb.rbにもあるように、プロフィールページはuser_path(user)というURLに飛ぶので、どのidのURLに飛んで欲しいのか(今回なら@user)を記述しないとエラーが出てしまいます。

あとはCSSなどで、ページの好きな位置にパンくずを表示すればOKです。とても簡単。。!

パンくずリストはヘッダーの下などに記述することが多いかと思いますので、部分テンプレートに分けておくのが便利かと思います。

gem gretelを使って、パンくずリストを作ってみよう

Image from Gyazo

一見むずかしそうな機能が、とても簡単に作れることが分かったと思います。

便利なgemを駆使しながら、より使いやすいRailsアプリケーションを作っていきましょう!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む