- 投稿日:2020-09-26T23:40:33+09:00
二つのテーブルを繋ぐ存在、中間テーブル
中間テーブルとは
二つのアソシエーションしたいテーブル同士が「多対多」の関係のときに、テーブルの間を受け持つ、便利なやつ。
具体例
LINEを思い浮かべると、一人のユーザーはいくつものグループに所属している。また、一つのグループには、何人ものユーザーが招待されている。このとき、ユーザーとグループは「多対多」の関係と言える。
問題点
「多対多」のテーブルをそのままアソシエーションすることが困難である。
解決策
先の例で言えば、ユーザーとグループの間に組み合わせを記録するテーブルをかませる。それが、中間テーブル。ユーザーとグループの組み合わせを記録するというのがポイントで、カラムにはユーザーidとグループidが必要となる。
記述
アソシエーションをするため、「has_manyメソッド」「belongs_toメソッド」を使う。
そのモデル(テーブル)ファイルの目線になって、繋がりを持ちたいモデル(テーブル)にはが複数か単数か考える。
ex) user(モデル) has_many groups
ここは、もはや英語の話。group.rbhas_many :user_groups has_many :users, through: :user_groupsuser.rbhas_many :user_groups has_many :groups, through: :user_groupsuser_group.rbbelongs_to :user belongs_to :group注意
直接的に繋がっていないモデルには、「throughオプション」を使う。
ポイント
- 中間テーブルは必ず「belongs_toメソッド」で、後に続くモデル名は単数形。
- アソシエーションしたいテーブル同士は間接的に多対多の関係になる。
- 中間テーブルではないテーブルは必ず「has_manyメソッド」で、後に続くモデル名は複数形。
- 「throughオプション」を使って、経由しているモデル名を複数形で記述。
最後に
人生で初めてQiitaに投稿します。自分のアウトプットを目的としていますが、お気づきの点があれば、ご指摘ください。
- 投稿日:2020-09-26T23:03:36+09:00
Ruby on RailsにてRails new〜デプロイまでの忘備録2
Ruby on RailsにてRails new〜デプロイまでの忘備録2です!
、Rails newコマンドでアプリケーション作成からデプロイまでの一連をつらつらと書いていきます。
前回
https://qiita.com/gonshiba-n/items/abd1b11e35f99eb5975fRailsアプリケーションの日本語化と日本時間適応
config/application.rbrequire_relative 'boot' require 'rails/all' # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups) module xxxxxx class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. config.load_defaults 5.2 #ここから config.time_zone = 'Asia/Tokyo' #日本時間設定 config.i18n.default_locale = :ja #日本語設定 config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s] #起動時にja.ymlを読み込みさせる #ここまでを追加 #-省略- end endこれで日本語化の設定は出来たので、読み込むためのファイルを入手しましょう!
ターミナルは今、Railsの作業ディレクトリにいますか?
いるのであれば、下記コマンドを入力してGitHubから日本語化ファイルを入手しましょう。ターミナル.curl -s https://raw.githubusercontent.com/svenfuchs/rails-i18n/master/rails/locale/ja.yml -o config/locales/ja.yml次に日本時間です。
新しくconfigディレクトリの中にinitializersディレクトリ内にtime_formats.rbを作成しましょう。ターミナル.touch config/initializers/time_formats.rbこれで作成できます!
time_formats.rbを開いて下記のコードを書いてあげれば準備完了です。config/initializers/time_formats.rbTime::DATE_FORMATS[:datetime_jp] = '%Y年 %m月 %d日 %H時 %M分'実際には、下記のように使用することで
2020年9月25日12時00分みたいに表示されるようになります。<%= xxxxx.created_at.to_s(:datetime_jp) %> <%= xxxxx.updated_at.to_s(:datetime_jp) %>Rspec導入については過去にまとめてあるのでそちらをどうぞ!
https://qiita.com/gonshiba-n/items/36c91e000fdc9b18aa28
ただ、開発環境とテスト環境にRspecを書いた方がテストファイルを作成するジェネレータを使用できるため、下記のグループ内に入れ込む方が良いと思われます!ついでにRubocopも入れちゃいます。
Rubocopはリンターと呼ばれるもので、コードがルールから外れてる場合やタイポなどチェックできる優れものです!Gemfile.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] #ここに、Rspecをはじめとするテストgemを記す gem 'rspec-rails' gem 'capybara', '>= 2.15' gem 'selenium-webdriver' gem 'webdrivers' gem 'factory_bot_rails' gem 'rubocop-airbnb'#←リンター end他にも自分が使いたいgemを書いたら
ターミナル.bundle上記を実行!
Rubocopについては、こちらの記事を参考にしてください!
https://qiita.com/shunsuke_sasauchi/items/70ccc4b02be72640f699rootの設定
railsアプリにアクセスした時に一番最初に表示されるページを設定します。
今は雛形のみで何も中身がないので作成します。
rails g controllerでView,controllerと諸々を作っちゃいましょう。ターミナル.rails g controller StaticPages top about login僕の例ですみません!
これで一通り、railsが自動であれやこれやを作成してくれました。次はルーディングの設定をします。
congig/routes.rbを開きます!config/routes.rbRails.application.routes.draw do resources :static_pages#←こっちはrailsが作ってくれたコードを消してresource任せにしています root 'static_pages#top'#←これを追加 endこれでroot設定完了!
試しにサーバーを起動して
http://localhost:3000
にアクセスして見ると設定したページが表示されていると思います。config/environments/production.rbの設定
本番環境では画像の動的表示がoffになっているのでonに変更!
config/environments/production.rbconfig.assets.compile = true #デフォルトではfalse endこれでOK!
いよいよherokuにデプロイ!
herokuには登録しておいてください!
クレジットカードが必要だったと思いますが、検索するとめちゃくちゃ分かりやすい記事があると思うのでそちらを参考にしてください!
PostgreSQLを使用しているのでDB周りの設定はしていません。
他のDBを使用する場合は別途設定が必要になるのでお気をつけください。まずherokuをCLIで使えるようにしたらログインしましょう!
ターミナル.heroku loginherokuにアプリケーションを作成していきます。
アプリ名はそのままURLに組み込まれる為、URLで使用できない文字は使えません!
そして、すでに使われてしまっているアプリ名も使用できません!ターミナル.heroku create 好きなアプリ名(URLに使われるため _ とかは使えない)いよいよherokuのリモートリポジトリにpushしてデプロイしていきます。
ターミナル.git push heroku masterDBのマイグレーションファイルがある場合は下記のコマンドでマイグレートしてあげてください
ターミナル.heroku run rails db:migrateここまでくれば、後は実際にURLにアクセスして確かめてみましょう!
最後に
ここまで読んで頂きありがとうございました。
前回はアプリケーション完成間際にデプロイした為、凄く苦労しました。
アプリケーションの開発前の設定後にデプロイしてしまった方が絶対に楽だし、
開発環境と本番環境の両方で動作確認をしながら開発できる安心感は絶大だと思います。
ここまでざっくり、手順だけ書いてきましたが、出来ない!とかエラーが出た!とか間違ってる!とかいう場合は是非、ご教授くださると助かります。
- 投稿日:2020-09-26T22:38:36+09:00
【Rails】devise関連のルーティングまとめ
deviseも便利な機能が故、それぞれ独自のメソッドが自動で生成してくれるルーティングについて、こんがらがってしまいます。
そんな同じお悩みの方はぜひ。devise_for
routes.rbdevise_for :users$ rails routes Prefix Verb URI Pattern Controller#Action new_user_session GET /users/sign_in(.:format) devise/sessions#new user_session POST /users/sign_in(.:format) devise/sessions#create destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy user_password POST /users/password(.:format) devise/passwords#create new_user_password GET /users/password/new(.:format) devise/passwords#new edit_user_password GET /users/password/edit(.:format) devise/passwords#edit PATCH /users/password(.:format) devise/passwords#update PUT /users/password(.:format) devise/passwords#update cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel user_registration POST /users(.:format) devise/registrations#create new_user_registration GET /users/sign_up(.:format) devise/registrations#new edit_user_registration GET /users/edit(.:format) devise/registrations#edit PATCH /users(.:format) devise/registrations#update PUT /users(.:format) devise/registrations#update DELETE /users(.:format) devise/registrations#destroyresources :usersとの比較
アクション名 リクエスト resources devise_for new GET /users/new /users/sign_up(.:format) edit GET /users/:id/edit /users/edit(.:format) show GET /users/:id なし index GET /users なし create POST /users /users(.:format) update PATCH / PUT /users /users(.:format) destroy DELETE /users /users(.:format) devise_scope
routes.rbdevise_scope :user do get 'signin' => 'devise_token_auth/sessions#new' post 'signin' => 'devise_token_auth/sessions#create' post 'signup' => 'users#create' put 'update' => 'users#update' end$ rails routes Prefix Verb URI Pattern Controller#Action signin GET /signin(.:format) devise_token_auth/sessions#new POST /signin(.:format) devise_token_auth/sessions#create signup POST /signup(.:format) users#create update PUT /update(.:format) users#updatemount_devise_token_auth_for
routes.rbmount_devise_token_auth_for 'User', controllers: { registrations: 'users' }$ rails routes Prefix Verb URI Pattern Controller#Action signin GET /signin(.:format) devise_token_auth/sessions#new POST /signin(.:format) devise_token_auth/sessions#create signup POST /signup(.:format) users#create update PUT /update(.:format) users#update
- 投稿日:2020-09-26T22:34:07+09:00
(Ruby on Rails6) テーブルへのデータの作成
まえがき
テーブルでのデータ設定で、便利かなと思ったので、1つ・複数 のテーブルへのデータ設定を記録します。
いずれも、最後に save を行いますので。忘れずに!
データを取り出す時に、エラーになってしまいますよ!!テーブルへのデータの作成
1つのデータ設定
コマンドrails console 変数1 = モデル名.new(カラム名: "内容") test1 = Test.new(description: "smple_text") 変数1.save test1.save
複数のデータ設定
先のコマンドに , を入力します。
コマンドrails console 変数1 = モデル名.new(カラム名: "内容",カラム名: "内容") test1 = Test.new(description: "smple_text",title: "smple_title" ) 変数1.save test1.save
あとがき
ここまで読んでいただき、ありがとうございました。
以上が、テーブルへのデータの作成でした。
是非、お役立てください。Myリンク
また、Twitter・Portfolio のリンクがありますので、気になった方は
ぜひ繋がってください。プログラミング学習を共有できるフレンドが出来るととても嬉しいです。
- 投稿日:2020-09-26T22:18:43+09:00
(Ruby on Rails6) モデルとテーブルを作成する方法
まえがき
今回は、Ruby on Rails6 でデーターベースのテーブルを作成する方法を忘却録として残します。
モデルとテーブルを作成する方法
bin/ ・・・ は Linux の開発環境で使用します。
(私はMAC{Unix}での開発環境で不要な文字ですが、知識として持っておくといいと思います。)
また、テーブル名前は "Form" の様に 頭文字を大文字にすると良いです。モデルと1種類のカラムの作成
コマンド$ bin/rails g model Smple_form title:string $ bin/rails g model デーブル名 カラム名:データ型 or $ bin/rails generate model Smple_form title:string $ bin/rails generate model デーブル名 カラム名:データ型モデルと複数のカラムの作成
コマンド$ bin/rails g model Smple_form description:text title:string $ bin/rails g model デーブル名 カラム名:データ型 カラム名:データ型 or $ bin/rails g generate Smple_form description:text title:string $ bin/rails g generate デーブル名 カラム名:データ型 カラム名:データ型テーブルの作成 マイグレーション
コマンド$ rails db:migrateたまにマイグレーションを忘れて、エラーを出してしまいます。
ご注意ください。マイグレーションファイルの作成
↓は、複数カラムを作成したものになります。
20200926124610_create_任意s.rbclass CreateGoals < ActiveRecord::Migration[6.0] def change create_table :goals do |t| t.text :description t.string :title t.timestamps end end endあとがき
ここまで読んでいただき、ありがとうございました。
以上が、モデルとデーターベースの作成でした。複数のカラム設定を記録できてよかったです。
是非、お役立てください。Myリンク
また、Twitter・Portfolio のリンクがありますので、気になった方は
ぜひ繋がってください。プログラミング学習を共有できるフレンドが出来るととても嬉しいです。
- 投稿日:2020-09-26T20:47:43+09:00
docker-composeを用いたRailsのAPIサーバー環境構築
筆者について
ProgateのRuby, Railsコースを一通りやった。
その後Dockerで環境作ってRailsでAPIサーバー作った。本記事について
Progateではviewを含んだrailsの書き方を学んだが、APIサーバーとしてのみRailsを使いたかった。
また、dockerで開発したかったため公式のクイックスタートを参考にRailsの開発環境を作った。
その過程で得られたノウハウをまとめる。APIサーバーの開発で使うGemについては別記事で書く。
前提
Docker, docker-composeの使い方がわかること
環境
Ruby 2.7
MySQL 5.7
VSCode
Mac 10.14.5
Sequel Pro データベース見る用Rails new するまで
まずはプロジェクトフォルダを作成。ここではrails-sampleとした。
そして、この直下に Dockerfileを作成FROM ruby:2.7 RUN apt-get update -qq && apt-get install -y RUN mkdir /myapp WORKDIR /myapp COPY Gemfile /myapp/Gemfile COPY Gemfile.lock /myapp/Gemfile.lock RUN bundle install # Add a script to be executed every time the container starts. COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"]次にrailsをインストールするためのGemfileを用意
source 'https://rubygems.org' gem 'rails', '~>5'空のGemfile.lockを作る
touch Gemfile.lockDockerfileに記載されている
entrypoint.sh
を作るentrypoint.sh#!/bin/bash set -e # Remove a potentially pre-existing server.pid for Rails. rm -f /myapp/tmp/pids/server.pid # Then exec the container's main process (what's set as CMD in the Dockerfile). exec "$@"なぜこれらのファイルを作るのかはDocker 公式クイックスタートの方を見ていただければ。
docker-compose.yml
を作るdocker-compose.ymlversion: '3' services: server: build: . tty: true volumes: - .:/myapp working_dir: /myapp ports: - "3000:3000" depends_on: - mysql command: bash # command: > # bash -c "rm -f tmp/pids/server.pid && # bundle exec rails s -p 3000 -b '0.0.0.0'" mysql: image: mysql:5.7 ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: mysql volumes: - "./mysql/db-data/:/var/lib/mysql" # データ永続化 - "./mysql/my.cnf:/etc/mysql/conf.d/my.cnf" # 日本語をデータとして使うために必要MySQLのデータの永続化と日本語対応のために
rails-sample > mysql > db-data フォルダを作成。
mysqlフォルダ以下にmy.cnf
を作成my.cnf[mysqld] character-set-server=utf8それができたら
rails new
する。docker-compose run server rails new . -MC --force --api --database=mysql --skip-active-storagerailsコマンドやコマンドのヘルプでオプションを調べ、不要そうなものを省いている。
重要なオプションは以下--force // rails new 時にファイルを上書き --api // api開発に不要なviewとかを生成しない --database=myql // デフォルトではsqliteだがmysqlを指定するこれでいろいろ作られる。
で、ここで
Gemfile
とGemfile.lock
が上書きされて新しくなっている。
これをイメージのほうに反映させるために、docker-compose buildする必要がある。
事前に必要なgemがわかっている場合にはここでGemfileに書いておく。
これでrails new完了
mysqlに繋がるように設定ファイルを書く。
config > database.yml
database.ymldefault: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: mysql development: <<: *default host: mysql database: myapp_development ... test: <<: *default host: mysql database: myapp_testproductionは不要なのでまるっとコメントアウトした
host名はdocker-compose.yml
のサービス名
passwordもdocker-compose.yml
で指定したものできたら
docker-compose up -d
でコンテナを起動し、VSCodeのAttach Shellで中に入るrails db:createでDBを作る
root@dc075120af8a:/myapp# rails db:create ... Created database 'myapp_development' Created database 'myapp_test'これでデータベースが作れた。
Sequel Proで接続すればデータベースができていることが確認できるあとはProgateで学んだ通りモデル作ってマイグレーションすればテーブルができる。
参考
Docker 公式クイックスタート 英語
日本語の方は内容が古いので注意。
- 投稿日:2020-09-26T20:39:25+09:00
Rakeタスクを定義してみよう。
Rakeタスクってなに
タスクってなに、、、「やること」っていう意味かな。はじめて聞いた時はそう考えましたが、調べてみるとRuby on Railsにはタスクというものが存在するらしい。
Rakeタスクとは
このタスクという機能は、いちいちアプリケーションを立ち上げるなくてもターミナルから任意の処理を実行することができるものらしい。自分が携わっているアプリケーションでは、開発段階でサンプルのデータが必要だったので、それをこのタスクというものを使って作成した。
タスクを作成してみる
rails g task sampleこれで
sample.rake
というタスクに関するファイルを作成する。
lib/tasks
にsample.taskという名前のファイルを作成。namespace :greet do end作成したファイルには、デフォルトで上のようなコードが書かれている。
この中を自分がタスクとして行いたい処理をコマンド一つで実行されるように書いていく。# タスク名前を書く。 namespace :sample do # タスクの説明を書く。 desc => description(説明) desc "" # db => タスクの名前を書く。 task db: :environment do # 実行したい処理を記述する場所 end end上から、、、、
●名前を書く → namespace
●タスクの説明 →desc
●タスクの名前 → task db: 上の例だと db がそう。namespace :sample do desc "ゴリラと表示するタスク" task gorira: :environment do puts "ゴリラ" end end作成したタスクがきちんと動作するか確認をしてみる。
rails sample:gorira↓
ゴリラ
これでrake タスクの完成。
- 投稿日:2020-09-26T19:05:37+09:00
配列内の任意の文字を探す判定するメソッドの作り方
【概要】
1.結論
2.includeメソッドとは何か
3.どのようにプログラムしたか
1.結論
include?メソッドを使う!
2.include?メソッドとは何か
include?は配列の中に指定した要素が、あるかを判定するメソッドです!
3.どのようにプログラムしたか
def array_hello(strs) if strs.include?(hello) puts "True" else puts "False" end end"strs"の引数から"hello"という文字を探したいので、
strs.include?(hello)という書き方にしています!
引数.include?(探したい配列内の文字)で適用できます!
- 投稿日:2020-09-26T19:03:43+09:00
(ECサイト)注文情報入力時におけるバリデーション
前提条件
ECサイトでECサイトで注文情報入力 ==> 注文確認画面の間に注文情報入力でバリデーションをかけたい
1.よく使うバリデーション
app/models/book.rbvalidates :title, presence: trueなどの普段よく使うバリデーションは
booksテーブルにtitleというカラムがあり
データベースに保存される時、つまり @book.save(book_params)の時にtitleカラムが空白だとバリデーションがかかる。
しかし、ECサイトで注文情報入力 ==> 注文確認画面
==> 注文確定(ここで.save
が行われる)というフローで実装する際、注文情報入力 ==> 注文確認画面の間に.save
が発生しない為、モデルにかけるバリデーションをrenderで呼び出すことができない為if文で条件分岐を書いてflash[:notice]
を使う必要がある。2.if文の実装
app/controllers/order_controllers.rbwhen 3 if params[:order][:new_add][:postal_code] == "" && params[:order][:new_add][:address] == "" && params[:order][:new_add][:name] == "" flash[:notice] = "新しいお届け先が全て入力されていません" redirect_to new_order_path elsif params[:order][:new_add][:postal_code] == "" flash[:notice] = "郵便番号が入力されていません" redirect_to new_order_path elsif params[:order][:new_add][:address] == "" flash[:notice] = "住所が入力されていません" redirect_to new_order_path elsif params[:order][:new_add][:name] == "" flash[:notice] = "宛名が入力されていません" redirect_to new_order_path else @order.postal_code = params[:order][:new_add][:postal_code] @order.address = params[:order][:new_add][:address] @order.name = params[:order][:new_add][:name] end end3.コードの説明
まず、case文を使い、ラジオボタンを3個order/new.html.erbに書きwhenで3パターン分岐させている。
そして、3個目のラジオボタンを選ぶと注文情報入力時に新しいお届け先を入力できるように実装している。
[:new_add] は注文情報入力時に新しいお届け先を入力する際のパラメータ。app/controllers/order_controllers.rbparams[:フォームで送られてくる値] == "" flash[:notice] = ”ホニャホニャ"と書くことで空欄の時にフラッシュメッセージを出せる。
4.今回の実装を終えて
当初 == nil にしており値が返ってきていなかったがターミナルを見ると""になっていたので条件文を変えるとうまくいった。
&&で条件文を繋ぐ時に最後に一個だけイコールを入れるのではなく毎回イコールが必要である。5.参考サイト
https://qiita.com/GreenFingers_tk/items/ed5219e1e0cdd5e5d1b1#new
- 投稿日:2020-09-26T18:52:42+09:00
Railsにフォントを導入するまで
はじめに
ネット上には素晴らしいフリーフォントがたくさんあります。
デザインの表現の幅を広げるために是非、活用していきたいところ。
そこで、フリーフォントをRailsに導入していきます。フォントファイルの導入
ここでは導入したいフォントファイルを
smog.otf
とします。
public
フォルダにfonts
フォルダを作り、そこにフォントファイルを配置。- public - fonts - smog.otf使用するcssファイル(ここでは
sample.css
)に以下のコードを追加します。
font-family
の名前は自由に設定できます、今回は'Smog'
としましょう。
またformat
はファイルのフォーマットに合わせます。
フォーマット 拡張子 format('woff') .woff format('truetype') .ttf format('opentype') .otf または .ttf format('embedded-opentype') .eot format('svg') .svg または .svgz sample.css@font-face { font-family: "Smog"; src: asset-url('/fonts/smog.otf') format('opentype'); font-weight: normal; font-style: normal; }あとはいつも通りcssでフォントを指定すれば使えます。
以下は例です。sample.css.foo h1 { font-family: 'Smog'; }index.html.erb<div class="foo"> <h1>hello!</h1> </div>以上です、お疲れ様でした!
- 投稿日:2020-09-26T17:12:22+09:00
【Rails】【bootstrap】レスポンシブに文字の大きさを変更したい
前提
gem bootstrapを使用
やりたいこと
Railsを使ってレスポンシブな画面を作る。
その際に文字の大きさをいい感じに大きくしたり小さくしたりしたい。結論
app/assets/stylesheets/application.scssbody, html { font-size: 30px; } @media screen and (min-width: 576px) and (max-width: 768px) { body, html { font-size: 30px; } } @media screen and (min-width: 769px) and (max-width: 992px) { body, html { font-size: 30px; } } @media screen and (min-width: 993px) and (max-width: 1200px) { body, html { font-size: 16px; } } @media screen and (min-width: 1201px) { body, html { font-size: 20px; } }上記のサイズを変更すればOK
色々見ているとpxで設定しない方がよいというのもあるので、他の方法も検討中
今回はRailsというよりはscssの書き方になる
- 投稿日:2020-09-26T16:40:51+09:00
sidekiqのリトライ上限を設定して死んだキューをslackで通知する方法
はじめに
非同期でjobを処理してくれるsidekiqを導入する中で、利便性を生かしつつも自分のアプリ専用にカスタマイズしたい、そんな時に役に立った設定をまとめています。
sidekiqとは
sidekiqとは、非同期処理を可能にしてくれるライブラリです。複数のジョブを同時に実行させる時などに、各ジョブのqueueの名称を分けることで、処理の優先順位を指定することができます。似たようなライブラリにresqueやdelayed_jobなどがあるかと思います。
簡単に導入できるのですが、つまづいてしまったキューをデフォルトで25回だか26回だかリトライするとか、その後はDEADとなって実行していたキューのログが見られないなどといった面倒な点もあります。
そこでこの記事では、例外を投げた時などにいつまでもリトライせず上限を設定してDEADとし、その際にslackにキューの内容とエラーメッセージを投げるという設定をする方法についてお話しします。環境
Ruby 2.6.6
Rails 6.0.2
sidekiqにはredisが必要になります。# On OSX brew update brew install redis brew services start redis失敗したキューをダッシュボードで確認する
gemにsidekiq-failuresを追加することでダッシュボードで確認することができ、失敗したキュー全てをリトライさせることもできます。
gem 'sidekiq-failures'他にも投げられたキューを知る&分析するなどでたくさんgemがあるようですので参考までに載せておきます
リトライの上限を設定する
sidekiqは確かデフォルトで25,6回程度リトライをしてからキューを殺すといった仕様になっていたかと思います。
そこで、たくさんのジョブを一気に処理させる時など、そこまでリトライしなくていいからダメになった何度かチャレンジしてダメになったら教えて・・・という人のために、リトライの上限をjobファイルに記載します。app/jobs/your_job.rbclass YourJob < ActiveJob::Base ... queue_as :default sidekiq_options retry: 5 ... endこれで5回トライしてダメだったキューはDEADキューとなります。
キューの死亡をslackで通知
Railsアプリにおいてslack通知をとても簡単にしてくれるgemがslack-incoming-webhooksです。
gem 'slack-incoming-webhooks'通知させるチャネルのURL取得はこのページを確認してください。
initializerでキューが死亡した場合の処理を設定(チャネルのURLは.envに保存します)
app/config/initializers/sidekiq.rbSidekiq.configure_server do |config| config.death_handlers << ->(job, ex) do slack = Slack::Incoming::Webhooks.new(ENV['SLACK_WEBHOOK_URL']) attachments = [{ title: "Sidekiq failure", text: "ONE DEAD JOB IS FOUND:\n (#{job['args']}) \n msg(#{job['error_message']})", color: "#fb2489" }] slack.post "", attachments: attachments end endこれで自然とDEADになってしまったキューはslack通知されるようになります。
注意点
sidekiqのダッシュボード上でキューを殺しても通知は来ない
config.death_handlersに通知の設定をする場合、ダッシュボード上でマニュアルにキューを死亡させた場合には通知が来ません。なのでリトライ上限の5回を超えた場合にのみ通知が来るようになります。rescure_from Exceptionで通知設定するとリトライしてくれない
例外処理なので一度ジョブを処理してエラーとなると死亡と看做され、slack通知はしてくれますがリトライはしてくれません。なんらかの事情で処理されずそれでもリトライして欲しい場合には、上記の通りconfig.death_handlersでslack通知の設定をおすすめします。
- 投稿日:2020-09-26T16:40:51+09:00
sidekiqのリトライ上限を設定して死んだjobをslackで通知する方法
はじめに
非同期でjobを処理してくれるsidekiqを導入する中で、利便性を生かしつつも自分のアプリ専用にカスタマイズしたい、そんな時に役に立った設定をまとめています。
sidekiqとは
sidekiqとは、非同期処理を可能にしてくれるライブラリです。複数のジョブを同時に実行させる時などに、各ジョブのqueueの名称を分けることで、処理の優先順位を指定することができます。似たようなライブラリにresqueやdelayed_jobなどがあるかと思います。
簡単に導入できるのですが、つまづいてしまったキューをデフォルトで25回だか26回だかリトライするとか、その後はDEADとなって実行していたキューのログが見られないなどといった面倒な点もあります。
そこでこの記事では、例外を投げた時などにいつまでもリトライせず上限を設定してDEADとし、その際にslackにキューの内容とエラーメッセージを投げるという設定をする方法についてお話しします。環境
Ruby 2.6.6
Rails 6.0.2
sidekiqにはredisが必要になります。# On OSX brew update brew install redis brew services start redis失敗したキューをダッシュボードで確認する
gemにsidekiq-failuresを追加することでダッシュボードで確認することができ、失敗したキュー全てをリトライさせることもできます。
gem 'sidekiq-failures'他にも投げられたキューを知る&分析するなどでたくさんgemがあるようですので参考までに載せておきます
リトライの上限を設定する
sidekiqは確かデフォルトで25,6回程度リトライをしてからキューを殺すといった仕様になっていたかと思います。
そこで、たくさんのジョブを一気に処理させる時など、そこまでリトライしなくていいからダメになった何度かチャレンジしてダメになったら教えて・・・という人のために、リトライの上限をjobファイルに記載します。app/jobs/your_job.rbclass YourJob < ActiveJob::Base ... queue_as :default sidekiq_options retry: 5 ... endこれで5回トライしてダメだったキューはDEADキューとなります。
キューの死亡をslackで通知
Railsアプリにおいてslack通知をとても簡単にしてくれるgemがslack-incoming-webhooksです。
gem 'slack-incoming-webhooks'通知させるチャネルのURL取得はこのページを確認してください。
initializerでキューが死亡した場合の処理を設定(チャネルのURLは.envに保存します)
app/config/initializers/sidekiq.rbSidekiq.configure_server do |config| config.death_handlers << ->(job, ex) do slack = Slack::Incoming::Webhooks.new(ENV['SLACK_WEBHOOK_URL']) attachments = [{ title: "Sidekiq failure", text: "ONE DEAD JOB IS FOUND:\n (#{job['args']}) \n msg(#{job['error_message']})", color: "#fb2489" }] slack.post "", attachments: attachments end endこれで自然とDEADになってしまったキューはslack通知されるようになります。
注意点
sidekiqのダッシュボード上でキューを殺しても通知は来ない
config.death_handlersに通知の設定をする場合、ダッシュボード上でマニュアルにキューを死亡させた場合には通知が来ません。なのでリトライ上限の5回を超えた場合にのみ通知が来るようになります。rescure_from Exceptionで通知設定するとリトライしてくれない
例外処理なので一度ジョブを処理してエラーとなると死亡と看做され、slack通知はしてくれますがリトライはしてくれません。なんらかの事情で処理されずそれでもリトライして欲しい場合には、上記の通りconfig.death_handlersでslack通知の設定をおすすめします。
- 投稿日:2020-09-26T16:31:14+09:00
特殊変数$1, $2, $3 ... で巨大な整数を使おうとすると、警告が表示される
Rubyには、
$1, $2, $3 ...
という特殊変数があり、$n
には最後に成功したパターンマッチで n 番目の括弧にマッチした値が代入されます。"abc" =~ /(.)(.)(.)/ p $1 #=> "a" p $2 #=> "b" p $3 #=> "c"番号 n はいくらでも大きな正整数を利用できます。
とありますが、実際には超巨大な値を使おうとすると、warningが表示されます (遊んでいるときに気が付いた)
$ ruby -e '$9999999999999999' -e:1: warning: `$9999999999999999' is too big for a number variable, always nilこうなると
$n
のnとしてどれだけの値が使えるのか気になってくるので、簡単な二分探索を使った以下のコードで調べてみたところ、自分の環境では最大値は1073741823のようでした。require 'stringio' ok = 0 ng = 10**10 while (ok-ng).abs > 1 io = StringIO.new $stderr = io mi = (ok+ng)/2 eval("$#{mi}") if io.size == 0 ok = mi else ng = mi end $stderr = STDERR end p ok #=> 1073741823別の方法で確認してみても、
$1073741823
が最大で、それよりも大きい値になると警告がでるようです。ただ1073741823という値はいかにも環境依存っぽいので、環境によってはもっと大きい値まで使えるかもしれませんし、もっと小さい値で警告が出てくるかもしれません。$ ruby -e '$1073741823' #=> 何も起きない $ ruby -e '$1073741824' #=> 警告が出力される #=> -e:1: warning: `$1073741824' is too big for a number variable, always nil当然の疑問として、キャプチャ数が1073741823個を超える正規表現でマッチが成功した場合どうなるのかということですが、これは無問題。Rubyではキャプチャ数の上限が32767と決まっており、それを超えるような正規表現はコンパイルに失敗します。
$ ruby -e 'Regexp.compile("(.)"*32767)' #=> 何も起きない $ ruby -e 'Regexp.compile("(.)"*32768)' #=> RegexpErrorが発生する。メッセージは次の通り #=> `initialize': too many capture groups are specified:自分は以下のような二分探索を用いた簡単なスクリプトで32767という値を見つけましたが、Rubyの正規表現エンジンである鬼雲のソースコードを見ると、
ONIG_MAX_CAPTURE_GROUP_NUM
というキャプチャ数の上限を示す変数があって、これが32767になっているようです。 であれば、特殊変数$1, $2, $3 ...
の側の最大値を32767にしてもよいような気はしますが(´・ω・`)ok = 0 ng = 10**8 while (ok-ng).abs > 1 mi = (ok+ng)/2 begin Regexp.compile("(.)"*mi) ok = mi rescue RegexpError => e ng = mi end end p ok #=> 32767環境情報
$ ruby -v ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]
- 投稿日:2020-09-26T15:15:04+09:00
FizzBuzz問題の備忘録
昨日のドリルで登場したFizzBuzz問題。
模範回答としては、
def fizz_buzz num = 1 while num <= 100 do if num % 15 == 0 puts "FizzBuzz" elsif num % 3 == 0 puts "Fizz" elsif num % 5 == 0 puts "Buzz" else puts num end num = num + 1 end end fizz_buzzというのが正解だったけど、
rubocopを使ったところ、def fizz_buzz num = 1 while num <= 100 if (num % 15).zero? puts 'FizzBuzz' elsif (num % 3).zero? puts 'Fizz' elsif (num % 5).zero? puts 'Buzz' else puts num end num += 1 end end fizz_buzzと言う形で、
数式を()で括り「その数値が0か否か」を判断する、
zero?メソッドを使った別の記述が(偶然だけど)できた。rubocop的にはやはり、
可能な限りスッキリと整頓した記述がいいんだろうな。
- 投稿日:2020-09-26T14:49:33+09:00
【Ruby】getsメソッドの注意点
標準入力からの文字列との比較処理を行ったところ、なぜかうまく行かなかったので
その原因と解決策を備忘録として記載します。問題点
gets
メソッドは標準入力からの文字列を受け取るためのメソッドです。
このメソッドを利用して取得した入力文字列と別の文字列を比較しようとすると
思い通りの結果が得られませんでした。input = gets # hogeを入力 bool = (input == 'hoge') print boolfalse同じ値の文字列同士を比較してるはずなのになぜか
false
が返ってきました。原因
調べたところ、どうやら
gets
メソッドは標準で末尾に改行コード(\n)を追加するみたいです。input = puts # hogeを入力 p input"hoge\n"改行コードが含まれている状態で比較しようとしていたので、比較しても弾かれてたみたいです。
解決策
末尾の改行コードを削除すればよさそうなので調べてみたところ、
そのためのメソッドとしてchomp
メソッドというのがあり、
こちらを利用したら、期待した結果が得られました!input = gets.chomp # hogeを入力 bool = (input == 'hoge') print booltrue補足
chomp
は何かの略称かなと思って調べてみたところ、teratailでの回答が参考になりました。
chompってなんの略?推測をかなり含んでいますが
もともと、chopというのがあり末尾1文字を消す事ができました。
テキストファイルの末尾は改行で終わるのが(Unixの)マナーだったのでこれで問題なかったのですが
末尾に改行がついてないことや1文字でない環境もあったりと問題になり
「末尾の改行を削除する」関数が追加されchopのmultiline用だからchompになりました。
chop
を末尾1文字から改行コード削除用にしたのが、chomp
メソッドみたいです。参考
https://stackoverflow.com/questions/21504202/why-is-stringchomp-named-like-this
- 投稿日:2020-09-26T14:28:03+09:00
バリデーションメッセージを Decorator で加工する
のっぴきならない事情があり、フォームの入力パターンに応じて、バリデーションメッセージを生成後に加工したかったのでメモ。
例えば、下記のようなフォームがあったとする。new.slim= form_for post_form, url: confirm_post_path do |f| - if post_form.errors.present? ul - post_form.errors.full_messages.each do |msg| li = msgしかし、フォーム内の特定の選択肢を選んだ場合に、バリデーションメッセージを変えるという要件が加わったとする。
この場合、errors.full_messages は Array なので、Decorator で中身を1件ずつチェックして力技で置換した。new.slim= form_for post_form, url: confirm_post_path do |f| - post_form_decorator = ::PostFormDecorator.new(f.object) - if post_form.errors.present? ul - post_form_decorator.post_error_display(post_form.errors.full_messages).each do |msg| li = msgpost_form_decorator.rbclass PostFormDecorator delegate_missing_to :@post_form def initialize(post_form) @post_form = post_form end def post_error_display(error_full_messages) error_full_messages.each do |msg| if @post_form.category == 'music' msg.gsub!(/#{@post_form.model.class.human_attribute_name(:author)}/, '歌手') end end end end破壊的メソッドで中身を入れ替えているので、「!」を付けなければgsubで置換されないので注意。
- 投稿日:2020-09-26T13:21:50+09:00
(Ruby on Rails6) 投稿された内容を"消去" する
まえがき
ここでは、RubyonRails6を使用して、投稿内容を 編集(内容の消去) を行う忘却録を記録します。
以前の投稿で 編集機能の実装 を行いました。編集機能の実装はそちらで記録しているので確認されたい方は、そちらでご確認ください。投稿された内容を"消去" する
この投稿を実装するためには、アクション に データの消去(クリック)・投稿一覧への転送 を行います。
routes の設定
routes に deleteアクション を作成します。
form/:id/delete で、消去したいidのURLを特定させています。
また、データベースを変更する場合はroutes上で "get" ではなく "post" で設定します。config/routes・ ・ ・ post "form/:id/delete" => "form#delete"View へのリンク設定
app/views/任意.html.erb・ ・ ・ <%= link_to("削除", "/form/#{@post.id}/delete", {method: "post"}) %>link_to を用いて、先ほど作成した deleteアクション へリンクしています。
注意: get と post の違い
{method: "post"}) をつけることで、routesのpostと紐づけることができます。
ややこしい!!app/views/任意.html.erbpostでは↓エラー <%= link_to("削除", "/form/#{@forms.id}/delete") %> ↓が正しい <%= link_to("削除", "/form/#{@forms.id}/delete", {method: "post"}) %>データを取り出して削除する
app/controllers/任意.rbdef delete @forms = Form.find_by(id: params[:id]) @forms.destroy redirect_to("/") end↑の詳細
app/controllers/任意.rbdef delete # find_byメソッドで、データを取得する @forms = Form.find_by(id: params[:id]) endapp/controllers/任意.rbdef delete # @テーブル名.destroy で削除する @forms.destroy endapp/controllers/任意.rbdef delete # redirect_toメソッド でリダイレクトを設定する redirect_to("/") end以上が、完了しエラーが怒らなければ、削除機能が出来上がっているはずです。
いかがでしたか?あとがき
ここまで読んでいただき、ありがとうございました。
データベースの設定から表示・修正の機能を実装していて、投稿に削除機能をつけると本格的なサイトみたいですね。
でも、投稿機能が無事に削除された時は嬉しいけど切ない気持ちになります(Why?)データーベースの作成・編集・デリート と基本機能を今までで実装しました。
セキュリティーや詳細機能を今後は学びたいと思います。参考リンク
Myリンク
また、Twitter・Portfolio のリンクがありますので、気になった方は
ぜひ繋がってください。プログラミング学習を共有できるフレンドが出来るととても嬉しいです。
- 投稿日:2020-09-26T12:50:57+09:00
CodeWarでの勉強(ruby)②
この記事について
最近始めたCodewarを通じて学べたことを少しずつアウトプット
問題
An isogram is a word that has no repeating letters, consecutive or non-consecutive. Implement a function that determines whether a string that contains only letters is an isogram. Assume the empty string is an isogram. Ignore letter case.
引数で渡された文字列がアイソグラムであるかどうかチェックをするメソッドを作りなさい。
ただし、大文字・小文字は無視する。
※アイソグラムとは、同じアルファベットが使用されていない文字のこと。is_isogram("Dermatoglyphics" ) == true is_isogram("aba" ) == false is_isogram("moOse" ) == false # -- ignore letter case僕が考えた回答
def is_isogram(string) string = string.downcase.chars if string == string.uniq return true else return false end end①引数で渡された文字列をまずは
downcase
で全て小文字にして、chars
で各文字を配列にいれる。
②配列に入れられた各文字と、uniqメソッド
で重複した文字を排除した配列が同じであればtrue
を返す
③配列が異なればfalse
を返す。理想の答え
def is_isogram(string) string.downcase.chars.uniq == string.downcase.chars endわざわざ条件分岐をしなくても
==
でtrueとfalseを返してくれるんやな。。。。
- 投稿日:2020-09-26T12:50:57+09:00
CodeWarでの勉強②
この記事について
最近始めたCodewarを通じて学べたことを少しずつアウトプット
問題
An isogram is a word that has no repeating letters, consecutive or non-consecutive. Implement a function that determines whether a string that contains only letters is an isogram. Assume the empty string is an isogram. Ignore letter case.
引数で渡された文字列がアイソグラムであるかどうかチェックをするメソッドを作りなさい。
ただし、大文字・小文字は無視する。
※アイソグラムとは、同じアルファベットが使用されていない文字のこと。is_isogram("Dermatoglyphics" ) == true is_isogram("aba" ) == false is_isogram("moOse" ) == false # -- ignore letter case僕が考えた回答
def is_isogram(string) string = string.downcase.chars if string == string.uniq return true else return false end end①引数で渡された文字列をまずは
downcase
で全て小文字にして、chars
で各文字を配列にいれる。
②配列に入れられた各文字と、uniqメソッド
で重複した文字を排除した配列が同じであればtrue
を返す
③配列が異なればfalse
を返す。理想の答え
def is_isogram(string) string.downcase.chars.uniq == string.downcase.chars endわざわざ条件分岐をしなくても
==
でtrueとfalseを返してくれるんやな。。。。
- 投稿日:2020-09-26T12:27:00+09:00
macOS で Ruby 3.0.0-preview1 をインストール(Homebrew の ruby-build を使わない方法も)
はじめに
Ruby 3.0.0 Preview 1 がリリースされました。
https://www.ruby-lang.org/en/news/2020/09/25/ruby-3-0-0-preview1-released/型システム(という呼び方でいいのかしらん?)とか,並行プログラミングをサポートする Ractor だとか,超目玉機能が試せます。
macOS だと Homebrew で rbenv と ruby-build の二つのパッケージを入れて Ruby をインストールしている人が多いと思います。
本記事の読者はそういう方を念頭に置いています。インストール その(1)
今回,3.0.0 Preview 1 がリリースされて速攻1で ruby-build が更新されたので,
brew update brew upgrade ruby-build rbenv install 3.0.0-preview1
とすれば OK。
インストール その(2)
ところが,Homebrew の ruby-build は,対応する Ruby がリリースされてすぐに更新されるとは限りません。
今回はたいへんありがたいタイミングでしたが,3.0.0-dev の場合はリリースされてもなっかなか入らず,結局 3.0.0-preview1 と同時に入ったのでした。こういう場合,Homebrew の ruby-build パッケージを使わない方法があると Slack の ruby-jp で教えていただきました。
試してみたので,その方法を書きます。
まず,現状では Homebrew で rbenv と ruby-build が入っているので,ruby-build のほうをアンインストールします。
しかし,単純にbrew uninstall ruby-buildとやると,
Error: Refusing to uninstall /usr/local/Cellar/ruby-build/20200926 because it is required by rbenv, which is currently installed. You can override this and force removal with: brew uninstall --ignore-dependencies ruby-buildとエラーが出て実行できませんでした。
(なお,消そうとしたヤツが「20200926」と最新になっているのは,brew upgrade
したあとでこれを行ったからです)そこで,上記のメッセージに書かれているとおり,
brew uninstall --ignore-dependencies ruby-build
とやってアンインストールしました。
次に,ruby-build を GitHub のリポジトリーからクローンします。
ruby-build は(単体でも使えるそうですが)rbenv と組み合わせる場合は,rbenv のプラグインとして働くよう,プラグイン置き場に置く必要があります。典型的には,それはホームディレクトリーの
.rbenv/plugins
という場所です(Homebrew で ruby-build を入れた場合はこの場所にはありません)。
つまり,~/.rbenv/plugins
ですね。しかし,典型的でないケースもありうるので,確実に場所を把握したいところ。
rbenv rootで
plugins
ディレクトリーの親ディレクトリーが表示されるので,以下の手順ではこれを利用します。まず,
plugins
ディレクトリーは存在するとは限らないので,mkdir -p "$(rbenv root)"/pluginsとやってディレクトリーを作ります。既に存在していたとしても問題は生じません。
そして,
git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-buildとやると,しかるべき場所に最新の ruby-build がクローンされます。
この状態で
rbenv install 3.0.0-preview1
とすると,3.0.0 Preview1 がインストールされます!
説明が長かったけど,やるべきことは単純ですね。四箇所コピペするだけでした。将来,新しい Ruby がリリースされたら
git -C "$(rbenv root)"/plugins/ruby-build pullで ruby-build を最新版にすればそれがインストールできます。
このへんのことは ruby-build の README にちゃんと書いてあります。
コピペ用まとめ
Homebrew で rbenv と ruby-build がインストールされている環境で,Homebrew 版の ruby-build をアンインストールしてから Ruby 3.0.0-preview1 をインストールするまでの全手順を,コピペしやすいよう,ここにまとめました。
Homebrew 版の ruby-build をアンインストール:
brew uninstall --ignore-dependencies ruby-build
GitHub から ruby-build をクローン:
mkdir -p "$(rbenv root)"/plugins git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-buildRuby 3.0.0-preview をインストール:
rbenv install 3.0.0-preview1
クローンした ruby-build を更新:
git -C "$(rbenv root)"/plugins/ruby-build pullさいごに
Ruby の新しい時代が始まる。さあ,扉を開こう!
え? 「うちは Windows」だって?
タイムラグ 1 日くらい? ↩
- 投稿日:2020-09-26T09:56:48+09:00
Rails6.0ルーティングまとめ
はじめに
Rails6.0のルーティングのパス名 resouces resourceなどを忘備録を兼ねてまとめます。
明示的なルーティング指定
routes.rb# ルートへアクセスするルーティング root 'users#show' root to 'users#show' root '/', to: 'users#show'routes.rb# '/users/:id'でusersコントローラのshowアクションにルーティング get '/users/:id', to: 'users#show'routes.rb# 'hoge'でusersコントローラのshowにルーティング # as:オプションを使うとルーティングに名前を指定可能 get '/users/:id', to: 'users#show', as: 'hoge'<%= form_with %><%= link_to %>などでurlを指定する際に、直接/posts/:idなどのurlのように指定可能ですが、変更の際に修正箇所が多くなり得策ではありません。
as:で名前を付けることで、修正しやすくなり、コードも読みやすくなります。resourcesとresouceの違い
resources(複数)...7つのアクションがid付きで生成されます。
resource(単数) ...indexアクションを除いた6つのアクションがidなしで生成されます。
「写真」「ユーザー」「商品」のようにアプリケーションに複数存在する場合はresources(複数)
「自身のプロフィール」のように一つしか存在せず、idやindexが必要ない場合はresource(単数)resources(複数)
routes.rbresources :photosのような記述で、以下の7つのルーティングが生成されます。この場合、いずれもPhotosコントローラに対応します。
動詞 パス コントローラ#アクション 目的 GET /photos photos#index すべての写真の一覧を表示 GET /photos/new photos#new 写真を1つ作成するためのHTMLフォームを返す POST /photos photos#create 写真を1つ作成する GET /photos/:id photos#show 特定の写真を表示する GET /photos/:id/edit photos#edit 写真編集用のHTMLフォームを1つ返す PATCH/PUT /photos/:id photos#update 特定の写真を更新する DELETE /photos/:id photos#destroy 特定の写真を削除する resource(単数)
routes.rbresource :geocoder以上の記述で以下の6つのルーティングが生成されます。この場合、いずれもgeocoderに対応します。
動詞 パス コントローラ#アクション 目的 GET /geocoder/new geocoders#new geocoder作成用のHTMLフォームを返す POST /geocoder geocoders#create geocoderを作成する GET /geocoder geocoders#show 1つしかないgeocoderリソースを表示する GET /geocoder/edit geocoders#edit geocoder編集用のHTMLフォームを返す PATCH/PUT /geocoder geocoders#update 1つしかないgeocoderリソースを更新する DELETE /geocoder geocoders#destroy geocoderリソースを削除する 注意点
Railsのルーティングはルーティングファイルの上から順に実行します。そのため、同じ条件のルーティングが複数存在する場合、上のルーティングのみ有効になります。なお、無関係なURLの場合は順番は関係ありません。
参考
Railsのルーティング - Railsガイド v6.0
https://railsguides.jp/routing.html
- 投稿日:2020-09-26T01:03:18+09:00
Ruby on RailsにてRails new〜デプロイまでの忘備録1
Ruby on RailsにてRails new〜デプロイまでの忘備録です!
何回かに分けて、Rails newコマンドでアプリケーション作成からデプロイまでの一連をつらつらと書いていきます。
1回目は、Railsアプリケーション雛形作成からリモートリポジトリへpushまで書いていきます。足りない点や間違っている点があったら、教えていただけると嬉しいです。
※Ruby,Rails,GitはPCにインストール済みを想定します。
GitHubもリポジトリの作成等の説明は省きます。環境
開発環境
言語:Ruby 2.5.1
FW:Ruby on Rails 5.2.4
DB:PostgreSQL
test:RSpec
バージョン管理:Git,GitHub環境:MacBookAir
※VirtualBox,Docker等の仮想環境はRailsの基礎を重視するために導入しませんでした。
デプロイ先:heroku
AWSも環境と同じ理由で導入しませんでした。Railsアプリ作成
Rails newコマンドを使ってアプリケーションのディレクトリを作成しましょう!
ターミナル.rails new <App_name> -option実際に私はDBにPostgreSQLを使用したかったので下記のようなコマンドを入力して、最初にアプリケーションに組み込みました。(後でも変更可能です)
ターミナル.rails new App_name -d postgresqlそうするとRailsアプリケーションに必要なディレクトリがスルスル作られます。
作成後、今いるディレクトリから先ほど作成したディレクトリにcdコマンドで移動します。
ターミナル.cd App_nameさて、DBを作成しておきましょう!
ターミナル.rails db:createこれでDBが作成されます。
ターミナル.rails sRailsのサーバーを立ち上げ
http://localhost:3000
にブラウザからアクセス!正しくサーバーが立ち上がったのが確認できましたか?
ちなみに終了はcontrol + c で終了できます。Git管理を始める
Gitを使い始めましょう!
ターミナル.git initこれでGit管理する準備は整いました。
Git関連ディレクトリは、隠しディレクトリとして設定されているので、command + shift + . で可視化しておいてもいいかも知れません作ったアプリケーションをステージングする
私は大体、ステージングの前にステータス(git status)や差分(git diff)の確認を行っていますが割愛します。(変更されたファイルの状態を確認すること)ターミナル.git add .add .(ドット)で全ての変更されたファイルをステージングします。
この場合はRails newで作成された全ファイルですね!ターミナル.git commit -m "first commit"上のコマンドで、変更を記録します!
commitの後ろの -m はオプションであり、コメントを残すためのオプションです!
commitする際は必ずコメントを残すことが決められているので、コメントはどういう変更したのかが理解できるように追加しましょう次はリモートリポジトリへpush!
GitHubにリモートリポジトリを作成したら
ターミナル.git pushと打つと怒られます。
要はリモートリポジトリの接続先が分からないので教えてあげます。
(怒られついでに下記のコマンドを入力するように求められます)ターミナル.git remote add <name> <url>実際のコマンドっぽく書くと↓
ターミナル.git remote origin https://github.com/×××これでOK
あとは下記のコマンドでpushされる。ターミナル.git push -u origin master初回だけは上記のコマンドを使用するが2回目以降はgit pushだけでOK!
ブランチを切ったりする場合も同じです。今回はここまでとします。
あくまで、自分用の忘備録として書いていますが、
ご覧いただきありがとうございました!
- 投稿日:2020-09-26T00:33:39+09:00
Safari で disable_with オプションを付けても変わらない場合
Railsでフォームを作る際、送信ボタンに disable_with オプションを付けることで、二重送信を防ぐことができる。
= f.button '送信する', data: { disable_with: '送信中…' }しかし、Safariに限って、なぜかボタンの文言が変化しなかった。GitHub上でも、多々報告されている。
disable_with doesn't work with link in Safari #306解決策
結論から書くと、JSで送信処理をあえて遅らせることで、とりいそぎは回避できた。
Issue内ではバニラJSで書かれた例が出てくるので、jQueryを使っていなけば、そちらを参考にした方が早いかもしれない。= f.button '送信する', data: { disable_with: '送信中…' }, class: 'disable_with_safari'$('.disable-with-safari').click(function (event) { if ($(this).data('disableWith')) { $(this).prop('disabled', true); $(this).text($(this).data('disableWith')); var form = $(this).closest('form'); if (form.length) { event.preventDefault(); setTimeout(() => form.submit(), 300); } } });備考
冒頭のIssueでも議論されていたが、Safariの独特な仕様で、一度submitが走った後はDOMの更新が行われなくなるようだ。(あくまでもIssue上でのコメントなので、正確な仕様は一次情報を参照してください)
そのため、disable_withをつけても、ボタンの文言は変わらなかった。ちなみに、今回の問題について検索すると以下の解決策が出てきていたが、わたしの場合は効果がなかった。
- cursor: pointer; をつける
- 空のclickイベントを設定する
- 空のtouchstartイベントを設定する
- バインドを$(document)に変更する