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

【Qiitaクローン】2.トップページ作成

はじめに

未経験からWebエンジニア(サーバサイド)へ転職するため勉強中です。
Qiitaのクローンを一から作成しながら、こちらに投稿することでより理解を深めていけたらなと思います。

※ cloud9にて開発していきます。
Rails 5.2.3
Ruby 2.5.3 [x86_64-linux]

トップページ作成

toppage.png

$ rails g controller toppages index

トップページのコントローラーを作成し、viewファイルを編集する。

toppages/index.html
<h1>Hello hackers!</h1>
<p>Qiitaは、エンジニアリングに関する知識を記録・共有するためのサービスです。コードを書いていて気づいたことや、自分がハマったあの仕様について、他のエンジニアと知見を共有しましょう ;)</p>

ルーティングも設定しておきます。

config/routes.rb
Rails.application.routes.draw do
  root to: 'toppages#index'
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

herokuへのデータベースのリセットとサンプルデータの生成

heroku上のデータベースをリセットしたい場合

heroku pg:reset DATABASE

リセット後

heroku run rails db:migrate
heroku run rails db:seed

結果は同じだがこちらのコードでも大丈夫↓

heroku run rake db:migrate
heroku run rake db:seed
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsにpostgresqlを導入する

今までRailsのデータベースにmySQLを使用してきましたが
herokuを使うにあたりRailsでpostgreSQLを導入する
手順をまとめました。

$がついてるコマンドはターミナル上で実行してください。

postgreSQLのインストール

$ brew install postgresql

バージョンの確認

$ psql -V
psql (PostgreSQL) 11.5

データベースの初期化

$ initdb /usr/local/var/postgres -E utf8
The files belonging to this database system will be owned by user "username".
This user must also own the server process.

The database cluster will be initialized with locale "ja_JP.UTF-8".
initdb: could not find suitable text search configuration for locale "ja_JP.UTF-8"
The default text search configuration will be set to "simple".

Data page checksums are disabled.

initdb: directory "/usr/local/var/postgres" exists but is not empty
If you want to create a new database system, either remove or empty
the directory "/usr/local/var/postgres" or run initdb
with an argument other than "/usr/local/var/postgres".

Postgresのバージョンチェック

$ postgres --version
postgres (PostgreSQL) 11.5

PostgresSQLの起動

$ postgres -D /usr/local/var/postgres
2019-08-29 23:50:34.469 JST [22297] LOG:  listening on IPv6 address "::1", port 5432
2019-08-29 23:50:34.469 JST [22297] LOG:  listening on IPv4 address "127.0.0.1", port 5432
2019-08-29 23:50:34.471 JST [22297] LOG:  listening on Unix socket "/tmp/.s.PGSQL.5432"
2019-08-29 23:50:34.498 JST [22298] LOG:  database system was shut down at 2019-08-29 23:27:02 JST
2019-08-29 23:50:34.519 JST [22297] LOG:  database system is ready to accept connections

この時のIPv4 address "127.0.0.1"はローカル・ループバック・アドレスと呼ばれる
localhostのアドレスの実態がこれ。

データベースの確認

ターミナル上で
commant + T (新しいタブ)
もしくは
command + N (新しいウィンドウ)
で別のターミナルを開き、下記のコマンドでデータベースを確認する

$ psql -l
                                         List of databases
   Name    |      Owner       | Encoding | Collate | Ctype |           Access privileges           
-----------+------------------+----------+---------+-------+---------------------------------------
 postgres  | username         | UTF8     | C       | C     | 
 template0 | username         | UTF8     | C       | C     | =c/username                  +
           |                  |          |         |       | username=CTc/username
 template1 | username         | UTF8     | C       | C     | =c/username                  +
           |                  |          |         |       | username=CTc/username
(3 rows)

3つのデータベースが作られているのが確認できる。

postgresを終了させる

ターミナル上で control + c

パスを通す

Postgresを簡単に起動できるようにパスを通す

$ vi ~/.bash_profile
上記コマンドでvimに入って、「i」でインサートモードにする
export PGDATA=/usr/local/var/postgres
を追記する
escでインサートモードを終了
:wqで変更を保存してvimを終了

上の流れは

$ echo 'export PGDATA=/usr/local/var/postgres' >> ~/.bash_profile

で同じことをしたことになる。

変更した.bash_profileを読み込む

$ source ~/.bash_profile

パスを通した状態での起動を確認する

$ postgres

接続を確認

ターミナル上で
commant + T (新しいタブ)
もしくは
command + N (新しいウィンドウ)
で新しいターミナルから接続を確認する

$ psql -d postgres

ここからRails

$ cd projects
$ rails new <アプリの名前> -d postgresql
$ cd <アプリの名前>
$ rails db:create
$ rails s

http://localhost:3000/
にアクセスするとYay!がみれ・・・ない。

PG::ConnectionBad (could not connect to server: No such file or directory
    Is the server running locally and accepting
    connections on Unix domain socket "/tmp/.s.PGSQL.5432"?

エラーが発生している様子。

解消するために、brew経由でインストールしたpostgreを再起動させる

$ brew services start postgresql
$ brew services stop postgresql
$ brew services restart postgresql

Railsを起動させる

$ rails s

データベースがないとのエラーが発生。

ActiveRecord::NoDatabaseError (FATAL:  database “アプリ名” does not exist

なので、データベースを作り押して再度Rails起動

$ rails db:create
$ rails s

http://localhost:3000/
これでYay!が見れるようになった!

参考

https://qiita.com/longtime1116/items/9045717ff8607bed07fe
https://make-from-scratch.com/error-connections-on-unix-domain-socket-tmp-s-pgsql-5432/

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

idを変更してオリジナルURLを作ってみた(Rails)

はじめに

アプリケーション開発をしていて簡単に推測できるURLを利用したくないことってありますよね。
この記事では、id(例えばユーザーのid)をランダムな文字列に変更してオリジナルURLを作成します。
URLは次のようなものを目指します。

https://xxxxx.com/users/7b7375d7c10c97901ce

環境

windows(64bit)
ruby 2.6.3p62
Rails 5.2.2
Cloud9上で開発

手順

今回はUserモデルのuserのidをランダムな文字列に変更していきたいと思います。

1. UserモデルにランダムURL用のカラムを作成

Userモデルにurl_tokenというテーブルを作成します。
このurl_tokenが先ほどのランダムな文字列(=7b7375d7c10c97901ce)に対応します。
まずはマイグレーションファイルを作成し、DBに反映します。

$ rails generate migration add_url_token_to_users url_token:string
$ rails db:migrate

2. URL中のidをurl_tokenに変更

$ rails routes
                   Prefix Verb   URI Pattern                                                                              Controller#Action
                    users POST   /users(.:format)                                                                         chats#create
                 new_user GET    /users/new(.:format)                                                                     users#new
                     user GET    /users/:id(.:format)                                                              
   users#show
                          DELETE /users/:id(.:format) 

という感じになっていると思います。
この:idを:url_tokenと変更します。

まずはルーティングを変更します。

config/routes.rb
Rails.application.routes.draw do
  resources :users, param: :url_token
end

usersのresourcesに、paramオプションでurl_tokenを設定します。

次にモデル内でto_paramメソッドを用いてurl_tokenを指定します。

app/model/user.rb
class User < ApplicationRecord
  validates :name,      presence: true
  validates :url_token, presence: true, uniqueness: true

...

  def to_param
    url_token
  end
end

ルーティングを確認すると:idが:url_tokenに変更されています。

$ rails routes
                   Prefix Verb   URI Pattern                                                                              Controller#Action
                    users POST   /users(.:format)                                                                         chats#create
                 new_user GET    /users/new(.:format)                                                                     users#new
                     user GET    /users/:url_token(.:format)                                                              users#show
                          DELETE /users/:url_token(.:format) 

3. コントローラーでデータを取得する

userをidではなくurl_tokenを用いて取得するためには次のようにします。

@user = User.find_by(url_token: params[:url_token])

このとき、url_token:の部分をid:としないよう気を付けてください。
今まで行った操作は、Userモデルにurl_tokenカラムを作成し、URL内の:idを:url_tokenに変更しただけであって、idそのものをurl_tokenに変更したわけではありません。なのでちゃんとuseのidは存在します。コンソールで確かめると分かると思います。

4. ランダムな文字列を生成する

ランダムな文字列を作成するには、Userモデル内でattributeとSecureRandom.hex(10)を使います。
attributeはモデルの属性の定義や更新を行えます。今回ランダムな文字列はstring型として扱います。
またSecureRandom.hex(10)はランダムな文字列を生成しています。
そして次のようにモデル内で記述します。

app/model/user.rb
class User < ApplicationRecord
  attribute :url_token, :string, default: 

  validates :name,      presence: true
  validates :url_token, presence: true, uniqueness: true

...

  def to_param
    url_token
  end
end

今回はデフォルトにSecureRandom.hex(10)を設定しています。

これでもうオリジナルのURLは作成されているはずですが、いくつか補足しておきます。

pathの使い方

例えばユーザーページのリンクをview内で記述するときは次のようにします。

<%= link_to "ユーザーページ", user_path(url_token: @user.url_token) %>

Strong Parametersの使い方

Storong Parametersを設定するときもいつも通りurl_tokenをカラムの一つとしてpermitに加えてください。

def event_params
  params.require(:user).permit(:name, :email, :url_token)
end

おわりに

URLをオリジナルにするのはそんなに難しくないと思います。
ただネストしたりだとか、seeds.rb、fixureの作成とかで手間取るかもしれないので頑張ってみてください!何か間違いがありましたら、ご指摘ください。

参考文献

(1) "RailsでQiitaみたいなランダム文字列のURLを使う方法". Qiita. https://qiita.com/saitoeku3/items/dd91a290c695aa63e34f, (参照 2019-8-30)

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

大学2年生のオリジナルWebアプリケーション開発8日目

今日の流れ

  1. イベント一覧の表示(続き)
  2. フォーム作成

前回Eventモデルを作成し、作成されたイベントの一覧を表示させ日付の表示を行いました。
今日はその続きでCSSを整えたり、カラム名の変更、そしてイベントを作成するためのフォームを作成しました。

1. イベント一覧の表示(続き)

前回までにほとんどイベント一覧は完成していたのですが、気に入らない部分が二つありました。それは

⑴ イベント名のカラム名がeventであること
⑵ 一覧表のviewが見づらいこと

です。

(1) カラム名変更

Eventモデルのカラム名がeventだと、名前を取り出すときなどは、

@event.event

としなくてはならず、わかりづらかったので、カラム名の変更は以下のようにしました。

モデル名 変更前のカラム名 変更後のカラム名
event event event_name

カラム名変更の手順をまとめました。

migrationファイルの作成

まずはmigrationファイルを作成します。

$ rails generate migration rename_event_column_to_events #eventがカラム名, eventsがモデル名

migrationファイルを編集

db/migrate/○○_rename_event_column_to_events.rb
class RenameEventColumnToEvents < ActiveRecord::Migration[5.2]
  def change
    rename_column :events, :event, :event_name
  end
end

そして最後にDBに反映させます。

db:migrate

(2) borderの角を丸くする

borderの角を丸くするのは簡単でしたが、今まで使ってこなかったのでその方法を自分用に残しておきます。

border-radius: 10px;

こうするだけですね。実際に以下のように使いました。

app/assets/stylesheets/custom.scss
li {
    padding: 10px 0;
    margin-top: 5px;
    border: 1px solid #e8e8e8;
    border-radius: 10px;
  }

実際の画面ではこんな感じです。
イベント一覧.png

画像は当日撮ったものではなく、後日撮ったものなので回答や削除などまだ8日目にはコードにないものもありますが、うまく角が丸くなりました。

2. フォーム作成

フォーム作成自体は難しくなかったのですが、Railsチュートリアルとはいくつか異なる点がありました。

(1) 日付フォーム
(2) placeholder

(1) 日付フォーム

ユーザーにはイベントの日時を設定してもらう必要があるため日付を選択するフォームを作成しなければなりませんでした。
フォームに取り掛かる前は、カレンダーを自作するか、gemでも使うから難しいだろうと考えていました。しかしふたを開けてみたらなんとRailsに用意されているdate.filedタグを使ったらカレンダーもついてきました!ちょっと拍子抜けでした笑。
実際には以下のようにコードを書くとできます。

<%= f.label :date, "日付" %>
<%= f.date_field :date, class: "form-control" %>

カレンダー.png

(2) placeholder

実際にユーザーに使ってもらう時、記入例があるとわかりやすいと思いますので、フォームにあらかじめ記入例を入れておきました(ユーザーが記入すると消える)。

その方法も簡単で以下のように、あらかじめ入れておきたい言葉をplaceholderに続けて記述するだけです。

<%= f.text_field :event_name, class: "form-control", placeholder: "例)練習・旅行・飲み会" %>

すると上の写真のイベント名のフォームのように、あらかじめ記入例が入れられるようになります。

終わりに

イベントの一覧とフォームを完成させることができました。
次はevent_idをオリジナルの文字列(オリジナルのURLを作成する)やAnswerモデルの作成などです。気合い入れていきます!

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

Railsでのランダム表示を実装してみた 簡単!

初めに

ポートフォリオを作成するにあたり、ランダム表示を実装しました。
プログラミング歴4ヶ月の初学者でも簡単に実装できたのでメモを残します。
もし良かったら、参考にしてみてください。

環境

・Ruby '2.3.8'
・Rails '5.2.3'

前提条件

bookというテーブルに、titleとcontentカラムがあるとします。

実装方法

実装方法はは簡単でコントローラーとビューに記述するだけです。

コントローラー

books_controller.rb
#5件表示
@random = Book.order("RANDOM()").limit(5)

#全件表示
@random = Book.order("RANDOM()").all

limitを設定することで表示される件数を指定することができます。

注意点

mysqlを使用しているとエラーが発生します。
その場合は、以下のように記述する必要があります。
(*RANDOMをRANDにしないといけません。)

books_controller.rb
#5件表示
@random = Book.order("RAND()").limit(5)

#全件表示
@random = Book.order("RAND()").all

ビュー

index.html.erb
<% @random.each do |book| %>
  <%= book.title %>
  <%= book.content %>
<% end %>

以上で実装完了です。

参考資料

railsでランダムに複数のレコードを取得する

最後に

たったこれだけで実装できます。
もし良かったら試してみてください。

最後までお付き合い頂きましてありがとうございます。

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

Railsでのランダム表示を実装してみた 簡単![初心者向け]

初めに

ポートフォリオを作成するにあたり、ランダム表示を実装しました。
プログラミング歴4ヶ月の初学者でも簡単に実装できたのでメモを残します。
もし良かったら、参考にしてみてください。

環境

・Ruby '2.3.8'
・Rails '5.2.3'

前提条件

bookというテーブルに、titleとcontentカラムがあるとします。

実装方法

実装方法はは簡単でコントローラーとビューに記述するだけです。

コントローラー

books_controller.rb
#5件表示
@random = Book.order("RANDOM()").limit(5)

#全件表示
@random = Book.order("RANDOM()").all

limitを設定することで表示される件数を指定することができます。

注意点

mysqlを使用しているとエラーが発生します。
その場合は、以下のように記述する必要があります。
(*RANDOMをRANDにしないといけません。)

books_controller.rb
#5件表示
@random = Book.order("RAND()").limit(5)

#全件表示
@random = Book.order("RAND()").all

ビュー

index.html.erb
<% @random.each do |book| %>
  <%= book.title %>
  <%= book.content %>
<% end %>

以上で実装完了です。

参考資料

railsでランダムに複数のレコードを取得する

最後に

たったこれだけで実装できます。
もし良かったら試してみてください。

最後までお付き合い頂きましてありがとうございます。

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

Ruby on Railsでchart.jsに変数を入れる方法

はじめに

19年6月からプログラミングの勉強をはじめているものです。
作成したアプリでchart.jsを使用し、変数を入れるところに苦労したので書いてみます。

chart.jsの導入

導入に関してはこちらを参照、大変分かりやすくグラフの導入部までは簡単にできます。

グラフに変数を入れる。

例えば、毎日の運動時間を測るアプリで、運動時間と日付を棒グラフで作る際は、このような感じになります。

前提 

UsersとSportsとテーブルがある。
UsersとSportsは親子関係で一対複数の関係
Sportsにはsport_day(データ型はdate)とsport_time(データ型はfloat)のカラムを持つ
*created_atでも問題なし

Controllerからです。

X軸はこちら、日付を配列させます。

users_controller.rb
        @graphdays =  @user.sports.order(sport_day: "DESC").limit(6).reverse
        @dayline = Array.new
        @graphdays.each do |graphday|
            @dayline.push(graphday.sport_day.strftime('%m/%d').to_s)
        end

以上、limitの数はご自由に、reverseさせないと表示された時、31日、30日という順番になります。
date型は.to_sを使用しないと文字列として表示されないので注意

Y軸はこちら、時間を配列させます。

users_controller.rb
        graphtimes =  @user.sports.order(sport_day: "DESC").limit(6).reverse
        @timeline = Array.new
        @graphtimes.each do |graphtime|
            @timeline.push(graphtime.sport_time)
        end

こちらもreverseを忘れずに

次はViewです。

show.html.erb
<canvas id="spotsChart" width="200" height="200"></canvas>
   <script>
    var graphdays = <%== @dayline %>, graphtimes = <%= @timeline %>
   </script>
   <script>draw_graph();</script>

ここはvarを使わないと変数が入らないので注意が必要
daylineのところは<%== %>と==が二つならないとなぜか表示されませんでした。
(場合によっては==でなくても大丈夫かも知れません)

最後はcoffeeです。

users.coffee
    window.draw_graph = -> 
    ctx = document.getElementById("sportsChart").getContext('2d')
    sportsChart = new Chart(ctx, {
        type: 'bar',
        data: {
            labels: graphsdays,#ここは日付が表示される X軸に当たる
            datasets: [{
                label: '運動時間',
                data: graphtimes,#ここは時間が表示される Y軸に当たる
                backgroundColor: [
                    'rgba(255, 159, 64, 0.2)',
                    'rgba(255, 159, 64, 0.2)',
                    'rgba(255, 159, 64, 0.2)',
                    'rgba(255, 159, 64, 0.2)',
                    'rgba(255, 159, 64, 0.2)',
                    'rgba(255, 159, 64, 0.2)'
                ],
                borderColor: [
                    'rgba(255, 159, 64, 1)',
                    'rgba(255, 159, 64, 1)',
                    'rgba(255, 159, 64, 1)',
                    'rgba(255, 159, 64, 1)',
                    'rgba(255, 159, 64, 1)',
                    'rgba(255, 159, 64, 1)'
                ],
                borderWidth: 1
            }]
        },
        options: {
            scales: {
                yAxes: [{
                    ticks: {
                        beginAtZero:true
                    }
                }]
            }
        }
    })

このようなグラフができると思います。
ダウンロード (1).png

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

銀座Rails#12@DeNA行ってきました。

昨日行ってきた銀座Rails#12で学んだことをメモ的にまとめておこうと思います。

「出張Railsウォッチ in 銀座Rails」

週刊Railsウォッチの@morimorihogeさん(BPS株式会社)の発表でした。Rails6の新機能や、個人的にはまだ自分は使ったことがないgemなどを色々聞けたことが収穫でした。大規模サービスでは複数DBを使用することもありますが、Rails6には標準で対応(まだ実用は厳しいみたいです)したり、gemだとswitch_point、secondbase(Rails5.1まで対応)などが良いみたいです。複数DBを設定する時はdatabase.ymlの形式が変わったり、migrationもmagration_pathを設定して別々に行うようです。

あと他にも興味深いものを紹介して頂きました。

Fullstaq Ruby...高速化されたRubyのディストリビューション
Ruby on Jets...Rubyのサーバーレスアプリケーションフレームワーク

「Rails使いのNuxt.js入門」

坂川雅俊さんの発表でした。普段、私はRailsをメインに業務をしていますし、そのRailsもまだまだ勉強不足なので、なかなかJavaScriptをしっかり勉強できる機会は少ないのですが、VueやReactを使ってしっかり作られたWebアプリはモバイルのネイティブアプリと比べても差が少ないアプリケーションになっていると感じることも多く、Vue.jsのフレームワークであるNuxt.jsにも関心がありました。発表の内容はNuxt.jsで一から簡単にアプリを使ってみるという内容で、Nuxt.jsも一回は触ってみたくなる内容でした。
Pugという言葉を最近たまに聞いたことがあったのですが、この発表でも使われていてPugとはHTMLを効率的に書くためのテンプレートエンジンで、RubyでいうSlimテンプレートのような記法のことみたいです。Slimみたいにスッキリ書けるのはRubyエンジニアの特権みたいに感じているところもあったのですが、そういう訳でもないみたいですね。

「プログラマがコードを書きながら考えること 」

「プロを目指す人のためのRuby入門」で有名な@jnchito(伊藤淳一) さんの発表でした。伊藤淳一さんがコーディングをする過程を追体験して、アプリを作成しながらその時にどういうことを考えながらコーディングしているかという発表内容でした。作成したアプリケーション自体も自分にはかなり勉強になるものだったのですが、今回の発表内容的にも自分がコーディングをする時との違いや、作業の流れを追うように意識しました。

・公式のドキュメントを参照する
自分の場合は、公式ドキュメントは英語で書かれていることが多くなるべくブログやQiitaなどの日本語記事で済ませようと考えてしまうことが多いです。しかしどうしても個人が前に書いた記事は内容や環境が古くなっていたり、やはり公式のドキュメントに勝るものはないと再認識しました。

・なるべく簡単な機能をつけるところから始めて機能を拡張していく
伊藤淳一さんのようなエンジニアでもいきなり作りたい機能をまるっと作成するのではなく、まず簡単なサンプルを作って設定などが出来ているか確認していたりする姿は個人的には救われたというか、自分も最終的なゴールにたどり着くために途中の適切な目標を作成してアプリを作成していきたいと思いました。

・RubyMineのデバッガ機能でブレークポイントを設定してデバッグ
IDEのデバッガを使って素早くにブレークポイントを設定して、どこまでは正しく処理をしているか確かめている姿は便利な道具をしっかり使いこなせれば、やはり恩恵を受けられると感じさせられました。自分はIDE使っていてもデバッガはまともに使えたことがなかったのですが、また挑戦したいと感じさせられました。

・開発途中で簡単なテスト書いて、実際に動かして確認する時間を短縮
テストの使い方、活用の仕方を実際に感じることが出来ました。自分はまだしっかりとしたテスト書きながら開発が出来ていないので、テストを書く必要性や利点を思い知らされました。

アプリケーションを作成している時の思考過程などを追体験させて頂いて、色々勉強になりましたし普段自分が何度も体験している「あれ?動かないぞ?」という状態は、経験や実力のある人でも当然に起こるものであるということが分かったと同時に、そのエラーが起きてから解決するための技術がやはり違いましたし自分には足りないと感じました。知識や経験によってある程度、問題解決のための方法が直感的に分かることもあるみたいです。

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

Docker + Rails + React

Docker + Rails + React

streampack の minsu です。

今年の夏は主に室内で過ごしていましたが、先日帰省した折に中古のカメラを手に入れたので今後はアウトドアな趣味としてお散歩カメラをきめこみたいと考えています。 涼しくなったら、たぶん

目的

フロント: React
バック: Rails
を Docker を利用して構築します。

React + Rails ですが webpacker を利用する方法で行います。

ファイルの用意

まず、GemfileGemfile.lockDockerfiledcocker-compose.ymlを用意します。

Gemfile
source 'https://rubygems.org'
gem 'rails', '5.1.4'
Dockerfile
FROM ruby:2.4.1

RUN apt-get update -qq && apt-get install -y mysql-client build-essential nodejs apt-transport-https

RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update && apt-get install -y yarn

RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install
COPY . /app
docker-compose.yml
version: '3'
services:
  app:
    build: . 
    command: /bin/sh -c "rm -f /app/tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    depends_on:
      - db

  db:
    image: mysql:5.7
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    environment:
      - MYSQL_ROOT_PASSWORD=root
    volumes:
      - mysql_vol:/var/lib/mysql

volumes:
  mysql_vol:

pid は、開発用WEBサーバを起動するときに tmp/pids/server.pidに書き込まれて終了するときに削除されるのですが、なんらかの要因で削除されずに終了した場合は起動中と判断されて新たにサーバを起動できないのでrm -f /app/tmp/pids/server.pidで起動時に削除します。

rails new

コンテナから rails プロジェクトを作成します。
Gemfileは上書き、DBはMySQLを指定します。

$ docker-compose run app rails new . --force --database=mysql

docker-compose.yml の mysql の rootパスワードを MYSQL_ROOT_PASSWORD=root に設定したので config/database.yml の development に設定を追加しました。
host も同じく指定した db に変更します。

config/database.yml
username: root
password: root
host: db

Gemfile に

gem 'webpacker'
gem 'react-rails'

を追加し、 bundle install しなおした後に

$ docker-compose build

次のコマンドを実行します。

$ docker-compose run app rails webpacker:install
$ docker-compose run app rails webpacker:install:react
$ docker-compose run app rails generate react:install

上の2行は rails new のタイミングで --webpack=reactのオプションを追加でも良かったみたいです。

package.json の更新や
app/javascript/packs/配下に application.jshello_react.jsx が作成されます。

db、 model 作成

適当な model と seeds データを用意して DB を作成後にデータを入れます。

$ docker-compose run app rails g model List title:string desc:string
db/seeds.rb
5.times do
  List.create(
    title: 'title_' + SecureRandom.hex(4),
    desc: 'desc_' + SecureRandom.hex(4)
  )
end
$ docker-compose run app rails db:create
$ docker-compose run app rails db:migrate

作成したモデルを一覧表示させてみます。

controller、view を作成

$ docker-compose run app rails g controller Lists index
lists_controller.rb
  def index
    @lists = List.all
  end

view では javascript_pack_tagreact_component のタグを用いて js を呼び出します。

lists/index.html.erb
<%= javascript_pack_tag 'application' %>

<h1>Lists#index</h1>
<%= react_component 'Lists', lists: @lists %>

react component 作成

順番が前後しましたが、 view で呼び出している components を実装します。

$ rails g react:component Lists

のコマンドで app/javascript/components/Lists.js が作成されるので編集します。

Lists.js
import React from "react"
import PropTypes from "prop-types"
export default class Lists extends React.Component {
  constructor(props){
    super(props)
    this.state = {
      lists: []
    };
  }
  componentDidMount(){
    this.setState({
      lists: this.props.lists
    })
  }
  render () {
    return (
      <div>
        <table>
          <thead>
            <tr>
              <th>ID</th>
              <th>Title</th>
              <th>Description</th>
              <th>created_at</th>
              <th>updated_at</th>
            </tr>
          </thead>
          <tbody>
            {this.state.lists.map((list) => {
              return (
                <tr key={list.id}>
                  <td>{list.id}</td>
                  <td>{list.title}</td>
                  <td>{list.desc}</td>
                  <td>{list.created_at}</td>
                  <td>{list.updated_at}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    );
  }
}

動作確認

rails, webpack を立ち上げます。

$ docker-compose up -d
$ docker-compose run app bin/webpack-dev-server

http://localhost:3000/lists/index にアクセスします。
スクリーンショット 2019-08-30 15.19.12.png
無事に一覧が表示されました。

まとめ

起動と表示確認までを行いました。

この状態では何の機能もないので React での CRUD 操作を実装するまでを追記、または新しく記事にしたいと思います。

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

RailsでAws::Sigv4::Errors::MissingCredentialsError というエラーが出たら

エラー文の例

Rails6の新機能である、Action_textやActive_Storageを利用する際に、awsなどの認証情報をEDITOR=vi rails credentials:editで書き込んでいると思います。しかし、それだけだとローカルでは動作しますが本番環境では動きません。

...
/var/www/app-name/shared/bundle/ruby/2.6.0/gems/aws-sigv4-1.1.0/lib/aws-sigv4/signer.rb:612:in `extract_credentials_provider': Cannot load `Rails.config.active_storage.service`: (Aws::Sigv4::Errors::MissingCredentialsError)
missing credentials, provide credentials with one of the following options:
  - :access_key_id and :secret_access_key
  - :credentials
  - :credentials_provider
    from /var/www/app-name/shared/bundle/ruby/2.6.0/gems/aws-sigv4-1.1.0/lib/aws-sigv4/signer.rb:122:in `initialize'
    from /var/www/app-name/shared/bundle/ruby/2.6.0/gems/aws-sdk-s3-1.46.0/lib/aws-sdk-s3/plugins/s3_signer.rb:190:in `new'
    from /var/www/app-name/shared/bundle/ruby/2.6.0/gems/aws-sdk-s3-1.46.0/lib/aws-sdk-s3/plugins/s3_signer.rb:190:in `build_v4_signer'
    from /var/www/app-name/shared/bundle/ruby/2.6.0/gems/aws-sdk-s3-1.46.0/lib/aws-sdk-s3/plugins/s3_signer.rb:13:in `block in <class:S3Signer>'
    from /var/www/app-name/shared/bundle/ruby/2.6.0/gems/aws-sdk-core-3.64.0/lib/seahorse/client/configuration.rb:70:in `call'
    from /var/www/app-name/shared/bundle/ruby/2.6.0/gems/aws-sdk-core-3.64.0/lib/seahorse/client/configuration.rb:213:in `block in resolve_defaults'
    from /var/www/app-name/shared/bundle/ruby/2.6.0/gems/aws-sdk-core-3.64.0/lib/seahorse/client/configuration.rb:57:in `each'
    from /var/www/app-name/shared/bundle/ruby/2.6.0/gems/aws-sdk-core-3.64.0/lib/seahorse/client/configuration.rb:57:in `each'
...

解決方法

おそらく大抵の場合、credentialsが読み込まれていないのが原因だと思われるのですが、そもそも読み込むように対処していないのでこのようなエラーが出るのは必然的です。そこで、上手く認証情報が読み込まれるように設定する必要があります。

deploy.rb
# 以下を追記
append :linked_files, 'config/master.key'

次に、サーバー側にログインして、shared/configの配下にローカルと同じmaster.keyファイルを作成する。
自分の場合ec2を使用しており、pathは/var/www/アプリケーション/shared/config/master.keyといった感じでした。

master.keyの内容はローカルと同じく認証コードをコピペして貼れば大丈夫です。

作業例

$ cd /shared/config
$ vi master.key

master.keyには123456abcde78910みたいなコードが書かれているはずなのでそれをコピーしてペーストすれば完了です。

後はデプロイすれば無事に認証情報が通り、動くはずです。

参考リンク先

・secrets.ymlや環境変数をRails 5.2のEncrypted Credentialsに移行する
https://qiita.com/d-mato/items/aab2b6b2f587a8582631

・Rails 5.2の新機能Credentialsでパスワード等を管理する
https://thr3a.hatenablog.com/entry/20180408/1523156956

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

Rails 5.2 から 6.0 にアップグレードしたので手順のメモ

弊社はRuby on Railsを中心に扱っている、Webサービス受託開発会社です。

先日、運用中のサービスのRailsを5.2から6.0にアップグレードしました。
私は長くRailsと関わっているのでほぼルーティンになりましたが、誰かの参考になるかもしれないので手順を書き留めておきます。

アップグレード対象によって、追加で作業が必要になるかもしれません。
場合によってはgemの依存関係を解決できずforkしたり、他のgemに置き換えたりすることもあるでしょう。

作業方針の参考程度に捉えていただければと思います。

(といっても、ほとんど Railsガイドのアップグレードガイド にある通りに作業しただけで、ちょっとした補足をしているだけです)

日頃からできているとよいこと

  • バージョン管理システムの利用
  • 自動テストの整備
  • gemのアップデート
  • なるべく新しいバージョンのRubyへの対応

バージョン管理システムの利用

言うまでもなくアップグレードは一筋縄ではいかないことも多いので、少しずつ作業したり、差し戻したり、作業中にほかの作業を取り込んだり・・・といったことも発生します。
また、アップデートタスクでフレームワークのファイルを更新したとき、差分を確認するのに便利です。

自動テストの整備

Railsのアップグレードは大きな変更を伴うものですから、まず壊れます。これを見つけ、正すには自動テストの整備は必須です。

gemのアップデート

rails gem のアップデートにあわせて、Railsに依存する gem のアップデートが必要になる場合は多いです。
依存gem のアップデートによる影響が最小限になるよう、gemはなるべく最新に保つようにします。

なるべく新しいバージョンのRubyへの対応

Railsはリリース時点の最新のRubyをサポートします。
gemと同様に、Rubyのバージョンも追従したほうがよいです。

アップグレードの実施

0. DEPRECATION WARNING 潰し

Rails は将来互換性がなくなる機能を利用しているとき、警告と移行方法を提示してくれます。
アップグレード前に壊れることがわかるので、アップグレードの前に修正しておきます。

1. 依存gemのアップデート

各gemをアップグレード先のRailsに対応しているバージョンにアップデートします。

ちなみに、弊社では可能な限り最新の gem を維持しています。

  • Dependabot の導入
  • Gemfileでは gem のバージョンを原則縛らない!

2. Rubyのアップデート

アップデート前、アップデート後両方が動くRubyバージョンのうち、最新のものにアップデートしておきます。
今回は Ruby 2.6 にしました。

ここまででテストをパスすることをよく確認しておきます。

3. rails gem のアップデート

Rails アップグレードガイドに従って作業を進めていきます。

# before: gem 'rails', '~> 5.2'
gem 'rails', '~> 6.0'
$ bundle update rails

rails gemのバージョンが大ききなることで解決できなくなる依存関係が列挙されるので、それぞれ確認し、update対象に加えます。

Fetching gem metadata from http://rubygems.org/.........
Fetching gem metadata from http://rubygems.org/.
Resolving dependencies.....
Bundler could not find compatible versions for gem "railties":
  In Gemfile:
    devise was resolved to 4.7.0, which depends on
      railties (>= 4.1.0)

    jquery-rails was resolved to 4.3.5, which depends on
      railties (>= 4.2.0)

    letter_opener_web was resolved to 1.3.4, which depends on
      railties (>= 3.2)

    meta_request was resolved to 0.7.2, which depends on
      railties (>= 3.0.0, < 7)

    rails (~> 6.0) was resolved to 6.0.0, which depends on
      railties (= 6.0.0)

    rails-i18n was resolved to 5.1.3, which depends on
      railties (>= 5.0, < 6)

    rspec-rails was resolved to 3.8.2, which depends on
      railties (>= 3.0)

    sassc-rails was resolved to 2.1.2, which depends on
      railties (>= 4.0.0)

    web-console was resolved to 3.7.0, which depends on
      railties (>= 5.0)

rails 6.0 が railties 6.0.0 を要求しているものの、
rails-i18n 5.1.3 が railties 6 未満を要求していることがわかります。
ここで依存性の重複が発生したようです。

Bundler: bundle update - Overlapping Dependencies

rails-i18n を確認してみます。

https://rubygems.org/gems/rails-i18n

すると、rails-i18n 6.0.0 という、 rails 6.0 に対応したものがリリースされていました。

https://rubygems.org/gems/rails-i18n/versions/6.0.0

rails と一緒に rails-i18n をアップデートしてみます。

$ bundle update rails railties rails-i18n

無事 rails gem のアップデートができました。

Fetching gem metadata from http://rubygems.org/.........
Fetching gem metadata from http://rubygems.org/.
Resolving dependencies.....
(snip)
Using activesupport 6.0.0 (was 5.2.3)
(snip)
Using activemodel 6.0.0 (was 5.2.3)
(snip)
Using activejob 6.0.0 (was 5.2.3)
Using activerecord 6.0.0 (was 5.2.3)
(snip)
Using actionview 6.0.0 (was 5.2.3)
(snip)
Using actionpack 6.0.0 (was 5.2.3)
(snip)
Using activestorage 6.0.0 (was 5.2.3)
Using actionmailer 6.0.0 (was 5.2.3)
(snip)
Using actioncable 6.0.0 (was 5.2.3)
(snip)
Using railties 6.0.0 (was 5.2.3)
(snip)
Using rails 6.0.0 (was 5.2.3)
Using rails-i18n 6.0.0 (was 5.1.3)
(snip)
Bundle updated!

4. アップデートタスク

アップデートタスクを実行します。

$ bundle exec rails app:update

途中 conflict が報告され、上書きしてよいか確認してくれます。
適切にバージョン管理されていれば上書き後差分を確認できますし、戻すこともできるので、すべて上書きします。

    conflict  config/boot.rb
Overwrite /home/takeyuweb/Projects/myapp/config/boot.rb? (enter "h" for help) [Ynaqdhm] a
       force  config/boot.rb
       exist  config
    conflict  config/routes.rb
       force  config/routes.rb
    conflict  config/application.rb
       force  config/application.rb
   identical  config/environment.rb
    conflict  config/cable.yml
       force  config/cable.yml
    conflict  config/puma.rb
       force  config/puma.rb
   identical  config/storage.yml
       exist  config/environments
    conflict  config/environments/development.rb
       force  config/environments/development.rb
    conflict  config/environments/production.rb
       force  config/environments/production.rb
    conflict  config/environments/test.rb
       force  config/environments/test.rb
       exist  config/initializers
   identical  config/initializers/application_controller_renderer.rb
    conflict  config/initializers/assets.rb
       force  config/initializers/assets.rb
   identical  config/initializers/backtrace_silencers.rb
    conflict  config/initializers/content_security_policy.rb
       force  config/initializers/content_security_policy.rb
   identical  config/initializers/cookies_serializer.rb
      create  config/initializers/cors.rb
   identical  config/initializers/filter_parameter_logging.rb
   identical  config/initializers/inflections.rb
    conflict  config/initializers/mime_types.rb
       force  config/initializers/mime_types.rb
      create  config/initializers/new_framework_defaults_6_0.rb
   identical  config/initializers/wrap_parameters.rb
       exist  config/locales
    conflict  config/locales/en.yml
       force  config/locales/en.yml
      remove  config/initializers/cors.rb
       exist  bin
   identical  bin/rails
   identical  bin/rake
    conflict  bin/setup
       force  bin/setup
   identical  bin/yarn
       rails  active_storage:update
Copied migration 20190829054009_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb from active_storage

After this, check Rails upgrade guide at https://guides.rubyonrails.org/upgrading_ruby_on_rails.html for more details about upgrading your app.

更新のあったファイルを個別に確認して、必要に応じて編集したり、差し戻したりしていきます。
たとえば routes.rb を上書きした場合は、ルーティングの記述を復活させる必要があるでしょう。
差分を確認しながら進めていきます。

config.load_defaults について

アップグレード時はなるべく変更が小さくなるように努めるべきだと考えます。
まずは従来のバージョンのデフォルト設定を使うようにします。

config.load_defaults 5.2

Rails 5.2 => 6.0 固有の内容について

Rail アップグレードガイド - Rails 5.2からRails 6.0へのアップグレード
を参考に作業を進めます。

今回はCookieの互換性がいますぐ失われるのを避けたかったので、以下を new_framework_defaults_6_0.rb で設定しました。

new_framework_defaults_6_0.rb
Rails.application.config.action_dispatch.use_cookies_with_metadata = false

また、Action Cable を使用していたのでそちらの対応を行いました。

オートローダーについて

Rails 6.0 からはオートローダーが Zeitwerk になり、オートロードの挙動が変わっています。

定数の自動読み込みと再読み込み (Zeitwerk)

config.load_defaults 5.2 では従来のものが使われるので、いったん置いておきます。
従来のオートローダーで正しく動くことを保証できるようになってから、切り替えることを考えることにします。

テスト実行

$ bundle exec rails test
# または
$ bundle exec rspec

おそらく大量のテストが失敗するでしょう。
地道に修正していきます。(大抵は変な書き方をしてたり、隠れてたバグが表面化したり、といったケーススだったりします)

rspec-rails を使っている場合

Rails 6.0 対応の rspec-rails は4系になりますが、この記事の作成時点でベータ版( 4.0.0.beta2 )のため、 bundle update するだけでは入りません。Gemfile を触ります。

https://rubygems.org/gems/rspec-rails

Gemfile
gem 'rspec-rails', '4.0.0.beta2'
$ bundle update rspec-rails

今後やっていくこと

DEPRECATION WARNING 潰し

Rails 6.1 で互換性がなくなる機能を使っていると警告が表示されるので修正していきます。

DEPRECATION WARNING: Uniqueness validator will no longer enforce case sensitive comparison in Rails 6.1. To continue case sensitive comparison on the :beacon attribute in User model, pass case_sensitive: true option explicitly to the uniqueness validator.

config.load_defaults 6.0 にする

今回 new_framework_defaults_6_0.rbRails.application.config.action_dispatch.use_cookies_with_metadata = false を設定しました。
検討や必要に応じて修正を進め、 new_framework_defaults_6_0.rb を削除できるようになれば、晴れて config.load_defaults 6.0 にでき、Rails 6.0 対応を終えたといえるでしょう。

Zeitwerk に対応させる

config.load_defaults 6.0 にした後も、当初は従来と同じオートロードの挙動になるようにするには、以下のようにします。

application.rb
config.autoloader = :classic

ドキュメントに従って、従来のオートローダーから新しいオートローダーである Zeitwerk に対応するための修正を行っていきます。

Rails 5.2からRails 6.0へのアップグレード オートローディング

終わりに

Railsに限らず、アップグレードのコツは、溜めないことだと思っています。

個人的には、Rails 5.2 から 6.0 へは、メジャーバージョンアップにしては楽だと感じました。

皆さんも、サックリとアップグレードを済ませて、6.1 の登場を待ちましょう。

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

Rails 5.2 から 6.0 にアップグレードしたので手順メモ

弊社はRuby on Railsを中心に扱っている、Webサービス受託開発会社です。

先日、運用中のサービスを Rails 6.0 にアップグレードしました。
私は長くRailsと関わっているのでほぼルーティンになりましたが、誰かの参考になるかもしれないので手順を書き留めておきます。

アップグレード対象によって、追加で作業が必要になるかもしれません。
場合によってはgemの依存関係を解決できずforkしたり、他のgemに置き換えたりすることもあるでしょう。

作業方針の参考程度に捉えていただければと思います。

(といっても、ほとんど Railsガイドのアップグレードガイド にある通りに作業しただけで、ちょっとした補足をしているだけです)

日頃からできているとよいこと

  • バージョン管理システムの利用
  • 自動テストの整備
  • gemのアップデート
  • なるべく新しいバージョンのRubyへの対応

バージョン管理システムの利用

言うまでもなくアップグレードは一筋縄ではいかないことも多いので、少しずつ作業したり、差し戻したり、作業中にほかの作業を取り込んだり・・・といったことも発生します。
また、アップデートタスクでフレームワークのファイルを更新したとき、差分を確認するのに便利です。

自動テストの整備

Railsのアップグレードは大きな変更を伴うものですから、まず壊れます。これを見つけ、正すには自動テストの整備は必須です。

gemのアップデート

rails gem のアップデートにあわせて、Railsに依存する gem のアップデートが必要になる場合は多いです。
依存gem のアップデートによる影響が最小限になるよう、gemはなるべく最新に保つようにします。

なお、弊社では原則として Gemfile でバージョンを縛らない運用をしています。

なるべく新しいバージョンのRubyへの対応

Railsはリリース時点の最新のRubyをサポートします。
gemと同様に、Rubyのバージョンも追従したほうがよいです。

アップグレードの実施

0. DEPRECATION WARNING 潰し

Rails は将来互換性がなくなる機能を利用しているとき、警告と移行方法を提示してくれます。
アップグレード前に壊れることがわかるので、アップグレードの前に修正しておきます。

1. gemのアップデート

各gemを可能な限りアップデートして、正しく動作することを確認しておきます。

2. Rubyのアップデート

アップデート前、アップデート後両方が動くRubyバージョンのうち、最新のものにアップデートして正しく動作することを確認しておきます。
今回は Ruby 2.6 にしました。

3. rails gem のアップデート

Rails アップグレードガイドに従って作業を進めていきます。

# before: gem 'rails', '~> 5.2'
gem 'rails', '~> 6.0'
$ bundle update rails

rails gemのバージョンが変化することで解決できなくなる依存関係が列挙されるので、それぞれ確認ます。

Fetching gem metadata from http://rubygems.org/.........
Fetching gem metadata from http://rubygems.org/.
Resolving dependencies.....
Bundler could not find compatible versions for gem "railties":
  In Gemfile:
    devise was resolved to 4.7.0, which depends on
      railties (>= 4.1.0)

    jquery-rails was resolved to 4.3.5, which depends on
      railties (>= 4.2.0)

    letter_opener_web was resolved to 1.3.4, which depends on
      railties (>= 3.2)

    meta_request was resolved to 0.7.2, which depends on
      railties (>= 3.0.0, < 7)

    rails (~> 6.0) was resolved to 6.0.0, which depends on
      railties (= 6.0.0)

    rails-i18n was resolved to 5.1.3, which depends on
      railties (>= 5.0, < 6)

    rspec-rails was resolved to 3.8.2, which depends on
      railties (>= 3.0)

    sassc-rails was resolved to 2.1.2, which depends on
      railties (>= 4.0.0)

    web-console was resolved to 3.7.0, which depends on
      railties (>= 5.0)

rails 6.0 が railties 6.0.0 を要求しているものの、
rails-i18n 5.1.3 が railties 6 未満を要求していることがわかります。
ここで依存性の重複が発生したようです。

Bundler: bundle update - Overlapping Dependencies

rails-i18n を確認してみます。

https://rubygems.org/gems/rails-i18n

すると、rails-i18n 6.0.0 という、 rails 6.0 に対応したものがリリースされていました。

https://rubygems.org/gems/rails-i18n/versions/6.0.0

rails と一緒に rails-i18n をアップデートしてみます。

$ bundle update rails railties rails-i18n

無事 rails gem のアップデートができました。

Fetching gem metadata from http://rubygems.org/.........
Fetching gem metadata from http://rubygems.org/.
Resolving dependencies.....
(snip)
Using activesupport 6.0.0 (was 5.2.3)
(snip)
Using activemodel 6.0.0 (was 5.2.3)
(snip)
Using activejob 6.0.0 (was 5.2.3)
Using activerecord 6.0.0 (was 5.2.3)
(snip)
Using actionview 6.0.0 (was 5.2.3)
(snip)
Using actionpack 6.0.0 (was 5.2.3)
(snip)
Using activestorage 6.0.0 (was 5.2.3)
Using actionmailer 6.0.0 (was 5.2.3)
(snip)
Using actioncable 6.0.0 (was 5.2.3)
(snip)
Using railties 6.0.0 (was 5.2.3)
(snip)
Using rails 6.0.0 (was 5.2.3)
Using rails-i18n 6.0.0 (was 5.1.3)
(snip)
Bundle updated!

4. アップデートタスク

アップデートタスクを実行します。

$ bundle exec rails app:update

途中 conflict が報告され、上書きしてよいか確認してくれます。
適切にバージョン管理されていれば上書き後差分を確認できますし、戻すこともできるので、すべて上書きします。

    conflict  config/boot.rb
Overwrite /home/takeyuweb/Projects/myapp/config/boot.rb? (enter "h" for help) [Ynaqdhm] a
       force  config/boot.rb
       exist  config
    conflict  config/routes.rb
       force  config/routes.rb
    conflict  config/application.rb
       force  config/application.rb
   identical  config/environment.rb
    conflict  config/cable.yml
       force  config/cable.yml
    conflict  config/puma.rb
       force  config/puma.rb
   identical  config/storage.yml
       exist  config/environments
    conflict  config/environments/development.rb
       force  config/environments/development.rb
    conflict  config/environments/production.rb
       force  config/environments/production.rb
    conflict  config/environments/test.rb
       force  config/environments/test.rb
       exist  config/initializers
   identical  config/initializers/application_controller_renderer.rb
    conflict  config/initializers/assets.rb
       force  config/initializers/assets.rb
   identical  config/initializers/backtrace_silencers.rb
    conflict  config/initializers/content_security_policy.rb
       force  config/initializers/content_security_policy.rb
   identical  config/initializers/cookies_serializer.rb
      create  config/initializers/cors.rb
   identical  config/initializers/filter_parameter_logging.rb
   identical  config/initializers/inflections.rb
    conflict  config/initializers/mime_types.rb
       force  config/initializers/mime_types.rb
      create  config/initializers/new_framework_defaults_6_0.rb
   identical  config/initializers/wrap_parameters.rb
       exist  config/locales
    conflict  config/locales/en.yml
       force  config/locales/en.yml
      remove  config/initializers/cors.rb
       exist  bin
   identical  bin/rails
   identical  bin/rake
    conflict  bin/setup
       force  bin/setup
   identical  bin/yarn
       rails  active_storage:update
Copied migration 20190829054009_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb from active_storage

After this, check Rails upgrade guide at https://guides.rubyonrails.org/upgrading_ruby_on_rails.html for more details about upgrading your app.

更新のあったファイルを個別に確認して、必要に応じて編集したり、差し戻したりしていきます。
たとえば routes.rb を上書きした場合は、ルーティングの記述を復活させる必要があるでしょう。
差分を確認しながら進めていきます。

config.load_defaults について

アップグレード時はなるべく変更が小さくなるように努めるべきだと考えます。
まずは従来のバージョンのデフォルト設定を使うようにします。

config.load_defaults 5.2

Rails 5.2 => 6.0 固有の内容について

Rail アップグレードガイド - Rails 5.2からRails 6.0へのアップグレード
を参考に作業を進めます。

今回はCookieの互換性がいますぐ失われるのを避けたかったので、以下を new_framework_defaults_6_0.rb で設定しました。

new_framework_defaults_6_0.rb
Rails.application.config.action_dispatch.use_cookies_with_metadata = false

また、Action Cable を使用していたのでそちらの対応を行いました。

オートローダーについて

Rails 6.0 からはオートローダーが Zeitwerk になり、オートロードの挙動が変わっています。

定数の自動読み込みと再読み込み (Zeitwerk)

config.load_defaults 5.2 では従来のものが使われるので、いったん置いておきます。
従来のオートローダーで正しく動くことを保証できるようになってから、切り替えることを考えることにします。

テスト実行

$ bundle exec rails test
# または
$ bundle exec rspec

おそらく大量のテストが失敗するでしょう。
地道に修正していきます。(大抵は変な書き方をしてたり、隠れてたバグが表面化したり、といったケーススだったりします)

rspec-rails を使っている場合

Rails 6.0 対応の rspec-rails は4系になりますが、この記事の作成時点でベータ版( 4.0.0.beta2 )のため、 bundle update するだけでは入りません。Gemfile を触ります。

https://rubygems.org/gems/rspec-rails

Gemfile
gem 'rspec-rails', '4.0.0.beta2'
$ bundle update rspec-rails

今後やっていくこと

DEPRECATION WARNING 潰し

Rails 6.1 で互換性がなくなる機能を使っていると警告が表示されるので修正していきます。

DEPRECATION WARNING: Uniqueness validator will no longer enforce case sensitive comparison in Rails 6.1. To continue case sensitive comparison on the :beacon attribute in User model, pass case_sensitive: true option explicitly to the uniqueness validator.

config.load_defaults 6.0 にする

今回 new_framework_defaults_6_0.rbRails.application.config.action_dispatch.use_cookies_with_metadata = false を設定しました。
検討や必要に応じて修正を進め、 new_framework_defaults_6_0.rb を削除できるようになれば、晴れて config.load_defaults 6.0 にでき、Rails 6.0 対応を終えたといえるでしょう。

Zeitwerk に対応させる

config.load_defaults 6.0 にした後も、当初は従来と同じオートロードの挙動になるようにするには、以下のようにします。

application.rb
config.autoloader = :classic

ドキュメントに従って、従来のオートローダーから新しいオートローダーである Zeitwerk に対応するための修正を行っていきます。

Rails 5.2からRails 6.0へのアップグレード オートローディング

終わりに

Railsに限らず、アップグレードのコツは、溜めないことだと思っています。

個人的には、Rails 5.2 から 6.0 へは、メジャーバージョンアップにしては楽だと感じました。

皆さんも、サックリとアップグレードを済ませて、6.1 の登場を待ちましょう。

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

toggleメソッドで表示→非表示のイベント実装

こんばんは!今日はjs/jQueryで実装する部分があり、その中でtoggleがめちゃ便利だったので備忘録として。

toggleメソッドとは?

toggleメソッドは表示・非表示を切り替える事ができるjQueryの便利なメソッド。hideとshowが合体したメソッド。

js/jQueryでclickイベントを実装したい

実装したい事

demo
①クリックしたら画像部分が表示される
②もう一度クリックしたら画像部分が非表示になる
※ちなみgyazo gifをqittaで表示する方法は![demo](http://gyazo.com/xxxxxxxxxx/raw)でいけます

GyazoでアップロードしたGifアニメーションを簡単に表示する方法。(URLのみでOK)https://qiita.com/Kobutorina_hato/items/d28d4cc90096e058566d

準備

gem 'jquery-rails'を記述
bunde installします

application.js
//= require activestorage
//= require turbolinks
//= require_tree .
//= require jquery #追加
//= require jquery_ujs #追加

jQueryのライブラリを読み込ませましょう。JavaScriptの前に記述しないとエラーします

app/views/layouts/application.html.erb
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>

これを実行する事でスクリプトファイルの読み込むためにスクリプトファイルを自動的に生成してくれます

うまくいかない

sample.html.haml
.new-member-registration-form-content__group.whatnumber-text-right
  .signup-seqcode-text
    %i.fas.fa-question-circle{ style: "color:royalblue;" }
    カード裏面の番号とは?
    .signup-seqcode-info

classのsignup-seqcode-infoをクリックしたらイベント発火させたい

sample.js
$(function() {
  let btn = document.querySelector(".signup-seqcode-text");
  let image = `<div class="signup-seqcode-info is-show">
                  カードの裏面をご残照下さい。
                  <img src="//www
                  ://表示したい画像のURL" alt="" width="240">
              </div>`

  btn.addEventListener("click", function() {
    $(".signup-seqcode-info").html(image);
  });
});

指定のクラス名.signup-seqcode-textをクリックすると変数image.signup-seqcode-info要素の下に表示されるように実装できた。しかし表示はできるがどうすれば非表示にできるか分からない。off()やremove()使ってみたが、動的に出現したhtmlを消す方法がうまくいかず。

toggleメソッドで簡単に実装できた

今日のメインテーマのtoggle登場。色々調べて書いてみて動かなくてを繰り返していたら、toggleメソッドだったら簡単にいけるのではないかと。

sample.haml
.new-member-registration-form-content__group.whatnumber-text-right
            .signup-seqcode-text
              %i.fas.fa-question-circle{ style: "color:royalblue;" }
              カード裏面の番号とは?
              .signup-seqcode-info
              .signup-seqcode-info.is-show
                カードの裏面をご参照下さい
                = image_tag "//www://表示したい画像.png?3312594182", alt: "", width: "240"

表示したい文字カードの裏面をご参照下さいと画像部分=image_tagはhamlに書いておく
.signup-seqcode-info.is-showはクリックして動的に追加したDOM要素に与えるクラス

sample.scss
.signup-seqcode-info.is-show {
  width: 300px;
  display: none;
  position: absolute;
  top: 6px;
  z-index: 1;
  padding: 16px;
  border-radius: 6px;
  background: #eee;
  text-align: center;
  color: #333;
  line-height: 1.5;
  img {
    padding-top: 10px;
  }
}

cssでdisplay:none;にしてデフォルト時は非表示にする
デフォルト時は見えないですが、クリックして出現する時にどこに表示したいかをcssで決めておきましょ。ポイントはz-index: 1;を忘れると他の要素の下に潜り込みますのでご注意を。

sample.js
$(function() {
  $('.signup-seqcode-text').click(function() {
    $('.is-show').toggle();
  })
});

指定したクラス名.signup-seqcode-textをクリックするとイベント発火
toggleはクリック1回目showイベント発火で.is-show部分が表示される
クリック2回目hideイベントで.is-show部分が非表示になる

↓↓完成形をもう一度↓↓
demo

最初は二回clickイベントを作る必要があると思っていたがtoggleメソッド使えば超短い記述で実装できた

toggleは引数も指定できる

【 対象要素.toggle( ミリ秒 ) 】
◯ミリ秒かけて表示・非表示が行われる

【 対象要素.toggle( ミリ秒, 関数 ) 】
◯ミリ秒かけて表示・非表示をした後に関数を実行する事もできます(これ実装してないので詳しくは割愛)

toggleはアニメーションも設定できる

  • 【 fast 】:素早く非表示にする
  • 【 slow 】:ゆっくり非表示にする
  • 【 swing 】:デフォルトの非表示スタイル
  • 【 linear 】:一定の速度で非表示にする

toggle兄弟いろいろ

詳しい説明は省略しますが、「fadeToggle()」,「toggleClass()」,「slideToggle()」はよく使われるいたいです

fadetoggle()はじわーっと表示・非表示にしてくれます

toggleClass()は対象となる要素のclass属性値を追加したり削除したりを繰り返すことが可能なメソッド

slideToggle()は特定の要素を縦方向にアニメーションしながら表示・非表示する事ができます

この辺りはフロント実装で使えそうなので下記サイトを参考に使ってみたいなぁと思います

30分で理解!jQueryのtoggle()と3種のメソッド活用術!
https://www.sejuku.net/blog/40705

まとめ

そういえば以前にもtoggleってなんだろ?ってちょろっと調べた事ありました。ただ実際に動かす機会がないと分かりませんね。js/jQuery苦手なんですけど(他が得意なわけではない笑)、やっぱり見た目の変化が分かりやすいので意図した動きになった時は楽しいです。

終わり

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