管理画面を作りたい(メモ書き)
量が多いのでひとまず細かい手順は記載しません。
課題の反省点
- タスクを上手く分解できなかった
- 何をすべきかは分かっていても、どうすべきなのか検討がつかなかった
大まかな実装の流れ
- yarnでAdminLTE3をインストールする
- コントローラ、ルーティング作成
- admin-lteから使いたいテンプレートをそのままコピペする
- マニフェストファイルに読み込むべきファイルを記載する
- コピペしたテンプレ内に作成したマニフェストファイルを読み込む記載をする
- ビューを分解し、共通レイアウトでレンダリングさせる
- 動的な
<title>
の作成、翻訳追加
ユーザー管理用のコントローラ作成
- application_controllerを継承するadmin/base_controllerを作成
→base_controllerには管理系共通の処理を記載
→Admin::BaseController
という名前をつけることで、Adminというモジュールの名前空間の中にbase_controllerというクラスを定義することになる - Railsではモジュール階層を、コードを保存するためのディレクトリ階層に対応させているため、上記の記述によりapp/controllers/admin/base_controller.rbというファイルが対応することになる
- 管理系の機能を足したいときに、Admin::のついたコントローラを追加していけば、コードがadminディレクトリの下にまとまって分かりやすい
class Admin::BaseController < ApplicationController
↑BaseControllerはApplicationControllerを継承
管理系の各コントローラはこのBaseControllerを継承する設計にする。
作成したいコントローラ
- admin/dashboards_controller.rb(管理画面トップページへ)
- admin/user_sessions_controller(管理者ログインフォーム)
- 管理者用ログイン画面の立ち位置について
→管理者用のログイン画面なだけであってまだこの時点では管理画面ではない(ログイン状態にない)という解釈からビューをviews/layouts配下に置くか、管理画面に関する画面と解釈し、views/admin/layouts配下に置くのか、解釈によって分ける
管理用コントローラとルーティング
2.6 コントローラの名前空間とルーティング | Railsガイド
コントローラは名前空間でグループ化することができる。
管理系のコントローラはAdmin::名前空間の中に作成しているため、ルーティングはこの名前空間でグループ化することができる。
以下のようにnamescpaceブロックを使ってグループ化する
namespace :admin do resources :articles, :comments end
- 管理画面は
/admin
のみでアクセスできるようにroot to:
を使用 - user_sessionsは一般ユーザーのルーティングを参考に以下の通り
namespace :admin do root to: 'dashboards#index' get '/login', to: 'user_sessions#new' post '/login', to: 'user_sessions#create' delete '/logout', to: 'user_sessions#destroy' end
rails consoleで仮の権限持ちユーザーを作っておく
seedsファイルを使った作成方法にまだ行きついていないので仮に作っておく
User.create!(first_name: "admin", last_name: "admin", email: "admin@example.com", password: "password", password_confirmation: "password", role: 1 )
これでログインできるか確かめる
AdminLTEのインストール、マニフェストファイルについて
マニフェストファイルに読み込み設定
アセットパイプラインに「node_modules」のpathが通っているの確認
% rails c > Rails.application.config.assets.paths
↓なんかモリモリ出てきた😨
#<Pathname:/Users/user_name/workspace/***/rails_2/5***/node_modules>
とりあえずこんな表示が入っていればパスが通っているらしい。
パスが通っていない場合はconfig/initializers/assets.rb
に下記パスを記載
↑自分のは元々記載されていた。
管理者判定用のroleカラム(enum型)をusersテーブルに追加する
Usersテーブルにroleカラムをenum(列挙)型で追加する
enum型とは?
一つのカラムに指定した複数個の定数を保存できるようにするためのもの。
今回の例で言えば、role(役割)というカラムにgeneral(一般)とadmin(管理者)という二つの定数を保存したい。
特徴
- 指定した複数個の定数以外は保存できなくなる
- カラムに指定した定数が入っているレコードを取り出すのが容易になる
- enumはinteger型(0,1,2...)、もしくはboolean型(true,flase)としてDBに保存される
enumを使うためには?
①テーブルにenum用カラムを追加
bundle exec rails g migration AddRoleToUsers
② changeメソッドを編集
class AddRoleToUsers < ActiveRecord::Migration[5.2] def change add_column :users, :role, :integer, default: 0, null: false # 必ず一般ユーザーか権限ユーザーに振り分けるのでNOTNULL制約を追加 # generalは0、adminは1が入るようにuser.rbに後ほど記載 end end
③ enumのカラムに複数個の定数を紐づけていく
# user.rb enum role: { general: 0, admin: 1 } # 定数の数が多い場合、配列(シンボルor文字列)で書くとスッキリする # 配列で定義するとインデックスが自動で定数と紐づいてくれる enum role: [ :general, :admin ] enum role: [ "general", "admin" ]
※注意点
- enumを使うならboolean型はあまり使わない方が良い。
- enumの魅力は複数の定数を定義できること、そもそもtrueかfalseの二択で良いのなら、booleanだけで十分。enumを使う必要はない。
- Rails5.2系でfalseにupdateする際にnullに更新しようとするバグが発生している。
エラー
admin_login.html.erbに<%= csrf_meta_tags %>
の記述がないの下記エラーが発生するらしい。
ただ自分は<%= csrf_meta_tags %>
を追加してもエラーが解決しなかった。Ajaxで送信するフォームだと<%= csrf_meta_tags %>
を<head>
内で呼び、X_CSRF_Tokenをリクエストヘッダーに付与することでCSRF対策ができるそうな。
RailsのPOSTでCSRF TokenがVerifyできないときに確認したいこと - Qiita
formはlocal: trueのまま変更していないから、タグを追加しても変わらなかったのか🤔??
class ApplicationController < ActionController::Base protect_from_forgery # 追加
↑の記載を追加することでエラーが解決 【Rails API】ActionController::InvalidAuthenticityTokenの解決方法 - Qiita
このあとbase_controllerに記載したcheck_adminの判定ロジックにおいてnilに対して呼び出しているエラーが出たため、ぼっち演算子に変更したところ問題なく動作した。
参考にしたサイト
enum
【Rails】 enumチュートリアル | Pikawaka
AdminLTE
[管理画面]Rails 5 に yarnでインストールした「AdminLTE3.0.0-alpha.2」 を適用させる方法 - Qiita
AdminLTEを使って管理者用機能を実装する(トップページ) - Programming Learning Diary
AdminLTE 3を使って管理者ページを実装しよう - プログラミングの備忘録
CSRF(クロスサイトリクエストフォージェリー)対策
ActionController::InvalidAuthenticityTokenの解消(解決済み) - Blogメモφ(..)
ActionController::InvalidAuthenticityTokenのエラーが出る|simesime|note
【Rails API】ActionController::InvalidAuthenticityTokenの解決方法 - Qiita
アセットのプリコンパイル
アセット
https://wa3.i-3-i.info/word18324.html
「資産」、「財産」といった意味合いの言葉。リソースで良いじゃんと思った。
別にIT用語というわけではないらしい。
railsでは意味をさらに絞ってCSS,JavaScriptなどの静的なファイルに限定しているような感じがします。Ruby on Rails プリコンパイル という言葉の定義は?
コンパイル
https://wa3.i-3-i.info/word186.html
プログラムを作るとき、
まず、人間の言葉でプログラムの元ネタ(ソースコード)を書く。
しかし、機械は人間の言葉がわからないので書いたソースコードを機械語に翻訳する作業が必要になってくる。この作業をコンパイルと言う。
つまりコンパイルとは、ソースコードをバイナリコードに変換する作業と言える。
では、プリコンパイルとは?
プリコンパイルで検索すると、「プリコンパイラ」みたいな言葉が多く出てきた。
「事前に(pre)」コンパイルを行うってことですね。 コンパイルというのは、この場面では、CoffeeScriptとか、SCSSとか、ブラウザが直接は読めない形式のファイルを、JSやCSSに変換してあげるということです。
↑Ruby on Rails プリコンパイル という言葉の定義は?
↓
何に対して「事前」かというと、「rails serverが走るよりも前」ということです。Rubyはインタープリター方式の言語で、物事を解釈しながら進むのですが、アセットパイプラインは、最初に一気にやってしまうわけですね。precompileをかけない状態でサーバーをproductionモードで起動すると、JSやCSSが存在せず、エラーになってしまいます。
プリコンパイルとは
コンパイラが言語の翻訳ができるように、事前に準備することです。コンパイラに翻訳をお願いする前に、もっとコンピュータの分かりやすい言語にしてあげることです。
他のマニフェストや、個別のスタイルシート/JavaScriptファイルをインクルードしたい場合は、config/initializers/assets.rbのprecompileという配列を使う。
application以外のマニフェストファイルを個別に読み込みたい場合はプリコンパイルの設定をしないと、ファイルが対象外とされエラーが出てしまうらしい。
# コメントアウトされているのでシャープを外す Rails.application.config.assets.precompile += %w( admin.js admin.css )
宣言したら(decleared)サーバーを再起動する。
layout宣言とは
Railsは現在のレイアウトを検索するときに、最初に現在のコントローラと同じ基本名を持つレイアウトがapp/views/layoutsディレクトリにあるかどうかを調べます。たとえば、PhotosControllerクラスのアクションからレンダリングする場合は、app/views/layouts/photos.html.erb(またはapp/views/layouts/photos.builder)を検索します。コントローラ固有のレイアウトが見つからない場合は、app/views/layouts/application.html.erbまたはapp/views/layouts/application.builderを使います。.erbレイアウトがない場合は、builderレイアウトがあればそれを使います。Railsには、個別のコントローラやアクションに割り当てる特定のレイアウトをより正確に指定する方法がいくつも用意されています。
layout宣言
コントローラ用のレイアウトを指定する。既存のレイアウトのルールはlayout宣言で上書きすることができる。
例えば、
class ProductsController < ApplicationController layout 'inventory'
通常、Productsという名前と同じ基本名を持つレイアウトを探すが、layout宣言によりinventoryが指定されているので、inventory.html.erbがレイアウトとして用いられる。
アプリケーション全体で特定のレイアウトを使いたい場合は、layoutをApplicationControllerクラスで宣言する。
class ApplicationController < ActionController::Base layout 'main'
この宣言により、アプリケーション全てのビューでapp/views/layouts/main.html.erbレイアウトが使われるようになる。
管理画面課題の例
ベースとなるAdmin::BaseControllerではadmin/layouts/application.html.erbをレイアウトとして用いる。
class Admin::BaseController < ApplicationController before_action :check_admin layout 'admin/layouts/application'
Admin::BaseControllerを継承しているAdmin::UserSessonControllerでは読み込むファイルの関係でログイン画面用のレイアウトを用いるためlayout宣言でさらに上書きされている。
class Admin::UserSessionsController < Admin::BaseController skip_before_action :require_login, only: %i[new create] skip_before_action :check_admin, only: %i[new create] layout 'layouts/admin_login'
↑ちなみになんで管理者用ログインページなのに、admin配下に置かないのか
ログイン画面に関してはログインしていない状態のため、まだ管理画面ではないという解釈に基づき、admin配下ではないlayouts配下に置かれているとのこと。
管理用ログイン画面も管理画面に関する画面と解釈するならばviews/admin/layouts/配下に置く。
AdminLTEとマニフェストファイルの読み込みについて
マニフェストファイルとは
どのファイルを読み込むのか取りまとめたファイルのこと。
- HTMLでは、そのページで必要となる読み込みファイルを
<head></head>
内で読み込んでいる。 - CSSファイル、JSファイルはそれぞれ
stylesheet_link_tag
、
javascrippt_includee_tag
というヘルパーメソッドを用いて読み込みファイルを読み込む
↓こんな感じ
<!-- ファイルの拡張子は省略可 --> <!-- stylesheetはhead内で読み込んでいた --> <%= stylesheet_link_tag ‘application’, media: ‘all’ %> <!-- JSファイルはbody内の下部辺りで読み込まれていた --> <%= javascript_include_tag ‘application’ %>
↑に記載の通り、layout/application.html.erb
の<head></head>
内でデフォルトで読み込んでいるのは application.css
とapplication.js
という2種類
2種類のファイル内にはそれぞれ以下の記載がされている。
application.css
*= require_self (自分自身を読み込む) *= require_tree . (同階層に存在している全てのファイルを読み込む)
↓拡張子をscssに置き換えた場合は@import "○○";
のように記載する
@import "bootstrap"; @import "tasks";
application.js
//= require_tree .
「//=」で始まる行は、アセットパイプラインに指示を伝えるための行
アセットパイプラインって何だっけ?😕
JavaScriptやCSS、画像などのリソース(アセットと呼ぶ)を効率的に扱う仕組みのこと。sprockets-rails gemによって提供されるSprocketsの機能、デフォルトで有効になっている。スプロケットは自転車のチェーンを送る歯車のことを言うらしい。
ある一つのパイプライン処理に通すことで、難しい言語を分かりやすくしたり、ファイルを連結したり、改行・コメントアウト・スペースを消して通信量を節約したり、ファイルを最適化してくれる処理のこと。(正確な説明ではないと思われ)
読み込みファイルを読み込む流れ(まとめ)
<head>
や<body>
に記載されたapplication.css/application.jsの読み込みapplication.css/application.js各ファイル内でどのファイルを読み込むか取りまとめる (初期段階では同階層全てのファイルと自身を読み込むように定義されている)
という流れを経て、必要なファイルが読み込まれている。 このapplication.css/application.jsのように、どのファイルを読み込むのかを取りまとめたファイルをマニフェストファイルと呼ぶ。
どうやって見た目を作っていくのか
yarnでAdminLTEをインストール後、node_modules配下にadmin_lte/というディレクトリが作成されるので、この中から必要な箇所をマニフェストファイルに記載して読み込みたい。
コピペしたとしても、マニフェストファイルからの読み込み設定がされていなければビューに反映されないので、確認しつつができなくて困った。
どうすべきだったのか
admin_lte/ディレクトリ配下にあるテンプレートをブラウザで表示させ、検証を用いて<head>
や<body>
内にどのような記載がされているのか確認する。
例えば、今回指定の管理画面はAdminLTEのstarter.htmlが完成形だったため、そのまま参考にすれば良いだけの話だった。(とはいえ、それを自力で発想できる気はしなかった。。)
https://adminlte.io/themes/v3/starter.html
↑つまり、このサンプルHTMLで使用されているJavaScriptとCSSと同じものを適用させれば、自作の管理画面もサンプルと同じような挙動をしてくれる。
AdminLTE3のインストール
俺たちは雰囲気でAdminLTEを使っている - Qiita
AdminLTE(Bootstrapベースで作られたCSSフレームワーク)という公開ライブラリを使用して、管理画面用のCSSやJavascriptを適用する。
yarn add admin-lte@^3.0
Introduction | AdminLTE 3 Documentation
↑他にもgit cloneやnpm,composerなどの読み込み方法がある。
★上記のコマンドを使用後、git statusに表示されているファイルがpackege.jsonとyarn.lockだけだったため、node_modules
が作られていることに気が付かなかった。.gitignoreの中にnode_modulesの記載があったので、自動的にgitで追跡しない設定にされているっぽい🤔
このnode_modules内にテンプレートが記載されている。コピペして作りたいビューを作成する、とのこと。
★ポイント★
AdminLTEにstarter.htmlのサンプルが用意されているので、検証でHTMLの
情報を確認し、何が読み込まれているのか参考にする。ここは元々ヒントがあったものの、どういう意味なのか理解することができなかった。。
AdminLTEはインストールしただけではブラウザでCSS・JSを読み込むことはできないので、上記を参考にマニフェストファイルに読み込みたいファイルを記載して使用する。
JavaScriptは<body>
内にREQUIRED SCRIPTSというまとまりで定義されている
↑自分で調べた画面は<!-- REQUIRED SCRIPTD -->
というコメントアウトが記載されていなくて探すのに物凄く時間がかかってしまったけど、シンプルにscriptを探せば良かった。
<script src="plugins/jquery/jquery.min.js"></script> <script src="plugins/bootstrap/js/bootstrap.bundle.min.js"></script> <script src="dist/js/adminlte.min.js?v=3.2.0"></script>
マニフェストファイルでの読み込み方
app/assets/javascript/admin.jsに
//= require admin-lte/dist/js/adminlte.min
のように記載することで下記のファイルを読み込んでいる。JSのマニフェストファイルなので.js拡張子は省略可能
CSSは<head>
内に読み込んでいる記載がある
app/assets/stylesheets/admin.scss
@import 'admin-lte/dist/css/admin.min';
読み込む際にnode_modules/から記載しなくて良い理由
なぜnode_modules/配下のファイルなのに、記載が要らないのか
自分はここに疑問すら持たなかった(苦笑)
Rails.application.config.assets.paths
という設定が関係している。RailsコンソールでRails.application.config.assets.pathsとコマンド入力してみると、大量にパスが出現する。その中にnode_modulesの設定もあるので
#<Pathname:/Users/user_name/workspace/runteq/rails_2/5118_user_name_runteq_curriculum_normal/node_modules>
これらの出力されたパスの先頭から順に検索していくらしい??
config/initializers/assets.rb内の
Rails.application.config.assets.paths << Rails.root.join('node_modules')
という記載でパスが追加されているそうな。
//= require_tree .の記載について
app/assets/javascripts/application.jsで//= require_tree .
の記載を消す
require_treeの特徴
指定したディレクトリ以下の全てのJSファイルを読み込む
→require_tree .
では.(ドット)
が指定されているので同じ階層以下の全てのJSファイルを読み込んでいる読み込む順序を指定できないので、利用しているJSファイルが特定の読み込み順に依存している場合に不都合が生じる
↑
app/assets/javascripts/application.jsと同じ階層に、
app/assets/javascripts/admin.jsを作っている
app/assets/javascripts/application.jsでrequire_tree .してしまうと、
app/assets/javascripts/application.jsでapp/assets/javascripts/admin.jsを読み込んでしまう。
つまり?
admin系は管理画面でしか使わないのに、共通のapplication.jsで読み込んでしまうのはよろしくないので、require_tree .を使わず、必要なファイルを個別に必要な順序で読み込む。
感想
今回の課題、何をすべきかは分かっていた気がするけど、どうすべきかが全く分からなかった。課題自体も進めている内に何をしたら良いか段々と分からなってきてかなり大変だった。Sorcery並みに大パニックだった...笑
パスワード再設定課題メモ
★ 完成イメージに対し、どういった実装をするのか必要なのかを洗い出しておくと。To doリストを作っておくことで、こんがらがってきたときに対処しやすい。
ユニーク制約、nilは許可する
bundle exec rails g sorcery:install reset_password --only-submodules
マイグレーションファイルにユニーク制約追加
add_index :users, :reset_password_token, unique: true
モデルにもバリデーション追加
この時、一意性を保つuniqueness: true
だけでなく、allow_nil: true
というオプションを追加すること。この記載がない場合、tokenがnilの時も重複と見なされてしまう。tokenはデフォルトではnilのため、複数のユーザーを登録できなくなってしまう。nilという状態を許容してあげる必要がある。
※wikiに書いていことはままある
validates :reset_password_token, uniqueness: true, allow_nil: true
password_resetsコントローラの働き
★ぼっち演算子、破壊的メソッドを使う理由
# password_resets_controller.rb def create @user = User.find_by(email: params[:email]) @user&.deliver_reset_password_instructions! # ここでぼっち演算子を用いているのは、emailが実在するしないに関わらず処理を通すため # 適当にメアドを打って、実在するかしないか確認できてしまうのはセキュリティ面でよろしくない # 失敗時の処理を指定していないため破壊的メソッドを使って、失敗時には例外を発生させる redirect_to login_path, success: 'パスワードリセット手順を送信しました' end
★edit,updateアクションでは@userが存在しなかった場合の処理が記載されているが、if文は後置ifを用いて短く書くことができる
def edit @token = params[:id] @user = User.load_from_reset_password_token(@token) # トークンからユーザーを検索する処理。wikiだと引数にparams[:id]を渡しているが、@tokenを渡しても同じことなのでどちらでも可 # 変更前 if @user.blank? not_authenticated return end # 変更後 return not_authenticated if @user.blank? end
def update @token = params[:id] @user = User.load_from_reset_password_token(@token) return not_authenticated if @user.blank? @user.password_confirmation = params[:user][:password] if @user.change_password(params[:user][:password]) redirect_to login_path, success: 'パスワードを変更しました' else flash.now[:danger] = 'パスワードを変更できませんでした' render :edit end end
サブモジュールの追加、メイラーの設定
# config/initializers/sorcery.rb # サブモジュールを追加する記載 Rails.application.config.sorcery.submodules = [:reset_password] Rails.application.config.sorcery.configure do |config| config.user_config do |user| # メイラーを指定する記載 # コメントアウトされているので、#を外せばOK user.reset_password_mailer = UserMailer end end
メール本文のtext形式、html形式は何が違うのか
reset_password_email.html.erb
とreset_password_email.text.erb
と二つ存在する理由について
まず、html形式の方が色をつけられたり、画像を挿入できたりバリエーションに富んだメールを送ることができる。けれどもブラウザによってはhtml形式のメールを表示することができないものもあるらしいので、そういったクライアントに対してメール本文が確認できるように、テキスト形式のものも用意しておく。
環境ごとの定数管理
この記事で記載したconfig.aciton_mailer.default_url_options = { host: localhost:3000 }
について深堀りしたい。
↑でメール内のリンクが上手く通らなかったのは、:hostパラメータを明示的に指定していなかったため(2.7 Action MailerのビューでURLを生成する | Railsガイド参照)。現にhostの記述を追加したことで解決している。
解答例の書き方を噛み砕いてみる
# config/environments/development.rb config.action_mailer.delivery_method = :letter_opener_web config.action_mailer.default_url_options = Settings.default_url_options.to_h
to_hメソッドの部分は何をしてる?
【Ruby】 to_hメソッドの使い方を理解しよう | Pikawaka
二次元配列をハッシュに変換するメソッド
[["name", "dog"]]
こういうのを二次元配列というらしい。
[key, value]
のペアとして作成した配列に対し、to_hメソッドを実行する。この時、二次元配列でないとエラーが出る。
# キーは文字列でなく、シンボルでも指定ができる animal = [[:name, "dog"],[:age, 5]] animal.to_h => {:name=>"dog", :age=>5}
もう一度確認してみる
# config/environments/development.rb config.action_mailer.default_url_options = Settings.default_url_options.to_h
# config/settings/development.yml default_url_options: host: 'localhost:3000' # => default_url_options = [[:host, "localhost:3000"]]
Settings.default_url_options.to_h # => {:host => "localhost:3000"}
↓
config.aciton_mailer.default_url_options = { host: localhost:3000 }
( д) ゚ ゚
アハ体験をした
感想
今の段階の謎としては、「development.rb」という開発環境のファイルに記載しているんだから{ host: localhost:3000 }とそのまま記載しちゃダメなの?と思っちゃうけどどうなんだろう?🤔
果たしてこれが分かりやすいのかと、今の自分に聞かれるとうーんと唸ってしまう。ただ定数を環境ごとに管理することで、メンテナンスの際に修正箇所が少なく済むというのはよく分かルような分からないような。。
gem: configについて
★gem: configを使うことで便利に定数管理ができる!
- 環境ごとに異なる定数を管理するため
- 設定値をconfigフォルダ以下に一元管理することでメンテナンスが楽になる
- 環境ごとに値が変わらない場合は一つ上の階層の
config/settings.yml
ファイルに記述すると良い
gem 'config'
bundle install --path vendor/bundle
$ bundle exec rails g config:install Running via Spring preloader in process 2577 create config/initializers/config.rb create config/settings.yml create config/settings.local.yml create config/settings create config/settings/development.yml create config/settings/production.yml create config/settings/test.yml append .gitignore
.gitignoreに自動で追加されるファイル
config/settings.local.yml config/settings/.local.yml config/environments/.local.yml
基本的にはconfig/settings.yml(全ての環境で利用する定数を定義)に記載する 環境ごとに定数を定義する場合はそれぞれのファイルへ .gitignoreに追加されているsetting.local.ymlには共有したくないものを記載する
共有したくないものって一体なんだろう?🤔
使い方例
- 環境ごとにhost情報を分けたい時など便利
# config/settings/development.yml host: 'localhost:3000'
# config/environments/development.rb config.action_mailer.delivery_method = :letter_opener_web config.action_mailer.default_url_options = { host: Settings.host }
翻訳の呼び出しと似ていると思った。
各環境ごとに設定されたsettings配下のファイルの設定された定数hostが適用される的なことだと思う。
本番環境にデプロイする際は、config/settings/production.ymlに取得したドメイン名を設定する。
★デプロイ(deploy)…(兵士などを)配備する、展開する
≒作ったプログラムを然るべき場所に置き、あれこれ設定して使える状態にすること
みなさんがプログラムを作る目的は、プログラムを作ることではありません。プログラムを動かすことです。つまり、プログラムが完成した時点では、まだ途中なのです。完成したプログラムがお仕事できる状態になって、はじめて作業完了です。 この、完成したプログラムを動かせる状態にするのが(システム開発の話で出てくる)デプロイです。 https://wa3.i-3-i.info/word16767.html
参考にしたサイト
Rails 定数を管理するsettings.yml・環境ごとの定数管理の方法 - Qiita
【Rails】「config」gemを使って定数管理をおこなう方法 | vdeep