20210122のRailsに関する記事は14件です。

Railsのルーティングについて学び直そうと思う…②

はじめに

昨日に引き続き、Railsのルーティングについて、基本的なことから復習しています。

Railsのルーティングについて学び直そうと思う…①

基本形

HTTPリクエスト URL, to: 'コントローラ名#アクション名'
※省略形もあります

HTTPリクエストとは、getやpostなど。

ルール

  • 読み込まれる順番は、上から。
    →つまり、より限定的なURL程、上に記述しないと、予期しないところでマッチしてしまう。 ex) 「りんご」で、一致させたいのに、「くだもの」で一致してしまうみたいな…
    …より、わかりにくくなったらすみません。
get "posts/:id" => "posts#show"
get "posts/new" => "posts#new"
  • :idは似たURLの中でも最後に書く。:idは変数なので、何にでも一致してしまう。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】1対1のアソシエーションにおけるリソース設計について

はじめに

リソース設計を考えるときに悩んだ結果をまとめました。
コード例はRailsです。

DB構造

Untitled Diagram.png

questionsテーブルとanswerテーブルが1対1の関係です。
answerがquestionに紐づくので、外部キーはanswersに持たせます。

モデル

question.rb
class Question < ApplicationRecord
  has_one :answer, dependent: :destroy
end
answer.rb
class Answer < ApplicationRecord
  belongs_to :question
end

特に言うことのないシンプルな形です。

リソースどうしよう?

さて、「ある質問に対する回答を追加する場合」を考えました。
オーソドックスな1対多の場合はこんな感じになるはずです。

POST questions/:id/answers

では、「更新」は?

PATCH questions/:question_id/answers/:id

しかし、これを1対1で想定すると違和感があります。

  • 「ある質問に対する回答」は一つしかないのに、question_idanswer_idをリクエストで送るのが冗長
  • 一度回答を作成したら、同じ質問に対して回答を新規作成することはない

「ある質問の回答」を追加することと更新することは同等の意味を持つはずです。

HTTP の PUT リクエストメソッドは、新しいリソースを作成するか、指定したリソースの表現をリクエストのペイロードで置き換えます。
PUT - HTTP | MDN

ということなので、Railsのupdateメソッドに相当します。

PUT questions/:id/answer

というリクエストで回答の値を更新することにします。

既にanswerが存在しているときに、新たなanswerをnewとかcreateすること自体がおかしいです。
question1のanswerは一つしかないので、newとedit、createとupdateは等価といえます。
なので、単一リソースのときはedit/updateで作成または更新の行動をしたい。
POST, PATCHを使い分けるためには、リクエスト(URL)がanswerの有無を知る必要があるので、違和感があります。URLがそこまで責任を持つべきではありません。

URLが
:no_good:「question1のanswerを新しくこの値で作成してくれ」とか「question1のanswerがあるはずだから、この値に書き換えてくれ」
:ok_woman:「answerがあるかどうかは知らんけど、question1のanswerの値をこうしてくれ」
ってお願いして、それに答えるのが自然です。

ルーティング

routes.rb
resources :questions do
  resource :answer, only: %i[edit update show]
end

コントローラ

#find_or_initialize_byという便利なメソッドがあるので、それを使うだけで他は普通のCRUDの場合と変わりません。

answers_controller.rb
class AnswersController < ApplicationController
  before_action :set_question

  def show
    @answer = @question.answer
  end

  def edit
    @answer = Answer.find_or_initialize_by(question_id: @question.id)
  end

  def update
    @answer = Answer.find_or_initialize_by(question_id: @question.id)
    if @answer.update(answer_params)
      redirect_to question_answer_path(@question, @answer)
    else
      render :edit
    end
  end

  private

  def set_question
    @question = Question.find(params[:question_id])
  end

  def answer_params
    params.require(:answer).permit(:text)
  end
end

終わりに

という考えでこういうリソース設計にしたのですが、補足やオススメの書籍などありましたらコメントをいただけるとありがたいです。

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

【Rails】1対1のアソシエーションにおけるネストされたリソース設計について

はじめに

リソース設計を考えるときに悩んだ結果をまとめました。
コード例はRailsです。

忙しい人のための要約

PUT questions/:id/answer

でupsertする。

DB構造

Untitled Diagram.png

questionsテーブルとanswerテーブルが1対1の関係です。
answerがquestionに紐づくので、外部キーはanswersに持たせます。

モデル

question.rb
class Question < ApplicationRecord
  has_one :answer, dependent: :destroy
end
answer.rb
class Answer < ApplicationRecord
  belongs_to :question
end

特に言うことのないシンプルな形です。

リソースどうしよう?

さて、「ある質問に対する回答を追加する場合」を考えました。
オーソドックスな1対多の場合はこんな感じになるはずです。

POST questions/:id/answers

では、「更新」は?

PATCH questions/:question_id/answers/:id

しかし、これを1対1で想定すると違和感があります。

  • 「ある質問に対する回答」は一つしかないのに、question_idanswer_idをリクエストで送るのが冗長
  • 一度回答を作成したら、同じ質問に対して回答を新規作成することはない

「ある質問の回答」を追加することと更新することは同等の意味を持つはずです。

HTTP の PUT リクエストメソッドは、新しいリソースを作成するか、指定したリソースの表現をリクエストのペイロードで置き換えます。
PUT - HTTP | MDN

ということなので、Railsのupdateメソッドに相当します。

PUT questions/:id/answer

というリクエストで回答の値を更新することにします。

既にanswerが存在しているときに、新たなanswerをnewとかcreateすること自体がおかしいです。
question1のanswerは一つしかないので、newとedit、createとupdateは等価といえます。
なので、単一リソースのときはedit/updateで作成または更新の行動をしたい。
POST, PATCHを使い分けるためには、リクエスト(URL)がanswerの有無を知る必要があるので、違和感があります。URLがそこまで責任を持つべきではありません。

URLが
:no_good:「question1のanswerを新しくこの値で作成してくれ」とか「question1のanswerがあるはずだから、この値に書き換えてくれ」
:ok_woman:「answerがあるかどうかは知らんけど、question1のanswerの値をこうしてくれ」
ってお願いして、それに答えるのが自然です。

ルーティング

routes.rb
resources :questions do
  resource :answer, only: %i[edit update show]
end

コントローラ

#find_or_initialize_byという便利なメソッドがあるので、それを使うだけで他は普通のCRUDの場合と変わりません。

answers_controller.rb
class AnswersController < ApplicationController
  before_action :set_question

  def show
    @answer = @question.answer
  end

  def edit
    @answer = Answer.find_or_initialize_by(question_id: @question.id)
  end

  def update
    @answer = Answer.find_or_initialize_by(question_id: @question.id)
    if @answer.update(answer_params)
      redirect_to question_answer_path(@question, @answer)
    else
      render :edit
    end
  end

  private

  def set_question
    @question = Question.find(params[:question_id])
  end

  def answer_params
    params.require(:answer).permit(:text)
  end
end

終わりに

という考えでこういうリソース設計にしたのですが、補足やオススメの書籍などありましたらコメントをいただけるとありがたいです。

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

Railsの検索メソッドの基礎(whereでLIKE句を使う)

めちゃくちゃ曖昧に理解していたこんな文

検索用メソッドで出てくるこんな文。めちゃくちゃ曖昧に理解していたので、復習します。

@users = User.where('name LIKE ?', "%#{params[:name]}%")

('name LIKE ?', "%#{params[:name]}%")はどういう意味かというと...(ちゃんとRailsガイドに書いてあった)

検索に使う語句が可変である時の書き方らしい。
第一引数(name LIKE ?)の?の部分が、第二引数(%#{params[:name]}%)と置き換えられる。

そして、whereでは、上と下の書き方は同じ結果が得られる。

@users = User.where(name: 'sato')
@users = User.where("name = 'sato'")
# どちらもidが1のデータが得られる

発行されるSQLは若干異なるが、それぞれこんな感じ。

SELECT `users`.* FROM `users` WHERE `users`.`name` = 'sato';
SELECT `users`.* FROM `users` WHERE (name = 'sato');

User.where('id = 1')id = 1が、
SQL文のWHERE (id = 1)に入っているイメージか。

【注】この書き方はSQLインジェクションの可能性があるので、実際には書かない用が良い。

SQL

一方で、SQLでのLIKE句はこのように使う。

SELECT 列名 FROM テーブル名 WHERE 列名 LIKE '検索文字';

↑ちなみに、これは「完全一致」の時

  • '%検索文字列'...前方一致
  • '検索文字列%'...後方一致
  • '%検索文字列%'...部分一致

改めて、最初の文と合わせてみる

では、改めて、最初の文を眺めてみる。

@users = User.where('name LIKE ?', "%#{params[:name]}%")

この時、仮に「sato」という文字列がparams[:name]として渡ってきていると仮定すると、

@users = User.where('name LIKE ?', "%sato%")

となり、

SELECT `users`.* FROM `users` WHERE (name LIKE '%sato%');

このようなSQLが発行され、name「sato」さんのデータだけが抽出される。

追記:LIKE句で複数単語検索をしたい場合

今回、実現したいことはLIKEでの複数単語検索だったので、LIKE句の複数単語検索ではどのようなSQLが発行されるのか調べてみました。

例えば、住所録の中から%山%さんと%川%さんをOR検索で探したい時には、

SELECT * FROM users WHERE name LIKE '%山%'
                       OR name LIKE '%川%';

らしいので、
Railsで複数単語検索を実現するには、キーワードを配列に入れて、eachで回して、それぞれで、下記の処理をすれば良さそうですね^^

@users = User.where('name LIKE ?', "%#{params[:name]}%")

続きは次回、実装します〜

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

【Rails】scopeの定義とProcオブジェクト

scopeとは

よく利用する検索条件に名前をつけてひとまとめにしたもの。
railsガイドでは以下のように解説されています。

スコープを設定することで、関連オブジェクトやモデルへのメソッド呼び出しとして参照される、よく使用されるクエリを指定することができます。スコープでは、where、joins、includesなど、これまでに登場したすべてのメソッドを使用できます。どのスコープメソッドも、常にActiveRecord::Relationオブジェクトを返します。このオブジェクトに対して、別のスコープを含む他のメソッド呼び出しを行なうこともできます。

scopeの書き方

models/book.rb
class Book < ApplicationRecord
  scope :costly, -> { where("price > ?", 3000) }
end

scopeの第一引数にメソッド名、第二引数にProcオブジェクト(のラムダ)を定義することで、コントローラーやモデルでBook.costlyと書いたとき、Book.where("price > ?", 3000)と書いたのと同義になります。これによるメリットは以下の2つです。

  • 繰り返し利用できる
  • 可読性が向上する

何度もクエリを書かなくてよくなるのに加えて、Book.costlyとあれば、高価な本を探しているんだなとひと目で分かります。

また、引数を渡すこともできます。

models/book.rb
class Book < ApplicationRecord
  scope :written_about, ->(theme) { where("name like(?)", "%#{theme}%") }
end

scopeを定義した際の返り値のクラスはActiveRecord::Relationとなるので、scopeをメソッドチェーンでつなげたり、Query Interfaceを呼び出すこともできる。

Book.costly.written_about("ハリーポッター").limit(1)
=> #<ActiveRecord::Relation [
#<Book id: 1, name: "賢者の石", published_on: "1999-10-21", price: 4000>
]>

ブロックが複数行に渡る場合

scopeの第二引数はProcオブジェクトのラムダを使います。ブロックが複数行に渡る場合は下のような書き方が一般的です。

models/book.rb
scope :written_about, lambda { |theme|
  return if theme.blank?

  where("name like(?)", "%#{theme}%")
}

以上

補足

Procオブジェクトとは

ブロックをオブジェクト化したProcクラスのインスタンスです。

hello_proc = Proc.new { "hello" }
hello_proc.call
=> "hello"

Procオブジェクトの作成方法

Proc.new { |a, b| a + b }
proc { |a, b| a + b }
->(a, b) { a + b }
lambda { |a, b| a + b }

厳密には上2つと下2つのオブジェクトは異なります。下2つはラムダと呼ばれ、scopeの第二引数で使っているものです。ラムダは引数のチェックがより厳密です。検索条件で渡ってくる引数は決まっているため、ラムダを使っていました。

add_proc = Proc.new { |a, b| a.to_i + b.to_i }
add_proc(10)
#=> 10 

add_lambda = ->(a, b) { a.to_i + b.to_i }
add_lambda(10)
#=> ArgumentError: wrong number of arguments (given 1, expected 2)

Procオブジェクトの実行方法

add_proc = Proc.new { |a, b| a + b }

add_proc.call(10, 20)
add_proc.yield(10, 20)
add_proc.(10, 20)
add_proc[10, 20]

参考

https://railsguides.jp/active_record_querying.html#%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97
パーフェクトRuby on Rails

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

続きを読む(truncate)の実装

環境

・rails 5.2.4

続きを読むの実装

snsでよくある続きを読むの実装の紹介をさせて頂きます。。

とっても簡単で以下のように末尾にtruncateと書くだけです。

images/index.html.erb
<%= image.introduction.truncate(20) %>

20文字以上で...で表示されるという意味です。

この記述をすれば、以下のような表示になります。
image.png

ちなみに、続きを読むのリンクは以下の記述で実装できました。

images/index.html.erb
<%= image.body.truncate(20) %>
  <% if image.body.size >= 20 %>
    <%= link_to image_path(image.id) do %>
       <p>続きを読む</p>
    <% end %>
  <% end %>

20文字以上だと続きを読むが表示されるというif文です。

簡単ですが、説明は以上となります。
ありがとうございました。

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

Rails gem 'devise'でログアウトをコントローラから一発で呼ぶ方法

Rails gem 'devise'でログアウトをコントローラから一発で呼ぶ方法

今日はrailsのコントローラで一発でログアウトさせるということで記事をかいきます!

結論としては
reset_session
これをコントローラーないに記述するだけでした笑

今回なぜこれを使ったのかと言いますと
現在ユーザ退会機能を作っておりまして、その退会処理の後にログアウトさせる
必要があったために使いました:relaxed:

これ便利なメソッドなので是非皆さんも使ってみてくださいね!!

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

BASIC認証とは

自分の備忘録用

Basic認証とは

ベーシック認証(Basic認証)とはWebサイトの特定の領域、つまりページやファイルにアクセス制限をかけることができる認証方法の1つ。ベーシック認証をかけると、認証をかけたWebサイトにアクセスしようとしたとき、下の画像のような認証ダイアログが立ち上がって、ユーザー名(ID)とパスワードの入力が求められる。

設定方法

まずトップページのコントローラーに before_action :basic_authを定義する。

「basic_auth」は変数名なので名前はこれじゃなくてもいい。

class アプリ名Controller < ActionController::Base
  before_action :basic_auth


  private

  def basic_auth
    authenticate_or_request_with_http_basic do |username, password|
      username == 'ユーザー名' && password == '好きなパスワード'
    end
  end
end

ここに出てくる「authenticate_or_request_with_http_basic」と言うメソッドはRailsに用意されているメソッドで
Basic認証を使うときに必要、ブロックの中にusernameとpasswordを入れdo〜endの中にそれぞれ設定する

保守性

でもこのままだとパスワードが丸見えになるので環境変数を設定しその中にusernameとpasswordを代入する形を取る。
macOSがCatalina以降なら
俺はCatalinaなのでこっち


% vim ~/.zshrc

# .zshrcを開いたら、「i」とタイプしてインサートモードに移行

# .zshrcの内部に次の記述を追加
export BASIC_AUTH_USER='ユーザー名'
export BASIC_AUTH_PASSWORD='好きなパスワード'
# 記述を追加したら、escキーを押してインサートモードを抜け、 「:wq」と入力して保存して終了する

# .zshrcを再読み込みし、定義した環境変数を有効にする
% source ~/.zshrc

macOSがMojave以前なら

$ vim ~/.bash_profile

# .bash_profileを開いたら、「i」とタイプしてインサートモードに移行

# .bash_profileの内部に次の記述を追加
export BASIC_AUTH_USER='ユーザー名'
export BASIC_AUTH_PASSWORD='好きなパスワード'
# 記述を追加したら、escキーを押してインサートモードを抜け、 「:wq」と入力して保存して終了する

# .bash_profileを再読み込みし、定義した環境変数を有効にする
$ source ~/.bash_profile

設定できたらコントローラーに戻って以下に編集

def basic_auth
    authenticate_or_request_with_http_basic do |username, password|
      username == ENV["BASIC_AUTH_USER"] && password == ENV["BASIC_AUTH_PASSWORD"]  # 環境変数を読み込む記述に変更
    end
  end

heroku上にも環境変数を反映させるには

% heroku config:set BASIC_AUTH_USER="ユーザー名"
% heroku config:set BASIC_AUTH_PASSWORD="好きなパスワード"

設定できたかを確かめるコマンド⬇︎

% heroku config

設定したらデプロイを忘れない

% git add .
% git commit -m "Basic認証を導入"
% git push heroku master

できたぁ!(悟空)

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

flashメッセージ

flashとは

paramsと似たような存在。
ハッシュなので、キーを指定しなければならない。
paramsと違い、画面遷移を1回までは、データを保持したままにしてくれる。

制作物

以下のコードからは、bootstrapを前提としているが、レイアウトを気にしなければ参考になるはず。

<%= yield %>の上にflash用のdivを用意する。
flash[:info]における、[:info]はキーにあたる。
flash[:oshirase]と定義しても問題ない。

application/html/erb
  <main>
    <div class="my-2 bg-warning text-center text-dark" id="flash_error"><%=flash[:error]%></div>
    <div class="my-2 bg-info text-center text-dark" id="flash_info"><%=flash[:info]%></div>
    <div class="container">
        <%= yield %>
    </div>

  </main>

本の投稿を例にあげる。

books_controller.rb
def create
  @book=Book.new(book_params)
  if @book.save
     flash[:info]="成功しました。"
     redirect_to .....
  else
     flash[:error]="保存に失敗しました。"
     render "books/new" #もといたページ
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】seedとFakerでランダムなサンプルデータを作成

はじめに

データベースに予め大量のデータを入れておきたいとき手動では大変です。
この記事ではseedとFakerを使って、自動でランダムなサンプルデータを作成する方法を紹介します。

seedについて

seedファイルは、データベースにあらかじめ入れておきたいデータを定義しておくものです。
データをあらかじめ定義しrails db:migrateすることで、簡単にDBへデータを投入できます。

gem 'faker'について

Fakerとはランダムな値を入れられるgemです。
 Gemfileの中にgem 'faker'を追記し、 bundle installコマンドを実行することで使用出来る様になります。

詳しくは下記の公式ページを参照してください。
【公式】
https://github.com/faker-ruby/faker

開発環境

ruby 2.6.5
Rails 6.0.3.4
faker 2.15.1
gimei 0.5.1

fakerインストール

Gimile
gem 'faker'
gem 'gimei'

gimeiは、日本人の名前や、日本の住所をランダムに返すGemです。

ターミナル
bundle install

今回demosデーブルに200件のダミーデータを追加します。

db/seeds.rb
require 'faker'

200.times do |n|
  sample_name = Gimei.kanji
  sample_kana = Gimei.katakana
  sample_email = Faker::Internet.email
  sample_tel = Faker::Number.number(digits: 11)
  start_time = Faker::Date.forward(50)
# start_time = Faker::Date.between(from: '2021-01-01', to: '2021-04-30') #期間を限定することもできます。
  Demo.create!(
    sample_name:         sample_name, 
    sample_kana:         sample_kana, 
    sample_email:        sample_email, 
    sample_tel:          sample_tel, 
    sample_product_name: "京都ツアー", 
    price:               "19600", 
    num_id:              "2", 
    start_time:          start_time, 
    sample_id:           "1", 
    created_at:          "2021-01-01 00:00:00",
    updated_at:          "2021-01-01 00:00:00"
  )
end
ターミナル
rails db:seed

データベースを確認します。
スクリーンショット 2021-01-13 8.32.33.png
サンプルデータ作成完了です!

まとめ

fakerの使い方さえわかれば非常に簡単です。
このデータを検索機能のサンプルにするのも良いと思います。

最後に

同じ様に悩んでる方々の助けになればと思い、記事を投稿しております。
それでは、また次回お会いしましょう〜

参考

【公式】
https://github.com/faker-ruby/faker

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

単体テストエラー 〜ActiveRecord::StatementInvalid: Mysql2::Error::ConnectionError: Lost connection to MySQL server during query〜

自分の備忘録として残しておきます

エラー内容

ActiveRecord::StatementInvalid:
Mysql2::Error::ConnectionError: Lost connection to MySQL server during query

スクリーンショット 2021-01-22 12.27.34.png

スクショを見る限り一つ目のテストは成功してるのに二つ目以降のテストは失敗している、、、なぜ?
可能性としてはテストに負荷がかかりすぎてread_timeout以内に処理が終わらなかった。

spec/models/ファイル名_spec.rb
RSpec.describe UserAddress, type: :model do
  before do
    @user = FactoryBot.create(:user)
    @item = FactoryBot.create(:item)
    @user_address = FactoryBot.build(:user_address, user_id: @user.id, item_id: @item.id)
    sleep 0.1    #この1行を追加
  end


#以下略
sleep 0.1 

上記の記述はインスタンスを生成する処理に0.1秒待機させてread_timeoutのエラーを回避するための記述です。

スクリーンショット 2021-01-22 12.59.55.png

できたぁ!(悟空)

参考記事
https://abicky.net/2017/09/17/014241/

https://qiita.com/shun915a/items/e18f538be6221f929876

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

単体テストのエラー 〜ActiveRecord::RecordInvalid: Validation failed: Email has already been taken〜

単体テストして変なエラーが出たので備忘録として残しておきます

結論

「そのメールは既に登録されているよ」って怒られてます。

この時僕はFakerでメールを作らずに手入力で入れていてのでテスト内でuserが何度も作成されるにあたって手動で入れてしまうとメールが重複してしまった、と言うことになります

以下コード

fuctories/user.rb
FactoryBot.define do
  factory :user do
      nickname                 {"tarou"}
      email                    {"sanple.sample@com"}
#emailを以下に変更⬇︎
      email                    {Faker::Internet.free_email}
#emailを上記に変更⬆︎
      password                 {"a1234567"}
      password_confirmation    {"a1234567"}
      last_name                {"山田"}
      last_name_kana           {"ヤマダ"}
      first_name               {"太郎"}
      first_name_kana          {"タロウ"}
      birthday                 {"2000-01-01"}
  end
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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

MVC(エム・ブイ・シー)

Railsを始めアプリケーションの処理を表しています。
M=モデル
V=ビュー
C=コントローラー

これからアプリケーションの処理の流れを順番に解説していきます。
image.png

それではリクエストを振り分ける役割のルーティングから説明していきます

ルーティング

クライアントからのリクエストに対して対応した行き先を指定します。
トップページをみたいというリクエストがあったとしたら、トップページを表示するための処理にいく道筋をたてます。
configディレクトリのroutes.rbに記述していきます。

Rails.application.routes.draw do
 HTTPメソッド 'URIパターン', to: 'コントローラー名#アクション名'
end

HTTPメソッド

Webアプリケーションを表示する際の、情報やデータなどを送受信するための通信方法をHTTP通信と言いHTTPメソッドとはその処理における種類を表します。

HTTPメソッド(一例) 処理
GET 取得する
POST 送信する、作成する
PUT 更新する、作成する
DELETE 削除する

URIパターン

URLと同じような物でリクエストのパスを表します。

ルーティングの一例

Rails.application.routes.draw do
 get 'tests', to: 'tests#index'
end

ルーティングファイルに次のように記述するとルーティングが設定されます。

rails routes コマンド

現在設定されているルーティングを確認することができます。

rails routes

以下の画像のように表示されます。
image.png

prefix

これもパスを表す物です。

Verb

この下に書かれているものがHTTPメソッドです。

つまりこのルーティングは
HTTPメソッドがGETでtestsコントローラーのindexアクションにいく物になります。

次回はコントローラーについて説明していきます。

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

Ruby on Rails6でのjQueryの実装方法(Windows10 + 仮想環境)

Rails5までの実装方法を試してみてもjQueryが動かなかったので調べてみると、
Railsのversionが上がり、Rails6になってからはjQueryの実装方法が変わったようなので、
自分の勉強もかねて、読んでくださる方々に共有させていただきます。

※プログラミング初心者ですので、おかしい点などがありましたら指摘してもらえると助かります。

開発環境

  • 使用PC:Windows10
  • 仮想環境:vagrant + CentOS7
  • テキストエディタ:VSCode
  • Ruby version:ruby2.5.8
  • Rails version:6.1.1

実装したい環境

Ruby on Rails6での環境でjQueryを実装したい

目次

  1. jQueryインストール
  2. application.jsのファイル先の変更
  3. Webpackの設定
  4. application.jsの設定
  5. 外部ファイル作成

1. jQueryインストール

Rails5までのverでは、GemfileにjQueryを記載してbundle installしていた。しかし、Rails6ではWebpacketを利用してjQueryをインストールします。

【Windowsの人はこちらのコマンド yarnが使えない人用】
npm add jquery

【Macの人はこちらのコマンド yarnが使える人用】
yarn add jquery

2. application.jsのファイル先の変更

Rails5ではapplication.jsファイルは
【Rails5の場合】
app/assets/javascript/application.js

にあった。しかしRails6では
【Rails6の場合】
app/javascript/packs/application.js

ファイルの場所が変わっている。

application.jsの head 内に以下のコードが追記されているか確認する。
追記されていない場合は追記する。

app/javascript/packs/application.js
<head>
// ~他のコードが記載されている
  <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
// ↑のコードが記載されているか
</head>

3. Webpackの設定

Webpackの設定に以下を追記する。

config/webpack/environment.js に追記する

config/webpack/environment.js
const { environment } = require('@rails/webpacker')
// 以下を追記
const webpack = require('webpack')
environment.plugins.prepend('Provide',
    new webpack.ProvidePlugin({
        $: 'jquery/src/jquery',
        jQuery: 'jquery/src/jquery'
    })
)
// ここまで
module.exports = environment

4. application.jsの設定

【Rails6の場合】

app/javascript/packs/application.js
require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")

require ('test.js')  //追加 自分が決めたjsのファイル名

【Rails5の場合】

app/assets/javascript/application.js
import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"

Rails.start()
Turbolinks.start()
ActiveStorage.start()

僕はRailsのバージョンが違うと何が変更されるのかなど、よくわかっておらず、Rails5のapplication.jsのコードの下や上にRails6のコードを書いたりしててjQueryが動かなかったので注意が必要かもです。

5. 外部ファイル作成

次に外部ファイルにjQueryコードを書いていく。
今回は例としてtest.jsとファイル名をする。
ファイルは app/javascript/ このjavascriptフォルダより下に格納する。

※フォルダを新たに作って、その下に格納してもいい。

app/javascript/test.js
$(function() {
$(".title").css("color", "red");
});

今回は例として post/index.html.erb にjQueryを実行してみる。
viewやコントローラーやモデルなどはすでに作られている前提で書いていきます。

app/views/posts/index.html.erb
<title>Hello World</title>

実際に rails s して確認してみる。

unnamed.png

正常に動きました。

【jQueryを導入していない場合の結果】
unnamed (1).png

4. でapplication.js に require ('test.js') を追加したので
どのViewファイルでも test.js(好きなファイル名) に書き込めばjQueryが実行される。

app/views/posts/index.html.erb に直接jQueryを書き込むこともできるが、
重くなったり、管理がしづらかったりなど、あまり使われていないです。

app/views/posts/index.html.erb
<title>Hello World</title>

<script>
$(".title").css("color", "blue");
</script>

最後まで見てくれてありがとうございます。
プログラミングの勉強一緒に頑張りましょう!

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