- 投稿日:2020-10-12T23:56:06+09:00
今回使ったlink_toのいろいろ、まとめてみた
はじめに
今回のカリキュラムで一番躓いたのが、
link_toメソッド
だった。もちろん基本的な使い方は理解しているつもりだが、どうもpathの引数がしっくりときていない。今回の投稿は何かを説明する目的ではなく、自分がコードを読むための記録である。
以下、今回作成したアプリの全link_toを余計な記述はカットして引数の読み方とともに載せる。全link_toメソッド
①
application.html.erb<%= link_to "ログアウト", destroy_user_session_path, method: :delete %> <%= link_to "新規投稿", new_prototype_path %>サインイン状態で表示させている「ログアウト」と「新規投稿」どちらも誰もが共通するページや処理のため、( )で引数を渡す必要がない。
ユーザーによってログアウトページが違うことはないし、ユーザーによって新規投稿ページが違うことはない。
link_toメソッド
はデフォルトでHTTPメソッドがGETのため、ログアウトのときは、第三引数にメソッドを指定する。②
application.html.erb<%= link_to "ログイン", new_user_session_path %> <%= link_to "新規登録", new_user_registration_path %>①と考え方は同じ。今度は非ログイン状態のときの表示。ログイン画面も新規登録もユーザーによって変わることはないから、引数がなくてよい。
③
application.html.erb<%= link_to image_tag("logo.png"), root_path %>root_pathは引数がなくてもいける!
④
prototypes/show.html.erb<%= link_to "編集する", edit_prototype_path(@prototype) %> <%= link_to "削除する", prototype_path(@prototype), method: :delete %>投稿したものの詳細ページから、編集したり、削除したりする部分。
showアクションの中で、@prototype = Prototype.find(params[:id])
と一つのレコードを選び出しているため、どのprototypeを編集・削除するか判断ができる。⑤
prototypes/_prototype.html.erb<%= link_to prototype.title, prototype_path(prototype.id) %> <%= link_to image_tag(prototype.image), prototype_path(prototype.id) %>user_pathシリーズ
user_pathはユーザーのマイページに飛ぶ。誰のマイページなのか明らかにするため、引数が必要になる。
prototypes/index.html.erb<%= link_to current_user.name + "さん", user_path(current_user) %>ログイン中のユーザー名をクリックするとそのユーザーのマイページに飛ぶ。
deviseのGemを用いることによって使えるcurrent_user
。prototypes/_prototype.html.erb<%= link_to "by " + prototype.user.name, user_path(prototype.user.id) %>prototypeとアソシエーションしているuserのidを取得。
prototypes/show.html.erb<%= link_to "by " + @prototype.user.name, user_path(@prototype.user.id) %>誰による投稿か、名前が表示されている部分のコード。
showアクションの中で、@prototype = Prototype.find(params[:id])
と一つのレコードを選び出しているため、prototypeとアソシエーションしているuserのidを取得できる。prototypes/show.html.erb<%= link_to comment.user.name, user_path(comment.user.id) %>誰のコメントか表示されているところのコード。each文で|ブロックパラメーター(変数)に
comment
|が入り、commentとアソシエーションしているuserのidを取得。
- 投稿日:2020-10-12T23:36:47+09:00
[Rails]Rspecを使ったテストコード
はじめに
Rspecを導入し、テストコードを書いてみようと思います。
コマンドはdocker環境のコマンドを使う。Gemの導入
group :development, :test do gem 'rspec-rails' gem 'factory_bot_rails' gem 'faker', "~> 2.8" end
docker-compose run web bundle install
docker-compose build
インストール完了。Rspecの設定
docker-compose run webrails g rspec:install
上記コマンドを行うと、下記ファイルが生成される。create .rspec create spec create spec/spec_helper.rb create spec/rails_helper.rb.rspc --format documentationコード作成
spec/models/user_spec.rbrequire 'rails_helper' describe User do describe '#create' do it "usernameとemail,passwordとpassword_comnfirmationが存在すれば登録できること" do user = build(:user) expect(user).to be_valid end it "usernameがない場合は登録できないこと" do user = build(:user, username: nil) user.valid? expect(user.errors[:username]).to include("can't be blank") end it "emailがない場合は登録できないこと" do user = build(:user, email: nil) user.valid? expect(user.errors[:email]).to include("can't be blank") end it "passwordがない場合は登録できないこと" do user = build(:user, password: nil) user.valid? expect(user.errors[:password]).to include("can't be blank") end it "passwordが存在してもpassword_confirmationがない場合は登録できないこと" do user = build(:user, password_confirmation: "") user.valid? expect(user.errors[:password_confirmation]).to include("doesn't match Password") end it "重複したemailがある場合は登録できないこと" do user = create(:user) another_user = build(:user, email: user.email) another_user.valid? expect(another_user.errors[:email]).to include("has already been taken") end it "passwordが6文字以上であれば登録できること" do user = build(:user, password: "000000", password_confirmation: "000000") expect(user).to be_valid end it "passwordが5文字以下であれば登録できないこと" do user = build(:user, password: "00000", password_confirmation: "00000") user.valid? expect(user.errors[:password]).to include("is too short (minimum is 6 characters)") end:grin: end endspec/factories/users.rbFactoryBot.define do factory :user do username {"aaa"} password {"000000"} password_confirmation {"000000"} sequence(:email) {Faker::Internet.email} end end
docker-compose run web bundle exec rspec
8 examples, 0 failuresとなれば、テストはうまく通過している。
おわりに
今回はRspecを使ったテストの入りを行いました。
今後、コントローラーのテストも行っていきます。
最後まで読んでいただきありがとうございます
- 投稿日:2020-10-12T22:28:16+09:00
クラウドIDE:Ruby on RailsチュートリアルでHerokuがインストールできなかった件
Ruby on Railsのチュートリアルで、Herokuをインストールしようとしたら、以下のエラーが出て進まなかった件。
調べても何が悪いのかよくわからなかった(゚∀゚)。
bash: /home/ec2-user/.profile: Permission denied
実行コマンドはチュートリアルに記載してあった下記の通り。
source <(curl -sL https://cdn.learnenough.com/heroku_install)
環境
・AWS,Cloud9の統合環境(クラウド統合環境)
対処
解決方法をググっても特に見つからなかった\(^o^)/。
Heroku CLIをインストールするらしいので、Heroku CLIのインストール方法を確認した。
書いてあるコマンドで、チュートリアル以外のコマンドでインストールできないか調べた。
https://devcenter.heroku.com/articles/heroku-cli下の方にnpmコマンドを使ってもインストールできることが書いてある。
インストールの注意文を見ると、「npm」と「node」が入っているのが前提のインストール方法なのだそうだ。This installation method is required for users on ARM and BSD. You must have node and npm installed already.
npm install -g heroku
というわけでクラウドIDEに入っているかを確認した。
どちらも入っているらしいので、ダメ元で記載されていたコマンドを使ったらインストールができた。
もし詰まっていたら、一度この方法を試してみてください。(役に立つかはわからないけど)
- 投稿日:2020-10-12T22:27:12+09:00
【Rails6】主なGemについて
はじめに
Railsを使うにあたり、当たり前のように
puma
とかwebpacker
とかlisten
を使用していますが、正直あまり意味がわからずに使っていました。ここいらで主なGemについてまとめたいと思います。Railsデフォルトの主なGem
下記がRails6で生成されるデフォルトGemです。
Gemfile# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 6.0.3' # Use sqlite3 as the database for Active Record gem 'sqlite3', '~> 1.4' # Use Puma as the app server gem 'puma', '~> 4.1' # Use SCSS for stylesheets gem 'sass-rails', '>= 6' # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker gem 'webpacker', '~> 4.0' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 2.7' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 4.0' # Use Active Model has_secure_password # gem 'bcrypt', '~> 3.1.7' # Use Active Storage variant # gem 'image_processing', '~> 1.2' # Reduces boot times through caching; required in config/boot.rb gem 'bootsnap', '>= 1.4.2', require: false group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] end group :development do # Access an interactive console on exception pages or by calling 'console' anywhere in the code. gem 'web-console', '>= 3.3.0' gem 'listen', '~> 3.2' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' end group :test do # Adds support for Capybara system testing and selenium driver gem 'capybara', '>= 2.15' gem 'selenium-webdriver' # Easy installation and use of web drivers to run system tests with browsers gem 'webdrivers' end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]それぞれ説明していきます。
sqlite3
SQLデータベースエンジンを実装するC言語ライブラリ。
パスワード設定がない等のセキュリティ機能がないため、基本的に開発環境、テスト環境で使用し、本番環境では別のデーターベースエンジンを使用する。https://www.sqlite.org/index.html
puma
RubyWebアプリケーション用のHTTP1.1サーバー構築に使用する。スレッドプールを使用してリクエストを処理する。
https://puma.io/
https://github.com/puma/pumasass-rails
RailsでSass(SCSS)使用できる。
https://github.com/rails/sass-rails
webpacker
Webアプリケーションで一般的に良く使われるメジャーな設定を、標準で実装してくれるwebpackのラッパー。webpackは、最新のJavaScriptアプリケーション用の静的モジュールバンドラー1。
【主な機能】
・webpack 4.x.x
・複数のエントリポイント2を使用した自動コード分割
・新しいJavaScript構文(ES6)をブラウザで動くように変換
・React、Vue.js、PostCSSなどのモダンなフレームワークに対する豊富な実績https://github.com/rails/webpacker
Jbuilder
Jbuilderは、JSON構造を宣言するためのシンプルなDSL(ドメイン特化言語)を提供。
https://github.com/rails/jbuilderturbolinks
Webアプリケーションでのリンクの追跡が高速になる。
https://github.com/turbolinks/turbolinks-classicbootsnap
railsの起動時の処理を最適化する(パスとrubyのコンパイル結果をキャッシュ)ことで起動時間を短縮してくれる。
ActiveSupport や YAML もサポートしている。https://github.com/Shopify/bootsnap/blob/master/README.jp.md
byebug
デバッグツール。
https://github.com/deivid-rodriguez/byebug
web-console
View 内でコンソールを立ち上げて、変数や parameter などの状態を見る事の出来るデバック用のライブラリ。エラー箇所のデバッグがしやすくなる。
https://github.com/rails/web-console
listen
ファイルの変更を検知してそれをフックに何か処理ができる。
【主な機能】
・ファイルの変更、追加、削除を検出
・複数のディレクトリを監視https://github.com/guard/listen
spring
Railsアプリケーションのプリローダー3。アプリケーションをバックグラウンドで実行し続けることで開発をスピードアップするため、テスト、移行を実行するたびにアプリケーションを起動する必要がなくなる。
https://github.com/rails/spring
spring-watcher-listen
Springはファイルシステムをポーリング4するのではなく、Listenを使用してファイルシステムの変更を監視します。
https://github.com/jonleighton/spring-watcher-listen/
capybara
実際のユーザーがアプリをどのように操作するかをシミュレートすることにより、Webアプリケーションのテストを支援する。
https://github.com/teamcapybara/capybara
https://en.wikipedia.org/wiki/Capybara_(software)selenium-webdriver
capybaraではJavaScriptをサポートしていないため、selenium-webdriverでシュミレートする。
https://github.com/SeleniumHQ/selenium/tree/trunk/rb
webdrivers
webブラウザを外部のソフトウェアから操作したり情報を取得したりできるようにするためのものです。
https://github.com/titusfortner/webdrivers
tzinfo-data
Windows ではタイムゾーン情報用に使用する。UnixベースのOSではtzinfoからシステムのタイムゾーン情報に直接アクセスできるので使用する必要はない。
https://github.com/tzinfo/tzinfo-data
それ以外の主なGem
bcrypt
パスワードを暗号化できる。
https://github.com/codahale/bcrypt-ruby
devise
Webアプリケーションには必須の、ユーザー認証機能を作ることができる。会員登録用フォームを作成や、メールやFacebook等での認証も実装できる。
https://github.com/heartcombo/devise
kaminari
ページネーション機能を簡単に追加できる。
https://github.com/kaminari/kaminari
carrierwave
画像のアップロード機能。
https://github.com/carrierwaveuploader/carrierwave
active admin
CRUD系の管理画面を作成することができる。
https://github.com/activeadmin/activeadmin
ruboCop
コーディング規約どおりに書かれているかをチェックする静的コード解析ツール。
https://github.com/rubocop-hq/rubocop
pry-rails
Rubyのirbのようにrailsのコンソールでメソッドなどを使えることができるようになる。
https://github.com/rweng/pry-rails
faker
偽のデータを生成する。
https://github.com/faker-ruby/faker
capistrano
自動デプロイツール。
https://github.com/capistrano/capistrano
まとめ
Railsは歴史が長い分、Gemは数が多いですね。初学者だと選定が難しそうです。まずは開発前にどんな機能がどこまで必要なのかピックアップしてGemを選定する必要がありそうです。Gemを選定の参考になりそうなサイトを張っておきます。この記事も有用なGemがあればどんどん更新していこうと思います。
Gemの探しツール
Gemのランキングサイト
モジュールごとに分割され、別々になったJavaScriptファイルの依存関係を解決して、1つのファイルにまとめるツール。 ↩
プログラムを実行を開始する場所のこと。(エントリーポイント - wiki) ↩
主に通信などの競合を回避するために、ホスト側が各機器に対して定期的に問い合わせを行い、条件を満たした場合に送受信や各種処理を行うこと。(ポーリング - wiki) ↩
- 投稿日:2020-10-12T21:50:26+09:00
動画を挿入する方法
トップページなどに動画を挿入する方法
GIF
https://gyazo.com/3015a8b1f689153dcfe7fcb308d483bb
下記コード
index.html<div class="bg-video-wrap"> <p>Brilliant Blue</p> <video src="images/foreign.mp4" autoplay loop muted> </video> </div>css.bg-video-wrap { position: relative; } p { font-family: serif; color: #fff; font-size: 400%; position: absolute; left: 30%; top: 100px; z-index: 1; }以上です!
状況に応じてCSSは各自変更して使って下さい!
foreign.mp4の部分は各々、ダウンロードや作った動画の名前を決めると思うのでそれを当てはめて下さい!おそらく末尾はmp4でもmovでもどちらでも挿入できます!
現場からは以上です!
- 投稿日:2020-10-12T20:52:53+09:00
削除されずに宙ぶらりんになったファイルがないか確認する
Active Storageを使ってアップロードファイルの管理をしていると、管理するテーブル (
active_storage_blobs
,active_storage_attachments
) とストレージに実際に保存されているファイル (実体ファイル) との間に、何らかの理由で不整合が起きることがある。中でも
active_storage_attachments
だけが削除され、それに紐づくactive_storage_blobs
と実体ファイルが残ってしまっている場合には、ActiveStorage::Blob.unattached
というスコープが使える。❯ rails c Loading development environment (Rails 5.2.4.4) [1] pry(main)> ActiveStorage::Blob.unattached ActiveStorage::Blob Load (1.0ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" LEFT OUTER JOIN "active_storage_attachments" ON "active_storage_attachments"."blob_id" = "active_storage_blobs"."id" WHERE "active_storage_attachments"."blob_id" IS NULLこれを使えば以下のように宙ぶらりんになった
active_storage_blobs
のレコードと紐づく実体ファイルを削除することができる。[1] pry(main)> ActiveStorage::Blob.unattached.each(&:purge) ActiveStorage::Blob Load (1.0ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" LEFT OUTER JOIN "active_storage_attachments" ON "active_storage_attachments"."blob_id" = "active_storage_blobs"."id" WHERE "active_storage_attachments"."blob_id" IS NULL (0.3ms) BEGIN ActiveStorage::Attachment Exists (0.2ms) SELECT 1 AS one FROM "active_storage_attachments" WHERE "active_storage_attachments"."blob_id" = $1 LIMIT $2 [["blob_id", 1], ["LIMIT", 1]] ActiveStorage::Blob Destroy (0.5ms) DELETE FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = $1 [["id", 1]] (0.8ms) COMMIT S3 Storage (105.5ms) Deleted file from key: ... => nil
ActiveStorage::Blob
クラスにunattached
というスコープとして以下のように定義されている。(Rails v5.2時点)activestorage/app/models/active_storage/blob.rbclass ActiveStorage::Blob < ActiveRecord::Base ... has_many :attachments scope :unattached, -> { left_joins(:attachments).where(ActiveStorage::Attachment.table_name => { blob_id: nil }) } ... endメモ:現時点でのmasterブランチには missing メソッドを使うように変更するコミットが入っているよう。
activestorage/app/models/active_storage/blob.rb@@ -46,7 +46,7 @@ class ActiveStorage::Blob < ActiveRecord::Base has_many :attachments - scope :unattached, -> { left_joins(:attachments).where(ActiveStorage::Attachment.table_name => { blob_id: nil }) } + scope :unattached, -> { where.missing(:attachments) }参考
- 投稿日:2020-10-12T20:34:22+09:00
ターミナルって何?
ターミナル説明
ターミナルは、PCに命令をすることができるツールですね。
環境構築を実行するには コマンドラインというツールが必要となります。
Macにデフォルトでインストールされているコマンドラインがターミナルです。コマンドライン説明
コマンドライン(または コマンドラインインタフェース:CLI )とは、コンピュータに対してキーボードからコマンドという文字を打ち込んで操作を行うツールになります。
GUI(グラフィカルユーザインターフェース)
コマンドラインとは対照的に、グラフィックを用いて操作を行う仕組みを グラフィカルユーザインタフェース(GUI) と言います。
例えば、「マウスでファイルをダブルクリックして開く」という操作など、普段PCで行う操作のほとんどはGUIで行なっていることが多いです。
ターミナルを使う理由を学ぼう
先程、マウスなどを使った直感的に操作をすることができるGUIと、ターミナルのようにコマンドを使用して操作するCLIがあることを説明させて頂きました。
直感的に操作ができて普段から使い慣れたGUIではなく、なぜわざわざターミナルの操作に慣れ、それを使用しなければならないのでしょう?
その理由は、GUIとCLIでは CLIの方が行える操作の数が圧倒的に多いためです。
GUIのように全ての操作をグラフィカルに表現していては画面がメニューやボタンで溢りかえってしまって、分かりづらくなってしまうためです。
普段行わない操作についてはボタンが無かったり、そもそも簡単に操作できては危険なものであれば操作できないものである場合が多いです。CLIでは、PCに対しての操作のほとんどが行えると言って良いほどに、
様々な操作を行うことができます。「Rubyプログラムの実行」もCLIが行える操作の1つです。
そのため、 ターミナルの操作は必須スキルだと思います。ターミナルの見方説明
まずは、ターミナルを開いて表示画面を見てみましょう!!
コンピュータ名は自分のコンピュータの名前ですね。
ここでは「A-137」となっています。ユーザ名は自分の名前です。
ここでは「div-M.T」となっています。このあとに続く「$」または「%」は プロンプト といい、 コンピュータが命令を受け付けられる状態であることを示します 。つまり今は、命令待ちの状態です。まとめ
・ターミナルとは、PCに命令をすることができるツールのこと
・「〜」には、カレントディレクトリが入ります。
「%」は、プロンプトを言います。プログラミングは、膨大な量の情報があるので、
基本から徐々に焦らずに理解していきましょう!!
できるようになるまで時間は、かかります。
でも、毎日継続して行えばだんだんとできるようになるので
一緒に頑張りましょう!!以上。
- 投稿日:2020-10-12T19:25:55+09:00
マイグレーションファイルから Model を直接触るのはやめて欲しい
何が起こったのか
開発環境で新たにDBを作成。
お約束通り、
$ rails db:create $ rails db:migrate大量のマイグレーションファイルを一気に migrate しようとしたその時、事件は起こった。
PG undefined column hogehoge ...的な感じで、スッと通らない?
嫌な予感がする。なになに。。。。
マイグレーションファイルから直接 Model にアクセスしていたんです。
migartion_file... Hoge.delete_all ...みたいな感じでモデルに対して直接操作を行う処理が書かれていた?
そのマイグレーションファイルは過去のものであり、その当時はそのモデルがあったのだろうが、今現在のソースコードには存在しない。
当然、そんなモデルは無いよ
と怒られたりする。こんな感じで直接 Model に対して処理を行っているマイグレーションファイルが散見された。
結果 migrate を通すのにものすごく苦労し、過去のマイグレーションファイルにも手を入れなくてはいけなくなった。マイグレーションファイルってそういうものなのでしょうか?
いいえ、違うはずです。どうすれば良いのか
マイグレーションファイルは、後々どんな人が開発に入ってきてもしっかり
rails db:migrate
が通るように積み上げていきましょう。ファイル数が増えるのは仕方ありません。大事なのはしっかり通るかどうかです。
おそらく当時の開発者もモデルに対して処理を書いているのは分かっていたはずで、データメンテナンスがしたかったのだと思います。既存データのメンテナンスはマイグレーションファイルでやらないで、rake task を作成するとか他にもやり方があったはずです。
自戒も込めて、マイグレーションファイルに関して気をつけるべきことを書いておきます
- マイグレーションファイルを追加した時には、
rails db:migrate:redo
を習慣づけて redo が通ることを確認する- 古いマイグレーションファイルを後から書き換えない(見栄えは悪いが単純に積み上げていくのがベストプラクティス)
- データメンテナンスはマイグレーションファイルの中で行わない(rake task を作ったり rails console から手動やったり他の方法がある)
Model は単なる ruby のクラスに過ぎません。
それは今後名前が変わるかもしれませんし、データの持ち方も変わるかもしれません。マイグレーションファイルの中からモデルを直接触るのはやめましょう?
どなたかの役に立てば幸いです。
- 投稿日:2020-10-12T18:01:13+09:00
deviseのコントローラー初期状態まとめ
deviseのコントローラーの初期状態が気になったことがあり、一度サンプルを作る羽目になったのでメモとしてQIITAに残しとく。
confirmations_controller.rbclass Sample::ConfirmationsController < Devise::ConfirmationsController # GET /resource/confirmation/new # def new # super # end # POST /resource/confirmation # def create # super # end # GET /resource/confirmation?confirmation_token=abcdef # def show # super # end # protected # The path used after resending confirmation instructions. # def after_resending_confirmation_instructions_path_for(resource_name) # super(resource_name) # end # The path used after confirmation. # def after_confirmation_path_for(resource_name, resource) # super(resource_name, resource) # end endomniauth_callbacks_controller.rbclass Sample::OmniauthCallbacksController < Devise::OmniauthCallbacksController # You should configure your model like this: # devise :omniauthable, omniauth_providers: [:twitter] # You should also create an action method in this controller like this: # def twitter # end # More info at: # https://github.com/heartcombo/devise#omniauth # GET|POST /resource/auth/twitter # def passthru # super # end # GET|POST /users/auth/twitter/callback # def failure # super # end # protected # The path used when OmniAuth fails # def after_omniauth_failure_path_for(scope) # super(scope) # end endpasswords_controller.rbclass Sample::PasswordsController < Devise::PasswordsController # GET /resource/password/new # def new # super # end # POST /resource/password # def create # super # end # GET /resource/password/edit?reset_password_token=abcdef # def edit # super # end # PUT /resource/password # def update # super # end # protected # def after_resetting_password_path_for(resource) # super(resource) # end # The path used after sending reset password instructions # def after_sending_reset_password_instructions_path_for(resource_name) # super(resource_name) # end endregistrations_controller.rbclass Sample::RegistrationsController < Devise::RegistrationsController # before_action :configure_sign_up_params, only: [:create] # before_action :configure_account_update_params, only: [:update] # GET /resource/sign_up # def new # super # end # POST /resource # def create # super # end # GET /resource/edit # def edit # super # end # PUT /resource # def update # super # end # DELETE /resource # def destroy # super # end # GET /resource/cancel # Forces the session data which is usually expired after sign # in to be expired now. This is useful if the user wants to # cancel oauth signing in/up in the middle of the process, # removing all OAuth session data. # def cancel # super # end # protected # If you have extra params to permit, append them to the sanitizer. # def configure_sign_up_params # devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute]) # end # If you have extra params to permit, append them to the sanitizer. # def configure_account_update_params # devise_parameter_sanitizer.permit(:account_update, keys: [:attribute]) # end # The path used after sign up. # def after_sign_up_path_for(resource) # super(resource) # end # The path used after sign up for inactive accounts. # def after_inactive_sign_up_path_for(resource) # super(resource) # end endsessions_controller.rbclass Sample::SessionsController < Devise::SessionsController # before_action :configure_sign_in_params, only: [:create] # GET /resource/sign_in # def new # super # end # POST /resource/sign_in # def create # super # end # DELETE /resource/sign_out # def destroy # super # end # protected # If you have extra params to permit, append them to the sanitizer. # def configure_sign_in_params # devise_parameter_sanitizer.permit(:sign_in, keys: [:attribute]) # end endunlocks_controller.rbclass Sample::UnlocksController < Devise::UnlocksController # GET /resource/unlock/new # def new # super # end # POST /resource/unlock # def create # super # end # GET /resource/unlock?unlock_token=abcdef # def show # super # end # protected # The path used after sending unlock password instructions # def after_sending_unlock_instructions_path_for(resource) # super(resource) # end # The path used after unlocking the resource # def after_unlock_path_for(resource) # super(resource) # end end
- 投稿日:2020-10-12T17:57:40+09:00
Ruby on Rails 教わった事 その2
この記事の目的
プログラミングスクールで私が約3ヶ月で教わった事を転職活動に生かすためにまとめました。
私による私のためだけの記事です。この講義で印象に残った一言は、
RSpecは絶対に身に付けなければいけない必須の技術。Hamlで書く
Hamlを使うと閉じタグがいらなくなり、コードを減らせる。
Hamlの書き方モデルメソッド
何回も使うロジックはモデルメソッドにする、DRYにする↓
example.html.haml- - if current_user.id == post.user_id #直書き + - post.created_user?(current_user) %p あなたは投稿した人ですpost.rbdef created_user?(user) self.user_id == user.id endモデルメソッドをRSpecでテスト
本来はテストを書き、失敗を確認しながらメソッドを書く(TDD、テスト駆動開発)
post_spec.rbdescribe "#created_user?" do let(:user) { FactoryBot.create(:user) } #本人 let(:other_user) { FactoryBot.create(:user) } #他人 let(:post) { FactoryBot.create(:post, user: user) } #本人の投稿 context "ログインユーザーと同じユーザーの場合" do it "trueを返すこと" do expect(post.created_user?(user)).to eq true end end context "ログインユーザーと同じユーザーではない場合" do it "falseを返すこと" do expect(post.created_user?(other_user)).to eq false end end end参考書
Everyday Rails - RSpecによるRailsテスト入門
とにかく手を動かして少しだけできるようになりました。
個人的にsystemスペックのajax関連のテストがトラウマです。
おすすめされた動画
TDD Boot Camp 2020 Online #1 基調講演/ライブコーディング感想
今回は主にRSpecのライブコーディングを見せてもらった。
当時、あまりテストの必要性を感じなかったが、今回過去の動画を見返しながら気になったコードをリファクタリングしようとしたところ無意識に、RSpecを動かしていたので少しずつ慣れてきているのだと思う。
- 投稿日:2020-10-12T17:52:33+09:00
gemfile書き換えによるBundler::Dsl::DSLErrorの対処法
gemfileを書き換えた際のエラー対処法について後発者のためにメモを残しておく。
開発環境
windows 10 home
ubuntu 20.04 LTS
ruby 2.7.1
Rails 6.0.3
postgresql 11エラー文
$ bundle ~~~~~中略~~~~~ Permission denied @ rb_sysopen - /home/admin0/taskleaf2/Gemfile (Errno::EACCES) ~~~~~中略~~~~~ was an error while trying to read from `/home/admin0/taskleaf2/Gemfile`. It is likely that you need to grant read permissions for that path. (Bundler::PermissionError) ~~~~~中略~~~~~ Bundler::Dsl::DSLError今回は特に理由はないが3つ目のエラー文着目に着目して検索したところ以下のサイトに良さげな解決方法が記載されていたので実行してみる
https://stackoverflow.com/questions/57926553/bundle-install-gives-bundlerdsldslerror$ chmod 644 Gemfileこれでエラーが発生しなくなったため、問題解決したと判断する。
- 投稿日:2020-10-12T17:08:30+09:00
【Rails】SessionsHelperを使ってコントローラー間でパラメータを受け継ぐ
はじめに
某プログラミングスクールでフリマアプリを作成中、購入内容の確認ページからクレジットカード登録ページに遷移。カード登録後、購入内容の確認ページに遷移することが出来なくなった。
原因:コントローラーがitems_controller.rbからcredit_cards_controller.rbに変わった時点でパラメータの:item_idが0になっていた。
詳細
- ユーザーログイン後、routingでトップページ(items#index)へ遷移。
- 他ユーザーの出品商品(items#create)の詳細ページ(items#show)へ遷移。
- 詳細ページ(items#show)の購入ボタンより商品購入ページ(items#purchase)へ遷移。
- クレジットカード情報の登録・変更するために、登録・変更ボタンより(credit_cards#index)へ遷移。
- 遷移したが変更がなければ、もどるボタンで商品購入ページ(items#purchase)へ遷移。
- 変更・未登録ならカード登録ページ(credit_cards#new,create)に遷移後,(credit_cards#show)に遷移。その後カード決定・もどるボタンより商品購入ページ(items#purchase)へ遷移。
resources :items, only: [:index, :new, :create, :show, :edit, :destroy] do get '/purchase/:id', to: 'items#purchase', as: :purchase end resources :credit_cards, only: [:index, :new, :create, :show, :destroy]5. 4-1,4-2にてitem_idがないというErrorが発生した
ターミナルで確認するとitem_idがcontrollerを跨ぐタイミングで消えている。
Processing by ItemsController#purchase as HTML Parameters: {"item_id"=>"2"} Item Load (0.3ms) SELECT `items`.* FROM `items` WHERE `items`.`id` = 2 LIMIT 1Processing by CreditCardsController#show as HTML
実装内容
item_idを引き継ぐ方法を検索していたところ...
sessionが使えそうだと判断。
はじめにapplication_controller.rbにinclude SessionHelperを追加。application_controller.rbclass ApplicationController < ActionController::Base include SessionsHelper #左記を追加 end/app/helpersに/sessions_helper.rbを作成し、下記コードでSessionsHelperを呼び出し
/app/helpers/sessions_helper.rbmodule SessionsHelper end参考記事
「初期化されていない定数ApplicationController :: SessionsHelper(NameError)」が表示されるのはなぜですか?これでsessionの準備が完了
まず、sessionにitem_idを保存する。
app/controllers/items_controller.rbdef purchase @item = Item.find(params[:item_id]) #paramsからitem_idを取り出し session[:item_id] = @item #取り出したitem_idをsessionに保存 end次に、credit_card登録先のcontroller(credit_cards#index,credit_cards#show)でsessionに保存していたパラメータを取り出す。
binding.pryで確認したところ配列になっていたので、valuesで取り出す。app/controllers/credit_cards_controller.rb#session[:item_id]で先ほどのsessionデータを取り出せる。 def index @item_id = session[:item_id].values.first end def show @item_id = session[:item_id].values.first endcontrollerで作成したインスタンス変数(@item_id)をviewで取り出し
app/views/credit_cards/index.html.haml= link_to "もどる", "/items/#{@item_id}/purchase", class:'return'app/views/credit_cards/show.html.haml%button.enter__permit__box.btn(onclick="location.href='/items/#{@item_id}/purchase'")選択した支払い方法を使う = link_to "もどる", "/items/#{@item_id}/purchase", class:'return'これで items#purchase ⇄ credit_cards#show,index において item_idのやりとりが出来るようになった。
最後に商品購入をした際に、sessionの削除をするapp/controllers/items_controller.rbdef pay session[:item_id] = nil end今回はsessionを使ってパラメータのやりとりを行なったがURLを使用してパラメータをやりとりできるみたいなので、今度試してみたい。
なお、sessionを使用する際は、それなりにリスクを伴うので、使用する際は下記のリンク先も合わせて読んでおきたい。
合わせて読みたい記事(セッションを取り扱う際の注意点)
- 投稿日:2020-10-12T16:37:28+09:00
Ruby on Rails 教わった事 その1
この記事の目的
プログラミングスクールで私が約3ヶ月で教わった事を転職活動に生かすためにまとめました。
私による私のためだけの記事です。この講義で印象に残った一言は、
Rails書けると出来るにはレベルに隔たりがある。
コードレビュー
メンターさんにとってすごい人だそうです!
Railsのコードレビューをするときに確認する観点をまとめてみた
コントローラーについて
スコープ
コントローラーの中で、モデルから直接メソッドを呼び出すことはセキュリティーホールに繋がりやすい。基本的に全体対象はイレギュラーであり、ほぼないものとする。↓
example_controller.rbdef new - @post = Post.new #間違ったIDが入る可能性がある + @post = current_user.posts.build #current_userの範囲(スコープ) endBefore_Action
コントローラー内での共通部分はprivateメソッドにして、before_actionでDRYに保つ↓
example_controller.rbbefore_action :set_post #省略 private def set_post @post = current_user.posts.find(params[:id]) endSave,Destroyメソッド
サーバートラブルなどネット環境の要因以外で、ほぼ失敗しないsave、destroyメソッドには!をつける↓
example_controller.rbdef create @post = current_user.posts.build(post_params) if @post.save! flash[:notice] = "投稿しました" redirect_to posts_path else render :new end end定数を使う
全体の人に分かりやすくするよう定数にする。モデルで定数を定義し、コントローラーで呼び出す。↓
example_controller.rb#ex_model.rb PER_COMMENT = 5 #example_controller.rb @comments = @post.comments.page(params[:page]).per(Ex_model::PER_COMMENT).order(created_at: :desc) #モデル名::定数名ルーティングについて
URLの意味を通す
resourcesをネストすると、URLの意味が分かりやすくなる。↓
routes.rb#Post(投稿)が親、Comment(コメント)とLike(いいね)が子。 resources :posts do resources :comments, only: [:create, :destroy] resources :likes, only: [:show,:create, :destroy] endしかも、URLから2つ、IDを持ってくる事ができる!↓
post_comments POST /posts/:post_id/comments(.:format) comments#create post_comment DELETE /posts/:post_id/comments/:id(.:format) comments#destroy post_likes POST /posts/:post_id/likes(.:format) likes#create post_like GET /posts/:post_id/likes/:id(.:format) likes#show DELETE /posts/:post_id/likes/:id(.:format) likes#destroy講義の感想
私よりも若い先生でしたが、とても立派な人です。
ZOOMで録画したものを、見返していますが当時よりはっきりと内容や意味を理解する事が出来ています。
その2へ続きます。
- 投稿日:2020-10-12T16:05:09+09:00
railsでformをdisableして送信すると値が送信されてない場合の解消法
- 投稿日:2020-10-12T15:39:44+09:00
[Rails] 最小限の労力でrubocopの恩恵を受ける
はじめに
「railsプロジェクトやるときには、rubocop入れましょう」と呪文のように刷り込まれてきましたが、実は、rubocopで何ができるのか、どんなメリットが有るのかきちんと理解していなかったのでまとめました。
この手の「いろいろできるツール」の使う際の大事な心がけとしては、提供される機能をくまなく把握して全部使いこなすことではなく、導入の目的を満たす8割ぐらいのことを、最小限の労力でできるようにすることが大事なんじゃないかとつくづく思います。
この記事を読んで、rubocopを導入することだけでなく、労力を取られずに(=本来書くべきロジックやテストに集中できるように)コードの品質を高めるという成果が得られてもらえれば、何よりです。
rubocopとは?
一言でいうと、ruby(.rbファイル)のコードを検査して、定められた規約に違反している箇所を検出してくれるツールです。
「コードが長すぎる」「インデンが適切でない」とかコードの可読性を高めるものだけでなく、「明確にすべきオプションがされていない」「DBとmodelで整合性があっていない」などバグにつながるような規約違反も検出してくれます。そして多くの場合、自動的に修正もしてくれます。
また、railsを使用している場合には、rubocop-railsを同時利用することで、rails特有のファイル(ex. マイグレーションファイル、設定ファイル)も検査してくれます。
メリット
rubocopを導入することで受けられるメリット(恩恵)は以下のものだと思います。
- バグにつながるような規約違反だったり、コードの読みやすさを阻害するような規約違反を自動検出してくれる
- チーム開発の場合は、チームで定めた同じ設定ファイルを使用することで、各自が書いたコードを同一ルールに基づいた一定の品質に保つことの助けになる
- 単純な規約違反(余計な余白がある、インデントが適切ではない)を自動的に修正してくれる
- 自動実行ツール(pre-commit 後述)と組み合わせることで、意識せずにcommitのタイミングで自動実行して、規約違反を検出してくれる。(そもそもの実行し忘れるということを防げる)
- コードレビューを機械的に行ってくれるので、規約違反の内容を理解し修正することで、自分のコードの品質を高めることができる
rubocopの使い方
railsを使用している場合の導入〜使い方を記載してきます。
試した環境は以下です。
- OS : macOS Catalina(10.15.7)
- ruby : 2.6.6
- rails : 6.0.3.3
また、私の場合まずは作るの優先でやったrailsアプリがあり、model,contorllerともに5,6個程度作成した状態で導入しました。
なお、私は導入に当たり以下のことを心がけました。なので、他の方が記載された導入の仕方や、設定内容とは異なる部分、相容れない部分があると思います。
- いきなり100%を目指さない
- ツールがやってくれることは、ツールに任せ、自分がやらなきゃいけないことに注力する
- 継続的に使えるようにする
インストール&設定
Gemfileに以下の記載を行い、bundle install
group :development do gem 'rubocop', require: false gem 'rubocop-rails' endとりあえずチェックする
$ rubocop Inspecting 57 files CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC Offenses: 57 files inspected, 292 offenses detected, 260 offenses auto-correctable292個って、、めちゃくちゃ出ましたね・・・ しかもスクロースしてもすべては表示しきれずorz
これを、一個一個確認して、修正。なんてことをやってくと。もうrubocopなんてしない!と投げ出してしまうので、継続的に使える有用なツールにしましょう。
というわけで、次の「設定ファイルの作成」と「自動修正」を行っています。
設定ファイルの作成
以下のコマンドを実行すると、設定ファイル(
.rubocop.yml
)を作成してくれ、かつ検出された規約違反を読み飛ばすための設定を(.rubocop_todo.yml
)に記載してくれます。$ rubocop --auto-gen-config適用する(しない)規約・範囲を設定ファイルに書いてあげます。
私は、とりあえず「チェック対象を自分で書いたコードに限定する」という考えで、以下の設定を入れてみました。
- コマンドで自動生成されたファイルや、初期ファイルはチェック対象外にする
AllCops: TargetRubyVersion: 2.6 NewCops: enable # ← 新しい規約が登録された場合に、適用するかどうかの判定 Exclude: - 'bin/**' - 'node_modules/**/*' - 'config/**/*' - 'config.ru' - 'db/schema.rb' - 'db/seeds.rb' - 'Gemfile'
- 自分のコード記載方法にそぐわない、エラー検出が必要ない規約を無効or変更
# 日本語でのコメントを許可 Style/AsciiComments: Enabled: false # クラスのコメント必須を無視 Style/Documentation: Enabled: false # 「frozen_string_literal: true」を追加しない Style/FrozenStringLiteralComment: Enabled: false # メソッドの行数が 10 行までは厳しすぎるので,20行までに変更 Metrics/MethodLength: Max: 20 # private/protected は一段深くインデントする Style/IndentationConsistency: EnforcedStyle: indented_internal_methodsこれらの設定ファイルを記載したうえで、規約違反を退避したファイル(
.rubocop_todo.yml
)の中身をコメントアウトして、再度rubocopを実行します。私の場合50個くらいまで減りました。ここまで来てもまだすべてを一つづつ直す気にはなれないので、次の自動修正を実行しします。
自動修正
冒頭にも記載したとおり、簡単な(かつ対処法が明確な)規約違反はrubocop -aコマンドで自動的に修正してくれます。
※ここは、一つ一つ規約違反の内容確認した上で、自動修正するべきという意見もありますが、私は「自動修正してくれるものは任せよう」と割り切って、規約違反はサーと見て自動修正しました。
実行すると、こんな感じで、自動修正された規約違反は
[Corrected]
が付与され、最後に、規約違反の総件数に対して、何件自動修正されたか表示されます。$ rubocop -a .rubocop.yml: Style/IndentationConsistency has the wrong namespace - should be Layout Inspecting 29 files ....................CC.CCCCCC Offenses: db/migrate/20200928124523_devise_create_users.rb:6:59: C: [Corrected] Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. t.string :nickname, null: false, default: "" ^^ ~ 途中略 〜 29 files inspected, 24 offenses detected, 22 offenses corrected手動修正
そして、自動修正しても残ってしまった規約違反が、自分で対応しなきゃいけない(=本来やりたかった、時間をかけて、内容理解し、あるべきコードに修正する作業)ものです。
私の場合は、以下の2つが残りました。こちらはバグに繋がる可能性のある規約違反だと思うので、エラーの内容を確認して(ex.
Rails/HasManyOrHasOneDependent
というキーワードでググれば、公式サイトの内容or丁寧解説記事にありつけます)、修正方法を検討して修正し、再度rubocopを実行して、無事に規約違反なしとなりました。# has_manyアソシエーションにたいして、dependentオプション(親レコード削除時に、同時に消す? 残す? エラーにする? 警告出す?)が未設定 app/models/category.rb:3:3: C: Rails/HasManyOrHasOneDependent: Specify a :dependent option. has_many :estimate_details ^^^^^^^^ # modelでuniqueバリデーションを定義しているのに、DB定義にはunique定義がされていない app/models/category.rb:6:3: C: Rails/UniqueValidationWithoutIndex: Uniqueness validation should be with a unique index. validates :user_id, uniqueness: { scope: :category_name }自動実行
便利なツールですが、そもそも実行することを忘れないために、何かを契機に自動的に実行するようにしましょう。一番良いタイミングがcommitのタイミングだと思うので、pre-commitというgemを導入して、git commitコマンド発行したタイミングで自動実行するようにします。
- pre-commitのインストール
gem pre-commit
をGemfileに設定して、bundle install
したあとに、以下のコマンドでpre-commitのファイルを生成します。$ pre-commit install Installed /Users/hiro/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/pre-commit-0.39.0/templates/hooks/automatic to .git/hooks/pre-commit
- pre-commitの設定
commit時にrubocopを自動実行するために、以下コマンドで設定を行います。
# 設定前の状態を確認 $ pre-commit list Available providers: default(0) git(10) git_old(11) yaml(20) env(30) Available checks : before_all ci coffeelint common console_log csslint debugger gemfile_path go go_build go_fmt jshint jslint json local merge_conflict migration nb_space pry rails rspec_focus rubocop ruby ruby_symbol_hashrockets scss_lint tabs whitespace yaml Default checks : common rails Enabled checks : common rails Evaluated checks : tabs nb_space whitespace merge_conflict debugger pry local jshint console_log migration Default warnings : Enabled warnings : Evaluated warnings : # git commitのタイミングで、rubocopを実行するように設定 $ git config pre-commit.checks rubocop # 設定後の状態を確認 $ pre-commit list Available providers: default(0) git(10) git_old(11) yaml(20) env(30) Available checks : before_all ci coffeelint common console_log csslint debugger gemfile_path go go_build go_fmt jshint jslint json local merge_conflict migration nb_space pry rails rspec_focus rubocop ruby ruby_symbol_hashrockets scss_lint tabs whitespace yaml Default checks : rubocop # ← rubocopが設定された Enabled checks : rubocop # ← rubocopが設定された Evaluated checks : rubocop # ← rubocopが設定された Default warnings : Enabled warnings : Evaluated warnings :また、bundle経由で、pre-commtiを使用する場合には.git配下の設定ファイル(
.git/hooks/pre-commit
)を以下のように修正する必要があります。#!/usr/bin/env sh 〜 中略 〜 PATH=$PATH:/usr/local/bin:/usr/local/sbin cmd=`git config pre-commit.ruby 2>/dev/null` if test -n "${cmd}" then true elif which rvm >/dev/null 2>/dev/null then cmd="rvm default do ruby" elif which rbenv >/dev/null 2>/dev/null then cmd="rbenv exec ruby" #← 修正前 then cmd="rbenv exec bundle exec ruby" #← 修正後 else cmd="ruby" fi 〜 中略 〜設定完了後に、git commitコマンドを実行して、rubocopが自動実行されるか確認します。
(規約違反が出るように事前に行末余白を仕込んでおきました)
$ git commit pre-commit: Stopping commit because of errors. Inspecting 1 file C Offenses: app/controllers/home_controller.rb:4:1: C: Layout/TrailingWhitespace: Trailing whitespace detected. 1 file inspected, 1 offense detected, 1 offense auto-correctable .rubocop.yml: Style/IndentationConsistency has the wrong namespace - should be Layout pre-commit: You can bypass this check using `git commit -n`commit時にrubocopが自動実行されることが確認できました。違反が検出されると、commit処理は中断されます。
検出後の流れとしては、「違反内容確認」→(修正すべき場合は)「マニュアル or 自動修正(
rubocop -a
)」→ 「ステージング環境へ登録」→「commit」の流れになるかと思います。おわりに
今後、commitのために自動的にrubocopが走り、チェックが行われる設定ができ継続的に使えるようになりました。
コードを書いて、新たな規約違反が出たときに、設定ファイルを見直したり、内容を確認して書き方を改めることができていければ、よりよいツールを育てていけると思いますし、自分のコード品質を高めることにもつながるのではないかと、考えております。参考にさせていただいた記事
使い方に関して、完全に無知でしたのでとても参考になりました。
記事の著者の方にはこの場を借りて、感謝のお礼をさせていただきます。
- 投稿日:2020-10-12T15:38:15+09:00
【Ruby on Rails】MySQL構築からデータベース変更まで
はじめに
様々な記事を参考にしながらなんとか導入できたので、
備忘録として残します。
もしおかしな点や、こうした方がいいなどありましたら
ご教授頂けますと幸いです。開発環境
ruby 2.5.7
Rails 5.2.4.3
Vagrant 2.2.4
VirtualBox 6.0.14
OS: macOS Catalina
centos 7流れ
1 vagrant上にMySQLを構築
2 既存アプリをSqliteからMySQLに変更
3 新規アプリをMySQLに設定
※基本的にはvagrant上で行うため、ssh接続しておいてください。vagrant上にMySQLを構築
CentOS確認
まずは現在のCentOSを確認します。
確認方法はvagrantファイルにあるVagrantfileを確認します。VagrantfileVagrant.configure("2") do |config| GUEST_RUBY_VERSION = '2.5.7' config.vm.box = "centos/7" ...今回はCentOSが7である前提で話を進めます。
CentOSとは仮想環境構築に使用する代表的なLinux系OSです。MySQLのインストール(CentOS7用)
Vagrant+Rails6+MySQL 開発環境構築
こちらの記事を参考にまずはvagrant上にMySQLを構築します。ターミナル$ vagrant ssh $ sudo yum -y install http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm $ sudo yum -y install mysql-community-server $ mysqld --versionバーションが表示されればOKです。
自動起動設定後、MySQL起動
vagrant起動時に自動で起動するように設定します。
2行目はmysqld.service enabledになっていればOKです。ターミナル$ sudo systemctl enable mysqld.service $ sudo systemctl list-unit-files -t service | grep mysqld $ sudo systemctl start mysqld.serviceMySQL初期設定(任意)
https://style.potepan.com/articles/19020.html
こちらの記事がわかりやすかったので、
$ mysql_secure_installation を実行後、
この記事のMySQLの初期設定を実施しよう!から設定してください。# rootユーザーにパスワードを設定(今回はrootパスワードを設定) $ /usr/bin/mysqladmin -u root password 'root' # セキュリティー関連の初期設定(ここでパスワードを聞かれると'root'とする) $ mysql_secure_installation設定後、下記を実行しパスワードを入力後、
mysql>
この表示になればOKです。ターミナル$ mysql -u root -p既存アプリをSqliteからMySQLに変更
Railsでmysql2をインストールするときにハマったところ
[初学者]既存アプリのDBをMySQLに変更する方法
上記記事を参考に導入していきます。railsアプリの作成、データベース確認
試しにscaffoldでpostテーブルを作成します。
ターミナル$ rails new sam $ cd sam $ rails g scaffold post name:stringcongig/database.ymlがこのような表記になっているかと思います。
初期設定ではsqlite3のデータベースをしようしています。congig/database.ymldefault: &default adapter: sqlite3 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000 development: <<: *default database: db/development.sqlite3 # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: <<: *default database: db/test.sqlite3 production: <<: *default database: db/production.sqlite3gemの導入
Gemfile# Use sqlite3 as the database for Active Record gem 'sqlite3' ↓ gem 'mysql2'ターミナル$ bundle installエラーが出る場合は下記を実行するか、
Gemfileのgem 'mysql2'のバージョンを
gem 'mysql2', '~> 0.4.4'
に変更してみてください。ターミナル$ sudo yum install -y mysql-develデータベース設定をMySQLに変更
congig/database.ymldefault: &default adapter: mysql2 encoding: utf8 pool: 5 username: root password: 初期設定をした場合はパスワードを記述 host: localhost development: <<: *default database: sam_development # samはアプリ名です。 # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: <<: *default database: sam_test # samはアプリ名です。 production: <<: *default database: sample_production username: sample_app password: <%= ENV['SAMPLE_DATABASE_PASSWORD'] %>下記でデータベースを作成。
ターミナル$ bundle exec rake db:create $ rails db:migrateターミナル$ mysql -u root -p $ show tables from sam_development; +---------------------------+ | Tables_in_sam_development | +---------------------------+ | ar_internal_metadata | | posts | | schema_migrations | +---------------------------+ 3 rows in set (0.00 sec)このようになっていたら設定完了です。
新規アプリをMySQLに設定
こちらは既存アプリの変更より簡単に出来ます。
ターミナル$ rails new sample -d mysql $ cd sample $ rails g scaffold post name:stringcongig/database.ymldefault: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: 初期設定をした場合はパスワードを記述 socket: /var/lib/mysql/mysql.sock development: <<: *default database: sample_development # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: <<: *default database: sample_test # As with config/secrets.yml, you never want to store sensitive information, # like your database password, in your source code. If your source code is # ever seen by anyone, they now have access to your database. # # Instead, provide the password as a unix environment variable when you boot # the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database # for a full rundown on how to provide these environment variables in a # production deployment. # # On Heroku and other platform providers, you may have a full connection URL # available as an environment variable. For example: # # DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase" # # You can use this database configuration with: # # production: # url: <%= ENV['DATABASE_URL'] %> # production: <<: *default database: sample_production username: sample password: <%= ENV['SAMPLE_DATABASE_PASSWORD'] %>Gemfile# Use mysql as the database for Active Record gem 'mysql2', '>= 0.4.4', '< 0.6.0'ターミナル$ bundle exec rake db:create $ rails db:migrateもしAccess deniedのエラーが出た場合は、
下記のように一度ログイン後、再度上記を実行してください。ターミナル$ mysql -u root -p exitまとめ
初期設定を行うことによってAccess deniedで弾かれるこtがありますが、
セキュリティー上仕方がないことかもしれません。
間違っている記述や方法がございましたらご教授頂けますと幸いです。またtwitterではQiitaにはアップしていない技術や考え方もアップしていますので、
よければフォローして頂けると嬉しいです。
詳しくはこちら https://twitter.com/japwork
- 投稿日:2020-10-12T15:09:03+09:00
AWSデプロイ後、画像が表記されない問題について
本番環境にアクセスしたらCSSがかかっていない。。。そんな時に解消した自分の解決法を備忘録に残します。画像の場所はapp/assets/imagesです
解決策1 CSSファイルの拡張子の後ろに.SCSSを付け足す
しかしこれでも解決しませんでした。人によってはこれだけいけたという人も聞きます。
解決策2 CSS.SCSSの表記を見直す
僕の場合、表記が
background-image: url(/assets/画像名);
だったのを
background-image: image-url("画像名");
に変更後$ git pull origin masterで反映させる。しかしこれでも適用されず
解決策3 コンパイルし直す
https://qiita.com/yoheism42/items/dcf71691ca3e8dfc26c5
ここの記事を参考に$ find app/assets/ -type f -exec touch {} \; $ rake assets:clobber assets:precompile $ RAILS_ENV=production rake assets:precompileを試す。そうすると2行目のコマンドで
======================================== Your Yarn packages are out of date! Please run `yarn install --check-files` to update. ========================================こんなエラー。これに対しては
$ yarn upgrade
その後またさっきの3行のコマンドを初めから試す。そうすると今回は弾かれずにすんなりいった。最後に
$ sudo systemctl start nginx $ sudo systemctl reload nginxの順に実行してエンジンエックス再起動
その後
$ ps aux | grep unicorn $ kill 1376 ←unicorn masterの行の一番左端の数字 $ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -Dこれでなんとか画像を表示させることに成功しました。
長かった・・・
- 投稿日:2020-10-12T13:19:05+09:00
[Rails] Herokuデプロイの流れ
備忘録
Herokuを使ったデプロイよく忘れてしまうので記録用
初学者のため間違っていたらご指摘お願いします。
尚本環境ではRails、MySQLを使っています。
プログラミング初心者の方に役立てばと思います!手順1 Heroku CLIをインストール
こちら最初のデプロイのみです。
2回目以降の方は手順2からご覧下さいターミナル
使用するディレクトリ内で以下のコマンドを入力 % brew tap heroku/brew && brew install herokuこのコマンドでherokuコマンドが使用できるようになり、ターミナルからHerokuにログインできるようになります。
手順2 Herokuにログインしましょう
ターミナルで以下を入力 % heroku login --interactive => Enter your Heroku credentials. # メールアドレスを入力し、エンターキーを押す => Email: # パスワードを入力して、エンターキーを押す => Password:これでHerokuにログインできました!
手順3 rails_12factorを導入
Railsアプリケーションを本番環境などのサーバ上で動かすためのアセットがまとまったGem
# Gemfileに追加 group :production do gem 'rails_12factor' endgemインストール % bundle install編集したのでコミット % git add . % git commit -m "gem rails_12factorの追加"デプロイはリモートリポジトリ上のデータを使うので変更の都度コミットしてプッシュを行うことを忘れないで下さい。
手順4 Herokuにアプリを作成
heroku createコマンドでheroku上にアプリを作成します。
heroku create 作成したいアプリ名ターミナルにて入力 例 % heroku create heroku-test01手順5 HerokuでMySQLを使えるようにする
ClearDBアドオンを追加する事でHeroku内でMySQLを使用できるようになります。
ターミナルで以下コマンドを実行 heroku addons:add cleardbターミナルで以下入力 # ClearDBデータベースのURLを変数heroku_cleardb % heroku_cleardb=`heroku config:get CLEARDB_DATABASE_URL` # データベースのURLを再設定 % heroku config:set DATABASE_URL=mysql2${heroku_cleardb:5}ここまででMySQLを使えるようになりました。
手順4に進む前にcredentials.yml.encファイルとmaster.keyファイルについて軽く説明します。credentials.yml.encファイルはrailsで外部に漏らしたくない情報を扱うファイルのこと。
master.keyファイルファイルはcredentials.yml.encの暗号文を複号するためのファイルのことです。
master.keyは重要なファイルのためデフォルトでGitで扱われないようになっています。手順5.5 credentials.yml.encをmaster.keyで複号
以下コマンドでcredentials.yml.encをmaster.keyによって復号し、中身を確認できた状態です
# ターミナルで以下コマンドを実行 % EDITOR="vi" bin/rails credentials:edit手順6 Heroku上にmaster.keyを設置
先ほども説明しましたが、master.keyはGitで扱えないため環境変数を設定する必要があります。
heroku config:set 環境変数名="値"
これにより、Heroku上で環境変数を設定でき、master.keyを使えるようになります。ターミナルで以下入力 heroku config:set RAILS_MASTER_KEY=`cat config/master.key`以下コマンドで環境変数の設定を確認 % heroku config手順7 アプリをプッシュ
git push heroku masterコマンドでheroku上のアプリにリモートリポジトリの内容をプッシュしています。
以下ターミナルで実行 % git push heroku masterここまででHeroku上にアプリケーションを反映する事ができました!
ですがマイグレーション情報が反映されていません、、、手順8 Herokuでマイグレーションを実行
heroku run rails db:migrateコマンドでHerokuのDB上にマイグレーション情報を反映させています。
ターミナルで以下コマンド実行 % heroku run rails db:migrate# 以下コマンドでHeroku上にデプロイしたアプリの情報確認できます % heroku apps:info追記
今後追加機能などを本番環境にデプロイする際には、コミット→プッシュ→手順7で簡単にデプロイする事ができます。
まとめ
お疲れ様です!
ここまでで一通りのデプロイ作業が終了しました!
実際の現場ではHerokuを使う事はほとんど無いと思いますが、私を含め初学者にとっては簡単にデプロイできるツールなのでデプロイの入門としてとても便利ですね!
誰かの助けになれば幸いです。
- 投稿日:2020-10-12T12:44:36+09:00
Ruby on Rails ログイン機能のバリデーション設定② メールの正規表現
前回の記事の続きになります。
name、emailカラムにバリデーションを設置した後、有効なメールアドレス(sample@sample.comなど)かどうかを判別するために正規表現を使おうと思いますが、Rubyのリファレンスを見ても膨大な情報に溺れてしまいそう。。。そこで今回はemailが有効かどうかを判別するのに必要な分だけを調べて使ってみることにしました。
結論からいいますと、今回使った正規表現はこちら。
/\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i正規表現についてはRubyのリファレンスよりもRailsチュートリアルの方が分かりやすく説明されていました。下記はRailsチュートリアルよりの抜粋ですが、これを見ながらだと理解できそうです。
正規表現 意味 /\A[\w+-.]+@[a-z\d-.]+.[a-z]+\z/i (完全な正規表現) / 正規表現の開始を示す \A 文字列の先頭 [\w+-.]+ 英数字、アンダースコア (_)、プラス (+)、ハイフン (-)、ドット (.) のいずれかを少なくとも1文字以上繰り返す @ アットマーク [a-z\d-.]+ 英小文字、数字、ハイフン、ドットのいずれかを少なくとも1文字以上繰り返す . ドット [a-z]+ 英小文字を少なくとも1文字以上繰り返す \z 文字列の末尾 / 正規表現の終わりを示す i 大文字小文字を無視するオプション さらにRubularを使えば正規表現を簡単にチェックできるようです。これは便利!
・・・で、この正規表現を前回の記事で作成したバリデーションに追加します。フォーマットを検証するためには。。。
validates :email, format: { with: /<regular expression>/ }このような形でformatオプションを使用するとのことなので、"regular expression"の箇所に正規表現を追加。
app/models/user.rbclass User < ApplicationRecord validates :name, presence: true, length: { maximum: 20 } validates :email, presence: true, length: { maximum: 300 }, format: { with: /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i } endRails consoleで確認してみると、sample@sample.comのような形でないので、エラーになっていました。
> user = User.create(name: "ruby", email: "ruby") (0.2ms) BEGIN (0.3ms) ROLLBACK => #<User id: nil, name: "ruby", email: "ruby", created_at: nil, updated_at: nil> > user.errors.messages => {:email=>["is invalid"]}
- 投稿日:2020-10-12T12:44:36+09:00
Rails:メールの正規表現を攻略する!
前回の記事の続きになります。
name、emailカラムにバリデーションを設置した後、有効なメールアドレス(sample@sample.comなど)かどうかを判別するために正規表現を使おうと思いますが、Rubyのリファレンスを見ても膨大な情報に溺れてしまいそう。。。そこで今回はemailが有効かどうかを判別するのに必要な分だけを調べて使ってみることにしました。
結論からいいますと、今回使った正規表現はこちら。
/\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i正規表現についてはRubyのリファレンスよりもRailsチュートリアルの方が分かりやすく説明されていました。下記はRailsチュートリアルよりの抜粋ですが、これを見ながらだと理解できそうです。
正規表現 意味 /\A[\w+-.]+@[a-z\d-.]+.[a-z]+\z/i (完全な正規表現) / 正規表現の開始を示す \A 文字列の先頭 [\w+-.]+ 英数字、アンダースコア (_)、プラス (+)、ハイフン (-)、ドット (.) のいずれかを少なくとも1文字以上繰り返す @ アットマーク [a-z\d-.]+ 英小文字、数字、ハイフン、ドットのいずれかを少なくとも1文字以上繰り返す . ドット [a-z]+ 英小文字を少なくとも1文字以上繰り返す \z 文字列の末尾 / 正規表現の終わりを示す i 大文字小文字を無視するオプション さらにRubularを使えば正規表現を簡単にチェックできるようです。これは便利!
・・・で、この正規表現を前回の記事で作成したバリデーションに追加します。フォーマットを検証するためには。。。
validates :email, format: { with: /<regular expression>/ }このような形でformatオプションを使用するとのことなので、"regular expression"の箇所に正規表現を追加。
app/models/user.rbclass User < ApplicationRecord validates :name, presence: true, length: { maximum: 20 } validates :email, presence: true, length: { maximum: 300 }, format: { with: /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i } endRails consoleで email: "ruby" と入力して登録しようとすると、sample@sample.comのような形でないので、エラーになっていました。正規表現は使いこなせればとても便利!
> user = User.create(name: "ruby", email: "ruby") (0.2ms) BEGIN (0.3ms) ROLLBACK => #<User id: nil, name: "ruby", email: "ruby", created_at: nil, updated_at: nil> > user.errors.messages => {:email=>["is invalid"]}
- 投稿日:2020-10-12T12:06:12+09:00
Bootstrap4 ハンバーガーメニューの色変更
CSSで設定する
1.ハンバーガーメニューの3本線の色を変更する
rgbaのところいじってやる
rgba(255,255,255,1)
.navbar-toggler .navbar-toggler-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255,255,255,1)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E"); }2.ハンバーガーメニューの背景色を変更する
.navbar-toggler{ background-color: #000000; }3.ハンバーガーメニューの枠線を変更する
.navbar-toggler{ border-color: #ffffff; }
- 投稿日:2020-10-12T10:56:19+09:00
querySelector()使用時の注意点(name属性を指定する時のひと工夫など)
この記事を書いた背景
JavaScriptの『querySelector()メソッド』を使って、任意のHTMLを取得する処理を記述していたのですが、最初、うまく取得することができませんでした。
うまく取得できなかった理由は、取得するHTMLを指定する際に記述したname属性の指定コードがうまく書けていなかったためです。
今回はname属性を指定するひと工夫も含め、querySelector()使用時の注意点を書いていきたいと思います。そもそもquerySelector()メソッドとは
JavaScriptのメソッドで、任意のHTMLを取得するメソッドです。
指定したセレクタに一致する最初のHTML要素(Element)を取得するメソッドです。
『document.querySelector( CSSセレクタ )』のように使います。
実際の使い方は下記の例をご覧ください。自分がどのようにつまづいたか
オリジナルアプリを作成中、ラジオボタンの実装を行ってましたが、
選択したボタンの値を取得する処理がうまく機能しない場合がありました。下記の例で見ていきたいと思います。
index.html<!--ラジオボタンの記述。iPhoneかAndroidかを選ぶラジオボタン--> <group class="inline-radio"> <div> <input type="radio" value="1" name="simulation[phone]" id="simulation_phone_1"> <label for="simulation_phone">iPhone</label> </div> <div> <input type="radio" value="2" name="simulation[phone]" id="simulation_phone_2"> <label for="simulation_phone">Android</label> </div> </group>index.js//ラジオボタンの要素(NodeList)を取得する const phone_list = document.getElementsByName('simulation[phone]'); //取得したラジオボタンの要素(NodeList)をラジオボタン1つずつ取り出し、変数eに格納する。 phone_list.forEach(function(e) { //クリック(ボタン押下)された要素eの場合イベント発火 e.addEventListener("click", function() { //クリックされたinputタグの値(value値)を取り出し、変数phone_planに格納する const phone_plan = document.querySelector("input:checked").value; //変数phone_planの出力 console.log(phone_plan); }); });※NodeListは、ざっくり言えばHTMLの情報全てが詰まったオブジェクトです。
簡単なHTMLとJSがあります。色々端折ってますがご了承ください。
見た目的には簡単なラジオボタン(●iPhone ●Android)があるだけです。
ラジオボタンでiphoneを選択すると、検証ツールのconsoleにて 1 が出力されます。console1
普通に値は取得できました。
しかし、HTMLにラジオボタンで実装された質問等がいくつも有り(スマホを選ぶラジオボタン・PCを選ぶラジオボタン...など)、それぞれのラジオボタンの押下された値を取得する処理を書くときに問題が起きます。
記述を見直さないといけないのは、JSの『querySelector()メソッド』です。querySelector()メソッドが取得する要素の位置は...
先程も書きましたが、『querySelector()メソッド』で取得するのは、指定したセレクタに一致する最初のHTML要素(Element)です。
そのため、現状の『querySelector("input:checked")』のような形でクリックされた要素を取得しようとすると、複数種類のラジオボタンがあるなかで、HTMLの一番上にあるラジオボタンの選択された値が取得されてしまい、HTMLの一番上にあるラジオボタン以外うまく値が取得できません。querySelector()メソッドにおけるname属性の指定
そこで色々調べたところ、name属性を指定すれば良さそうです。
下記のように修正してみました。javascript//修正前 const phone_plan = document.querySelector("input:checked").value; //修正後 const phone_plan = document.querySelector("input:checked[name=simulation[phone]]").value;このように修正すれば、『name属性がsimulation[phone]のラジオボタンでクリックされた要素』のように指定できるはず。
不正なセレクタということで、値が取得できないようです。(例とname属性違いますがご容赦ください。。。)
javascript//この書き方は正しい querySelector("input:checked[name=name属性名]]")という書き方は正しいのですが、クラスが指定されたname属性(今回で言ったら、simulationクラスのname属性「phone」)の場合は、上記の書き方では通用しないようです。(角括弧まみれになるからかな??)
ということで、今度はクラス名外してみました。
javascript//修正前 const phone_plan = document.querySelector("input:checked").value; //1回目修正後 const phone_plan = document.querySelector("input:checked[name=simulation[phone]]").value; //2回目修正後 const phone_plan = document.querySelector("input:checked[name=phone]").value;name属性がphoneのvalue値はなんにもないよ〜というエラーです。
正しいname属性は『simulation[phone]』ですからね。
やはり、クラス名を取るだけほど甘くない世界だ。そして、ついにLGTMな書き方発見。
ということで、このようにname属性を指定すればいいというのを見つけました。javascript//修正前 const phone_plan = document.querySelector("input:checked").value; //1回目修正後 const phone_plan = document.querySelector("input:checked[name=simulation[phone]]").value; //2回目修正後 const phone_plan = document.querySelector("input:checked[name=phone]").value; //3回目修正後(LGTM) const phone_plan = document.querySelector("input:checked[name*=phone]").value;name属性の指定のところで『*』を入れました。これは『部分一致検索』を意味します。
今回で言ったら、name属性に『phone』が含まれてるname属性という指定方法です。
ということで、無事、値が取得できました。console1
あとは、name属性の命名に気をつけながらname=*を使いこなしていけば、自分の思い通りのアプリが実装できると思います!
セレクタの様々な指定方法
ちなみにセレクタの指定方法は、name*=以外にもたくさん種類があります。
https://hakuhin.jp/js/selector.htmlこちらのサイトにセレクタの書き方が詳しく載っているので、ぜひ見てみてください。
色んな属性の指定方法があって、実装の幅が広がりますね。大変参考になりました。
- 投稿日:2020-10-12T10:00:54+09:00
【ざっくり解説】ActiveHashモデルからnameが取得できない原因と対処法
「ActiveHashのモデルからnameを取得したいんだけど、undefinedエラーが出て取得できない…」
そんな方向けに、ActiveHashのnameを多少強引に取得する方法と、そもそもnameが取得できない理由について解説していきます。
プログラミング初心者の方は参考にしていただけると幸いです。
(なぜエラーが出るかご存知の方にとっては、この記事は無益です。ごめんなさい。)この記事の目的
・ActiveHashを使った正常な値の取得方法を復習する
・ActiveHashモデルからfindメソッドで値を取得する方法を学習する
・なぜundefindエラーが発生するのかを理解する【前提】 ActiveHash 正常な値の取得
sushi.rbclass Sushi < ActiveHash::Base self.data = [ { id: 1, name: '大トロ' }, { id: 2, name: '中トロ' }, { id: 3, name: 'いくら' }, { id: 4, name: '穴子' }, { id: 5, name: 'えんがわ' }, { id: 6, name: '雲丹' }, { id: 7, name: 'いか' } ] endlunch.html.erb<%= @shari.sushi.name %> <!-- @shariのsushi_idが「4」 の場合、「穴子」が表示される-->このような記述で、ActiveHashのモデルから、@shari.sushi_idに紐づくnameの値を取得することができます。(今回モデルの記述は割愛します。)
しかし、ある条件下では、ActiveHashのname要素を取得することができず
undefined method '〇〇' for …
のように、エラーとなってしまう場合があります。
そんな時に、無理やりActiveHashのモデルから値を取得する方法をお伝えします。
その①:findを使って取得・表示する
lunch.html.erb<%= Sushi.find(@shari.neta_id).name %>「エラーは起きたけど、せっかくActiveHashモデル書いたし使いたいな…」
という方にオススメなのは、findメソッドを使って無理やり取得する方法です。
①findメソッドの引数に取得したいidを渡し、Sushiモデル(ActiveHash)から@shari.neta_idを探します。
②取得したidのnameが欲しいため、末尾に.nameをつけてあげます。
③Sushiモデルから、@shari.neta_idに合わせたname要素が取得できます。多少強引な方法ではありますが、この方法を使えば指定のname要素を取得することができます。ただし、コードが冗長になりやすいので、使うときは注意が必要です。
その②:form.select と Caseで取得・表示する
new.html.erb<%= form.select :neta_id,[["アジ",1],["コハダ",2],["赤むつ",3],["アマダイ",4]] %>lunch.html.erb<% case @shari.neta_id %> <% when 1 then %> <p>アジ</p> <% when 2 then %> <p>コハダ</p> <% when 3 then %> <p>赤むつ</p> <% when 4 then %> <p>アマダイ</p> <% end %>「記述量は少ないし、ActiveHashじゃなくてもいいかな…」
という方は、プルダウン部分をform.selectに、表示部分をcase文で記述することで、擬似的にActiveHashのような表現をすることができます。
ただし、この方法は選択肢が増えると記述量が膨大になり、コードの可読性を下げる可能性があるので、選択肢が少ない場合のみ使用することをオススメします。
そもそもなぜ取得できないの?
結論、「ActiveHashモデルのモデル名とカラム名が合っていない」場合、name要素を正規の方法で取得することができません。
カラム名がsushi_id(integer型)であった場合、ActiveHashのモデル名もSushi.rbである必要があります。前述その①の場合、Sushi.rbからneta.nameのような形で値を取得しようとしても、取得できません。
ActiveHashモデルを作成してプルダウンやチェックボックスを作る際は、モデルの名前とカラムの名前を揃えるようにしましょう。
まとめ
①ActiveHashはモデル名とカラム名があっていないと、.nameでname要素を取得することができない。
②別名のモデルから値を取得する場合は、findを使うことでname要素を取得することができる。
③記述そのもの(選択肢)が少ない場合は、form.selectとwhenを使うことで表現する方法もある。最後までご覧いただきありがとうございました。
引き続き、学習を頑張っていきましょう!
- 投稿日:2020-10-12T09:47:51+09:00
AWS Cloud9で初めてのLINEbot作成(Rails+Herokuデプロイ)
はじめに
Railsチュートリアルを終わったばかりのペーペーが、まず作ってみようと思ったのがLINEbot。文字をそのまま返す「くり返しBot」を今まで学習したモノを使って理解度を深めようというのが今回の目的。なので、あえてGASなど便利なものを使わずに「Rails+Cloud9+Heroku」で開発します。
目次
- LINE Developersアカウント&新規チャネル作成
- Herokuアカウントを作成
- cloud9上にRailsアプリ作成
- バージョン管理(Herokuデプロイ)
- Bot用にコード編集
- LINEで動作確認
LINE Developersアカウント&新規チャネル作成
まずはLINE Developersにログインします。(https://developers.line.biz/ja/)
初めての方は、普段使っているLINEアカウントで簡単に登録できます。プロバイダー情報を登録し、新規チャネルを作成します。
詳しくはこちらの記事を参照ください。(https://qiita.com/nkjm/items/38808bbc97d6927837cd)Herokuアカウントを作成
すでにHerokuのアカウントを作成済であれば、ここは飛ばして次の工程へ進んでください。
Herokuを開いたら、新規登録のボタンをクリックしてアカウントを作成します。
(https://jp.heroku.com/)
後からでもできますが、ここでCloud9上でHerokuを使えるように設定しましょう。以下のコードを一つずつ順番にターミネルに打ち込むだけです。terminalcurl -OL https://cli-assets.heroku.com/heroku-linux-x64.tar.gz tar zxf heroku-linux-x64.tar.gz && rm -f heroku-linux-x64.tar.gz sudo mv heroku /usr/local echo 'PATH=/usr/local/heroku/bin:$PATH' >> $HOME/.bash_profile source $HOME/.bash_profile > /dev/null無事ログインできればOKです。これで自身の開発環境でHerokuが使えるようになりました。
cloud9上にRailsでアプリ作成
Railsを学んだ方はおなじみの「Rails new」でサクッとアプリを作りましょう。
terminalrails new repeat-bot次にGemfileを少し編集します。
Gemfilegem 'line-bot-api' group :development do gem 'sqlite3'←ここが新しく追加された部分 # Access an interactive console on exception pages or by calling 'console' anywhere in the code. gem 'web-console', '>= 3.3.0' gem 'listen', '>= 3.0.5', '< 3.2' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' group :production do gem 'pg' end end新しく追加したGemをインストールしましょう。
terminalbundle install --without productionバージョン管理(Herokuデプロイ)
ここまで進んだところで一度Gitでバージョン管理しておきましょう。
terminalgit init続いて、herokuのappとこのRails上のappを結び付けましょう。
terminalheroku git:remote -a herokuのapp名先ほどHerokuのapp名を登録したのであれば、その名を。特に変更していない場合は自動で英数字の羅列がふられているのでそれを打ち込んでください。(Herokuのページより確認)
そして先ほど登録したHerokuにデプロイします。
terminalgit add . git commit -m "init"最後にpushして終了です。
terminalgit push heroku masterBot用にコード編集
くり返しBot用にコードを付け加えていきます。まずはRailsでおなじみコントローラーの作成です。
terminalrails g controller linebotつぎに、今回作成したLINEbotの管理画面から、チャンネルシークレットとアクセストークンをコピーしてターミネルに貼り付けます。
以下のように記入してください。terminalheroku config:set LINE_CHANNEL_SECRET=あなたのchannel secret heroku config:set LINE_CHANNEL_TOKEN=あなたのchannel tokenくり返し返答させるように、コードを編集します。
コピペして貼り付けてください。
:routes.rb
Rails.application.routes.draw do
post '/callback' => 'linebot#callback'
end
linebot_controller.rbclass LinebotController < ApplicationController require 'line/bot' protect_from_forgery :except => [:callback] def client @client ||= Line::Bot::Client.new { |config| config.channel_secret = ENV["LINE_CHANNEL_SECRET"] config.channel_token = ENV["LINE_CHANNEL_TOKEN"] } end def callback body = request.body.read signature = request.env['HTTP_X_LINE_SIGNATURE'] unless client.validate_signature(body, signature) error 400 do 'Bad Request' end end events = client.parse_events_from(body) events.each { |event| case event when Line::Bot::Event::Message case event.type when Line::Bot::Event::MessageType::Text message = { type: 'text', text: event.message['text'] } client.reply_message(event['replyToken'], message) end end } head :ok end end最後にもう一度デプロイしておきましょう。
terminalgit add . git commit -m "add linebot_controller" git push heroku masterそしてLINEbot管理画面から、Webhook URLを[https://herokuのapp名.herokuapp.com/callback]
で入力すれば完成です。LINEで動作確認
最後に実際にLINEで文字を入力して正しく返答されるのか見てみましょう。
- 投稿日:2020-10-12T09:30:20+09:00
AWS Cloud9 でRuby on Rails の開発環境を構築する
はじめに
ふとRuby on Railsの勉強をはじめようと思い、環境構築をすることにしました。
せっかくなので、AWS Cloud9で環境構築をしようと思います。やること
この記事では、以下のことを実施します。
- AWS Cloud9環境構築
- Ruby 環境構築
- rvmを使用したruby version 2.5.1のインストールと切り替え
- Rails 環境構築
- gemを使用したrails version 5.2.1のインストール
AWS Cloud9環境構築
Cloud9は、クラウド環境でIDE(統合開発環境)を利用できるサービスです。
ブラウザ上で動くため、OSやその他環境が異なるPCでも同じ手順で開発環境を準備することができます。
特徴 - AWS Cloud9 | AWSCloud9環境作成
AWS マネジメントコンソールからCloud9の画面に遷移します。
環境設定
作成するCloud9環境の設定をしていきます。
NameにCloud9環境の名前をつけます。
自由に決定できるようですが、今回はruby-cloud9-envにします。入力できたらNext stepをクリックします。
Cloud9環境に使用するEC2インスタンス(仮想マシン)の設定をします。
全てデフォルトで大丈夫です。Next stepをクリックします。
設定確認
構築する環境の設定を確認できます。
確認したらCreate enviroimentをクリックします。Cloud9のIDE画面に遷移します。
少し待つと操作できるようになります。これでCloud9環境の構築は完了です。
次はCloud9での開発に適した設定変更をします。
スペース可視化
スペース記号の可視化を行います。
テキストエディタの右下にある⚙歯車マークをクリックします。
設定が表示されるのでShow Invisiblesをクリックします。Ruby 環境構築
ここからはRubyの環境構築をしていきます。
Cloud9画面下部にターミナルが表示されています。
ここでコマンドを実行していきます。まずはOSにプリインストールされているライブラリを最新化します。
基本的にアップデートされるものは無いと思います。sudo yum update
rvmを使用してrubyのバージョンを切り替える
今回はRVM(Ruby Version Manager)を使用して複数VersionのRubyを管理したいと思います。
rvmインストール
Clooud9にはrvmがプリインストールされています。
念のためrvmがインストールされていることを確認します。rvm -v
ruby-2.5.1インストール
現段階でrvmで切り替えできるRubyのバージョンを確認します。
rvm listruby-2.6.3が使用できるようです。
今回はruby-2.5.1を使用したいのでrvmを使ってインストールします。rvm install 2.5.1
インストールが完了したらもう一度切り替えできるRubyのバージョンを確認します。
rvm listruby-2.5.1が追加され、currentとなっていることが確認できます。
念のため、Rubyコマンドでも確認します。
ruby -v
rvmデフォルトバージョン変更
これでRVMを使用したRubyのバージョン切り替えができました。
ただ、今の設定ではターミナルを再起動した時にはrubyバージョンが2.6.3に戻ってしまいます。そのため、RVMでのデフォルトバージョンを2.5.1に変更します。
rvm --default use 2.5.1
切り替えできるRubyのバージョンを確認します。
rvm listruby-2.5.1がcurrent && defaultとなっていることが確認できます。
以上でrubyの環境構築は完了です。
Rails 環境構築
ここからはRailsの環境構築をしていきます。
railsインストール確認
まずはrailsコマンドがインストールされているかを確認します。
rails -v
インストールされていないことが確認できます。
gemインストール
Railsはgemというコマンドを使用してインストールします。
gemとはRuby applicationやライブラリーのパッケージです。gemがインストールされているか確認します。
rubyがインストールされていれば使用できます。gem -v
インストールされていることが確認できます。
railsインストール
それでは、gemを使用してrailsをインストールします。
gem install rails -v 5.2.1 -N-Nオプションを使用すると、諸々のドキュメントのインストールをスキップできます。(インストールが早くなる)
インストールが完了したらrailsのバージョンを確認します。
rails -v
インストールされていることが確認できました。
Railsの環境構築は以上です。
最後に
Ruby on Railsの環境構築って割と面倒臭いイメージがありましたが、(特にWindows)Cloud9を使用すると簡単に環境構築ができますね。
これからRuby on Railsを使っていくつか簡単なシステムを構築してみようと思います。
- 投稿日:2020-10-12T04:15:05+09:00
rails db:create実行時のFATAL: role "admin0" does not existとPG::ConnectionBad: FATAL: role "admin0" does not existの対処方
rails db:create実行時にエラーが出た際の解決方法について後発者のために解決方法のまとめを書いておく。
実行環境
windows 10 home
ubuntu 20.04 LTS
ruby 2.7.1
Rails 6.0.3
postgresql 11
エラー文
$ rails db:create FATAL: role "admin0" does not exist Couldn't create 'taskleaf2_development' database. Please check your configuration. rails aborted! PG::ConnectionBad: FATAL: role "admin0" does not exist /home/admin0/taskleaf2/bin/rails:9:in `<top (required)>' /home/admin0/taskleaf2/bin/spring:15:in `<top (required)>' bin/rails:3:in `load' bin/rails:3:in `<main>' Tasks: TOP => db:create (See full trace by running task with --trace)今回要所となるのは上から5行目まであたりだろうか。
エラー解決順序
以前私は同じようなエラーに出会っていて既に解決したことがあったので同じ方法をとってみた。
https://teratail.com/questions/297341$ yarn installだがこれでも解決できなかった。
エラーがPG::ConnectionBad:である点に着目してみることにする。
だが以下のコマンドのようにDBは起動しているはずだし、、、?$ sudo service postgresql start [sudo] admin0 のパスワード: * Starting PostgreSQL 11 database server [ OK ] * Starting PostgreSQL 13 database server [ OK ]別(下)の手段で起動にチャレンジしてみることにした。
$ sudo su - postgres \q再度
rails db:create
を実行したところエラー文に変化が現れた。$ rails db:create WARNING: could not flush dirty data: Function not implemented Created database 'taskleaf2_development' WARNING: could not flush dirty data: Function not implemented Created database 'taskleaf2_test'あとはこのエラー文で検索したところ
https://stackoverflow.com/questions/45437824/postgresql-warning-could-not-flush-dirty-data-function-not-implemented
こちらが有力そうだったので
/etc/postgresql/11/main/postgresql.conf
の内容の一部を以下のように書き換えたfsync = off data_sync_retry = true再度
rails db:create
を実行してみるrails db:create Database 'taskleaf2_development' already exists Database 'taskleaf2_test' already existsどうやら成功したようだ。
サーバーも起動できたので今回はこれで問題解決したと判断する。
- 投稿日:2020-10-12T01:36:31+09:00
sanitizeメソッドをView以外で使いたい。
現在開発中のアプリのセキュリティ診断を行ったのですが、XSS(クロスサイトスクリプティング)とかいう脆弱性が見つかり、対応することになりました。
Web開発者としては当たり前すぎる知識らしいですが、今回対応するのが初めてだったのでなかなか手こずりました。つまずいたことがいくつかあったので、今回はその中の一つを書いていこうと思います。実現したいこと
https://qiita.com/kamohicokamo/items/571c58f2d6738a7dfe6a
この記事を参考に、XSS対策のためにデータのサニタイズを行いたい。例:
name.html.haml'山田太郎<script>alert("山田太郎です")</script>'埋め込んだJavaScriptが実行されてしまう。これはセキュリティ的にまずい。
= sanitize '山田太郎<script>alert("山田太郎です")</script>'この
sanitize
を使うと、このようにscriptタグが除去され、ただのテキストになる。
しかし
わざわざViewに
sanitize
と書いても良いが、htmlタグが混ざっている文字列が入力された段階で無効化しておきたい。しかし、この
sanitize
メソッドはヘルパーメソッドなので、View以外では使いにくい…方法
こんな感じのメソッドを作った。
modeldef remove_script_tag(str) ActionController::Base.helpers.sanitize(str) end※
sanitize
メソッドはデフォルトでは<script>
タグくらいしか除去してくれないので、remove_script_tag
としてある。このメソッドを
before_validation
なりbefore_save
でうまいこと使えば、悪意のあるスクリプトが文字列として送られてきても無効化することができるはず。環境
ruby 2.6.6
rails 6.0.3.2