- 投稿日:2020-01-07T22:49:06+09:00
[Rails]本日のエラー
今度作業する時に、あれ?過去にも同じエラーが起こったことあるぞ!!となった時用に記事として保管しておくのが目的です。
なので、個人的に使用する記事なので投稿内容は大雑把にまとめます。記事の流れ
1.なんの作業中にエラーが起きたのか
2.エラーの内容
3.対処法
4.原因以上の流れで書いていきます。
1.dbをリセットしようとした時
ターミナル.rake db:migrate:reset2.エラー内容
ActiveRecord::NoEnvironmentInSchemaError: Environment data not found in the schema. To resolve this issue, run: bin/rails db:environment:set RAILS_ENV=development Tasks: TOP => db:migrate:reset => db:drop => db:check_protected_environments (See full trace by running task with --trace)3.対処法
rake db:migrate:status上記のコマンドでdbのステータスを確認します。
⬇︎実行内容up 20191223083031 Create articles up 20191223091431 Devise create users up 20191225043801 Add name to user down 20191225083536 Add frequency to habitsどうやら、一番下のマイグレーションファイルが怪しい。。。
確認したところ
habitsテーブルにfrequencyカラムを二回作成していました。。
なので、一番下のマイグレーションファイルを削除してみます。
※downの状態だったら、手動でファイルを削除しても問題ない
⬇︎実行結果== 20191225234523 CreateHabits: migrating ===================================== -- create_table(:habits) -> 0.0302s == 20191225234523 CreateHabits: migrated (0.0302s) ============================ == 20191229141445 AddImageToHabits: migrating ================================= -- add_column(:habits, :image, :string) -> 0.0195s == 20191229141445 AddImageToHabits: migrated (0.0195s) ======================== == 20200101140707 AddDateAtToHabits: migrating ================================ -- add_column(:habits, :date_at, :date) -> 0.0231s == 20200101140707 AddDateAtToHabits: migrated (0.0232s) ======================= == 20200103135302 CreateLikes: migrating ====================================== -- create_table(:likes) -> 0.0157s == 20200103135302 CreateLikes: migrated (0.0158s) ============================= == 20200107020748 AddLikesCountToHabits: migrating ============================ -- add_column(:habits, :likes_count, :integer) -> 0.0174s == 20200107020748 AddLikesCountToHabits: migrated (0.0174s) ===================問題なくできました。
4.原因
1つのテーブルに同じカラム名のカラムを追加、作成するマイグレーションファイルが重複していたため、migrateコマンドが実行できなかったと思われる。
なぜ二つ追加、作成したかは謎。
参考記事
https://blog.freedom-man.com/no-environment-in-schema-error
- 投稿日:2020-01-07T21:25:49+09:00
【Rails】2つのテーブルを結合しつつ、欲しいカラムだけを抜き出してJSONで返すサンプルコード
はじめに
Railsで2つのテーブルを結合しつつ、欲しいカラムだけを抜き出してJSONにして返すサンプルコードです。
このコードで出来たJSONはネストされておらず、シンプルなので扱いやすいです。
環境
OS: macOS Catalina 10.15.1 Ruby: 2.6.5 Rails: 6.0.2.1前提
- UserモデルとPostモデルがある
- User1に対してPostが多の関係
- それぞれのテーブル名はusersとposts
- 以下のように関連付け済み
user.rbclass User < ActiveRecord::Base has_many :posts endpost.rbclass Post < ApplicationRecord belongs_to :user end欲しいデータ
各テーブルのカラムは以下のように多数あり、
「不要なデータは取得したくない!」
という状況を想定し、#欲しいを付けたカラムだけを抜き出したJSONが欲しいとします。- usersテーブル - id - name #欲しい - email - ... - postsテーブル - id #欲しい - name #欲しい - description #欲しい - user_id #欲しい - date - ...これは以下コードで実現可能です。
結論
posts_controller.rbdef posts_needed posts_needed = Post.joins(:user) .select(" posts.id, posts.name, description, #ここはusersテーブルと名前が被らない user_id, #ここはusersテーブルと名前が被らない users.name AS user_name #別名を付けられる ") render json: posts_needed end【ポイント】
Post.joins(:user)でpostsテーブルとusersテーブルを結合
.select("カラム1, カラム2, ...")で欲しいカラムを指定元のカラム名が被る場合は
posts.nameやusers.nameのようにテーブル名.カラム名として指定しないと、両方取り出すのは不可
テーブル名.カラム名 AS 任意名で出力されるカラム名を指定可能テーブル名は複数形
出力
出力(JSON)[ { "id": 1, "name": "投稿名1", "description": "投稿詳細1", "user_id": 2, "user_name": "Brutus" }, { "id": 2, "name": "投稿名2", "description": "投稿詳細2", "user_id": 3, "user_name": "Omae Dattanoka" }, ... ]ネストされたものよりシンプルで扱いやすいJSONに仕上がりました
おわりに
最後まで読んで頂きありがとうございました
どなたかの参考になれば幸いです
参考にさせて頂いたサイト(いつもありがとうございます)
- 投稿日:2020-01-07T21:17:20+09:00
Dockerでalpineイメージ使用時に発生したstandard_init_linux.go:211: exec user process caused "no such file or directory" を解決
alpineイメージ使用時に発生するstandard_init_linux.go:211: exec user process caused "no such file or directory" を解決
Docker X Rails6 X MySQL8で環境構築する際に、初めてalpineイメージを使用するとエラーに出会いました。
alpineはLinuxディストリビューションの1つで、CentOSやUbuntuよりも軽量なためDockerイメージのサイズを小さくすることができます。各種設定
DockerfileFROM ruby:2.7.0-alpine ENV LANG C.UTF-8 RUN mkdir /myapp WORKDIR /myapp COPY Gemfile /myapp/Gemfile COPY Gemfile.lock /myapp/Gemfile.lock RUN apk update -qq && apk add --no-cache yarn build-base tzdata libxml2-dev mariadb-dev libxslt-dev alpine-sdk mysql-dev nodejs vim g++ RUN bundle install run yarn install COPY . /myapp # 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"] EXPOSE 3000 # Start the main process. CMD ["rails", "server", "-b", "0.0.0.0"]docker-copose.yml~~省略 web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/myapp ports: - "3000:3000" ~~省略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 "$@"(他,
Gemfile,Gemfile.lock)エラー発生
$ docker-compose run web rails new .を実行すると
standard_init_linux.go:211: exec user process caused "no such file or directoryというエラーが発生し、
rails newは実行できませんでした。原因
alpineのシェルは
bashではなくashだった。解決
docker-compose.ymlとentrypoint.shを編集します。docker-compose.ymlweb: build: . # bash → ashに変更 command: ash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/myapp ports: - "3000:3000"entrypoint.sh#!/bin/sh ←bashからshへ 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-compose run web rails new .すれば実行できました。
参考
- 投稿日:2020-01-07T21:17:20+09:00
alpineイメージ使用時に発生するstandard_init_linux.go:211: exec user process caused "no such file or directory" を解決
alpineイメージ使用時に発生するstandard_init_linux.go:211: exec user process caused "no such file or directory" を解決
Docker X Rails6 X MySQL8で環境構築する際に、初めてalpineイメージを使用するとエラーに出会いました。
alpineはLinuxディストリビューションの1つで、CentOSやUbuntuよりも軽量なためDockerイメージのサイズを小さくすることができます。各種設定
DockerfileFROM ruby:2.7.0-alpine ENV LANG C.UTF-8 RUN mkdir /myapp WORKDIR /myapp COPY Gemfile /myapp/Gemfile COPY Gemfile.lock /myapp/Gemfile.lock RUN apk update -qq && apk add --no-cache yarn build-base tzdata libxml2-dev mariadb-dev libxslt-dev alpine-sdk mysql-dev nodejs vim g++ RUN bundle install run yarn install COPY . /myapp # 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"] EXPOSE 3000 # Start the main process. CMD ["rails", "server", "-b", "0.0.0.0"]docker-copose.yml~~省略 web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/myapp ports: - "3000:3000" ~~省略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 "$@"(他,
Gemfile,Gemfile.lock)エラー発生
$ docker-compose run web rails new .を実行すると
standard_init_linux.go:211: exec user process caused "no such file or directoryというエラーが発生し、
rails newは実行できませんでした。原因
alpineのシェルは
bashではなくashだった。解決
docker-compose.ymlとentrypoint.shを編集します。docker-compose.ymlweb: build: . # bash → ashに変更 command: ash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/myapp ports: - "3000:3000"entrypoint.sh#!/bin/sh ←bashからshへ 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-compose run web rails new .すれば実行できました。
参考
- 投稿日:2020-01-07T21:17:20+09:00
Dockerでalpineイメージ使用時に発生するstandard_init_linux.go:211: exec user process caused "no such file or directory" を解決
alpineイメージ使用時に発生するstandard_init_linux.go:211: exec user process caused "no such file or directory" を解決
Docker X Rails6 X MySQL8で環境構築する際に、初めてalpineイメージを使用するとエラーに出会いました。
alpineはLinuxディストリビューションの1つで、CentOSやUbuntuよりも軽量なためDockerイメージのサイズを小さくすることができます。各種設定
DockerfileFROM ruby:2.7.0-alpine ENV LANG C.UTF-8 RUN mkdir /myapp WORKDIR /myapp COPY Gemfile /myapp/Gemfile COPY Gemfile.lock /myapp/Gemfile.lock RUN apk update -qq && apk add --no-cache yarn build-base tzdata libxml2-dev mariadb-dev libxslt-dev alpine-sdk mysql-dev nodejs vim g++ RUN bundle install run yarn install COPY . /myapp # 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"] EXPOSE 3000 # Start the main process. CMD ["rails", "server", "-b", "0.0.0.0"]docker-copose.yml~~省略 web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/myapp ports: - "3000:3000" ~~省略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 "$@"(他,
Gemfile,Gemfile.lock)エラー発生
$ docker-compose run web rails new .を実行すると
standard_init_linux.go:211: exec user process caused "no such file or directoryというエラーが発生し、
rails newは実行できませんでした。原因
alpineのシェルは
bashではなくashだった。解決
docker-compose.ymlとentrypoint.shを編集します。docker-compose.ymlweb: build: . # bash → ashに変更 command: ash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/myapp ports: - "3000:3000"entrypoint.sh#!/bin/sh ←bashからshへ 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-compose run web rails new .すれば実行できました。
参考
- 投稿日:2020-01-07T21:11:50+09:00
herokuへデプロイ後、We're sorry, but something went wrong.
- 投稿日:2020-01-07T20:54:50+09:00
AWSでのデプロイ手順①ネットワーク環境設定
初心者には難関である、AWSを使用したデプロイ手順を書いてみます
AWSはUIもよく変化するので、
現在のもの(2019/10)で書いています※アカウントがない人はまず新規で申し込みしておいてください
今回内容
STEP1 ネットワーク環境設定
1.VPCの作成
2.サブネットの作成
3.インターネットゲートウェイの作成
4.ルートテーブルの作成
5.サブネットとの紐付け
6.セキュリティグループの作成STEP2 EC2の設定
1.EC2にてインスタンスの作成
2.Elastic IPの割り当て
3.インスタンスにSSHでログイン次回内容
STEP3以降
AWSでデプロイするまでの手順②サーバー(EC2インスタンス)環境設定※ここでいうサーバーとはAWS EC2インスタンス (Amazon Linux) のこととする
STEP1 ネットワーク環境設定
1.VPCの作成
https://aws.amazon.com/
Amazon Web Servicesでサインインしますヘッダーにあるリージョンを東京に設定し、
「VPC」を検索し「VPC」にいきます作成画面になるので
今回は下のように設定し、[作成]を押下します・ネームタグ :testVPC ・IPv4 CIDRブロック:10.0.0.0/16 ・IPv4 CIDRブロック:ブロックなし ・テナンシー :デフォルト2.サブネットの作成
サイドメニューのサブネットより[サブネットの作成]を押下します
作成画面になるので
下のように設定し、[作成]を押下します・ネームタグ:testSubnet ・VPC:先ほど作成したものを選択 ・アベイラビリティゾーン:ap-northeast-1a ・CIDRブロック:10.0.0.0/243.インターネットゲートウェイの作成
サイドメニューのインターネットゲートウェイより
[インターネットゲートウェイの作成]を押下します作成画面になるので
下のように設定し、[作成]を押下します名前タグ:testGateway下のように設定し、[アタッチ]を押下する
VPC:先ほど作成したものを選択4.ルートテーブルの作成
サイドメニューのルートテーブルより[ルートテーブルの作成]を押下
作成画面になるので
下のように設定し、[作成]を押下します名前タグ:testTable VPC:先ほど作成したものを選択作成したルートテーブルを選択した状態で、
下のタブ「ルート」>「ルートの編集」を押下、[ルートの追加]を押下下のように設定し[ルールの保存]を押下します
送信先:0.0.0.0/0 ターゲット:Internet Gatewayを選択し、先ほど作成したゲートウェイIDを選択5.サブネットとの紐付け
→左側の「サブネット」を選択します →関連付けを変更するサブネットを選択します →画面下のルートテーブルを選択します →[ルートテーブルの関連付けの編集]を押下します→先ほど作成したルートテーブルIDを選択します →[保存]を押下します6.セキュリティグループの作成
サイドメニューの
セキュリティ>セキュリティグループより>[セキュリティグループの作成]を押下します
下のように設定し、[作成]を押下する
セキュリティグループ名:testSecurityGroup 説明:そのセキュリティグループの説明 VPC:先ほど作成したものを選択画面下のインバウンドのルールの[ルールの編集]を押下し、[ルールの追加]を押下、
下のように設定し、[ルールの保存]を押下するタイプ:SSH ソース:マイIPSTEP2 EC2の設定
AWSでDBを利用したい場合、
・EC2にてインスタンスの作成 ・RDSを利用する ※ ただRDSを使用すると料金が掛かるので、 使用しない場合はサーバーに直接データベースを作成してください。この2種類の方法があります。
今回は
EC2にてインスタンスの作成(サーバーに直接データベースを作成)
をメインに行なっていきます1.EC2にてインスタンスの作成
インスタンスは起動のままだと
課金請求されるので、使わない場合は
停止状態にすることをお勧めしますAWS マネジメントコンソールにて"EC2"を検索しアクセスする
サイドメニューのインスタンスより[インスタンスの作成]を押下する
[次の手順: インスタンスの詳細の設定]をクリックする
下を設定し,[次の手順: ストレージの追加]を押下する
ネットワーク:先ほど作成したVPCを選択 サブネット:先ほど作成したサブネットを選択 自動割り当てパブリック IP:有効 他はデフォルトのままデフォルトのままで,[次の手順: タグの追加]を押下する
タグを追加する
キー:Name 値:testInstanceで[次の手順: セキュリティグループの設定]を押下する
セキュリティグループの設定する
セキュリティグループの割り当て:既存を
選択し、先ほど作成したセキュリティグループを選択し、
[確認と作成]を押下する
一覧画面にて、
最後に[起動]を押下します下ような表示になり、
新しいキーペアを作成を選択、
キーペア名を入力し、
[キーペアのダウンロード]を押下します
(一度作成されたファイルは再度ダウンロードができなくなるので注意)
ダウンロードしたら[インスタンスの作成]を押下します
しばらくするとインスタンスが作成されます!!
2.Elastic IPの割り当て
サイドメニューの
ネットワーク&セキュリティ>
Elastic IP[新しいアドレスの割り当て]を押下する[閉じる]で戻り
インスタンスを先ほど作成したものを選択し、[関連付け]を押下する
※停止していたインスタンスにElastic IPを関連付けたままにしていると小額の料金が発生してしまうので、
インスタンスを停止している場合は解放することをお勧めしますElastic IPをアタッチ(関連付け)しているインスタンスが起動している状態であれば、料金は発生しません。しかし、インスタンスが「停止」している状態や、Elastic IPを使っていない場合、料金が発生します。そのため、使わないElastic IPは削除しなければいけません。
Elastic IPがまだインスタンスにアタッチしている場合は、Elastic IPから該当のIPを選択し、「アクション」→「アドレスの関連付けの解除」をクリックします。確認画面が表示されますので、間違いなければ、「アドレスの関連付けの解除」をクリックし、EIPをデタッチします。
その後、再度該当のIPを選択し、「アクション」→「アドレスの解放」をクリックし、EIPを削除します。これで、料金が発生しなくなります。
3.インスタンスにSSHでログイン
各種インストール
python
$ brew install pythonpip(pythonのパッケージ管理システム)
$ easy_install pipawscli(awsをPCのコンソール上から扱うためのもの)
$ pip install awscliできない場合はこちら
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-macos.htmlec2-userでインスタンスにログインする
AWSでは、
EC2インスタンスにログインできるユーザーとして、
デフォルトでec2-userという名のユーザーが用意されています
こちらではまずec2-userでログインしますターミナルで以下を入れていきます
(※testKey.pemは、先ほどSTEP2でダウンロードしたキーです)$ mv Downloads/testKey.pem .ssh/ (#作成した公開鍵をsshフォルダに移動) $ cd .ssh/ (#ディレクトリをsshに移動) $ chmod 600 testKey.pem (#公開鍵に600番で定義されたアクセス権を付与する) $ ssh -i testKey.pem ec2-user@(@以降のURLは、作成したEC2インスタンスと紐付けたElastic IPを使用してください。) (#公開鍵を利用してec2-userとしてログイン) 例: ($ ssh -i testKey.pem ec2-user@13.112.140.56)yes/noを聞かれるので
無事にログインできました!!!
※
ssh port 22 Operation timed out
エラーになる場合はこちら
https://qiita.com/yokoto/items/338bd80262d9eefb152ehttps://qiita.com/minicoopers0716/items/cac50f29ef79a03f1d8d
ユーザー作成(EC2上での操作)
上記方法でインスタンスにログインしている状態で
[ec2-user|~]$ sudo adduser testuser (#新規ユーザー名の登録) [ec2-user|~]$ sudo passwd testuser (#新規ユーザー名のパスワード登録) パスワードを登録します
vimでユーザーに権限を追加する記述する$ sudo visudovimモードになります
## Allows people in group wheel to run all commands # %wheel ALL=(ALL) ALL ## Same thing without a password # %wheel ALL=(ALL) NOPASSWD: ALL ## Allows members of the users group to mount and unmount the ## cdrom as root # %users ALL=/sbin/mount /mnt/cdrom, /sbin/umount /mnt/cdrom ## Allows members of the users group to shutdown this system # %users localhost=/sbin/shutdown -h now検索モードにし下の
"wheel"を探します
(キーボードで"/wheel"を入力し押下、"N"を押下すると次にいけます)## Same thing without a password # %wheel ALL=(ALL) NOPASSWD: ALLキーボードの「i」を押下し、編集モードで
# %wheel ALL=(ALL) NOPASSWD: ALL
のコメントアウトを外します## Same thing without a password %wheel ALL=(ALL) NOPASSWD: ALLさらに
その下に、作成したユーザーに権限を追加する記述 testuser ALL=(ALL) ALL を追加する## Allow root to run any commands anywhere root ALL=(ALL) ALL testuser ALL=(ALL) ALLキーボードの「esc」を押下します
「:wq」を入力しEnterで保存しますこちらでユーザーの切り替えを行ってください。
[ec2-user|~]$ sudo su - testuser (#ユーザー名の切り替え) [testuser@ ~]無事に[ec2-user|がtestuser(作成したユーザー名)と切り替わればOKです。
exitを二回いれて
で一度ログアウトする追加ユーザ用キーペアを作成
こちらはローカルでの作業です
$ cd .ssh [.ssh]$ ssh-keygen -t rsa (#公開鍵を作成) ----------------------------- Enter file in which to save the key (): (#ここでファイルの名前を記述して、エンターを押す) test_key_rsa Enter passphrase (empty for no passphrase): (#何もせずそのままエンター) Enter same passphrase again: (#何もせずそのままエンター) ----------------------------- [.ssh]$ ls #「test_key_rsa」と「test_key_rsa.pub」が生成されたことを確認 [.ssh]$ vi config (#VIMを起動し、設定ファイルを編集する) ----------------------------- キーボードの「i」を押下し、編集モードで # 以下を追記 Host test_key_rsa Hostname 前出のElastic IP (#自分の設定に合わせて) Port 22 User testuser (#先ほどのユーザー名) IdentityFile ~/.ssh/test_key_rsa (#秘密鍵の設定) * ()部分は削除する。 ----------------------------- キーボードの「esc」を押下します 「:wq」で保存します [.ssh]$ cat test_key_rsa.pub (#鍵の中身をターミナル上に出力) ★ ssh-rsa~~~~localまでをコピーしておくサーバー側作業
続いてサーバーでの作業です
ec2-userでログインします$ cd .ssh $ ssh -i testKey.pem ec2-user@(@以降のURLは、作成したEC2インスタンスと紐付けたElastic IPを使用してください。) [ec2-user|~]$ sudo su - testuser [testuser@ ~]$ mkdir .ssh [testuser@ ~]$ chmod 700 .ssh [testuser@ ~]$ cd .ssh [testuser@ |.ssh~]$ vi authorized_keys (vimがオープンするので、「i」を押し、 先ほど ★ で、コピーしたssh-rsaをペーストする) キーボードの「esc」を押下します 「:wq」で保存します [testuser@ |.ssh~]$ chmod 600 authorized_keys $ exit もう一度 $ exit ログアウト[~]$ ssh test_key_rsaログインできれば、無事ユーザー設定は終了です。
なお、時間が経つとローカルからログインできなくなることがあるので、その場合は、 セキュリティグループ>インバウンド>編集で SSHのソースで マイIPを選択し[保存]すると繋がるようになります
- 投稿日:2020-01-07T19:34:09+09:00
railsでdeviseを使う手順
ユーザー登録の際に使える、deviseという便利なツール。
よく使うことが多いので、簡単な手順をまとめました。gemを入れる
まずはgemを入れます
gem 'devise'$ bundle installdeviseをインストールする
次にアプリケーション内にdeviseを読み込みます
$ rails g devise:installdeviseを使って、モデルを作成
今回はユーザーモデルを作ってみます
$ rails g model devise user必要な追加カラム等があれば、マイグレーションファイルを編集します
t.string :email, null: false, default: "" t.string :encrypted_password, null: false, default: "" #以下のように追加 t.string :name, null: false, default: ""その後、application_controllerを編集し、カラム追加を許可してもらいます
before_action :configure_permitted_parameters, if: :devise_controller? def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:name]) end #[:name]のところが、追加したいカラム名。複数指定の場合はカンマ区切りで記入必要なビューをダウンロード
新規登録ページやログインページなどのビューをダウンロードします
$ rails g devise:views特殊な処理が必要な場合はdevise用のコントローラーを生成する
$ rails g devise controller users
- 投稿日:2020-01-07T19:27:38+09:00
rails db:migrateでエラー(StandardError: An error has occurred, this and all later migrations canceled:)
$rails db:migrate、または、$rake db:migrateを行った後の謎のエラー。
== 20200107095832 CreateMicroposts: migrating ================================= -- create_table(:microposts) rails aborted! StandardError: An error has occurred, this and all later migrations canceled: SQLite3::SQLException: table "microposts" already exists: CREATE TABLE "microposts" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "content" text, "user_id" integer, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL) ・ ・以下つづく ・原因
『この前に行ったコマンドのmigrationで何らかの手違いがあると思います。おそらく、migration処理の途中からエラーが起きていて、テーブルは生成されているが、テーブルを生成したmigrationは未実行まま。といった状態なのかな?と思います。』
解決策
$ rake db:migrate:reset↑これで、データベースのリセットを行った後。
$ rake db:migrate↑もう一度!
直った!
これでオッケーかと❗️
このコマンドで、マイグレーションを順に実行し、データベースに変更を加えていくんですね。
- 投稿日:2020-01-07T19:09:22+09:00
【Rails】ブックマーク(お気に入り)機能
備忘録です。
掲示板におけるブックマーク機能追加し、ブックマーク一覧ページを作成。
※初学者です。ご指摘あればお願いします!環境
Rails 5.2.3
mysql 5.7.28
gem font-awesome-sass
gem Sorcery
→installしていない場合、後述のcurrent_userメソッドが使用できません。ER図
中間テーブル(Bookmark)使用。
中間テーブル...userとboardのidだけを保存するテーブル。
User:Board = 1:多
User:Bookmark = 1:多
Board:Bookmark = 1:多あくまでブックマーク機能実装の記事ですので、UserとBoardモデルはすでに作成されているものとして進行しますのでご注意ください。
実装
それでは実装していきます。
Bookmarkモデル作成
ターミナル$ rails g model Bookmark user:references board:references上記コマンドで
bookmark.rb(モデルファイル)とxxxxxxxx_create_bookmarks.rb(マイグレーションファイル)が作成されます。
referencesを指定することで外部キー制約がついてインデックスも貼られるので便利です。bookmark.rbbelongs_to :user belongs_to :board validates :user_id, uniqueness: { scope: :board_id } # 追加
uniqueness: trueでモデルレベルで一意性(ユニーク)を保ちます。
参照:Railsガイドバリデーションxxxxxxx_create_bookmarks.rbdef change create_table :bookmarks do |t| t.references :user, foreign_key: true, null: false t.references :board, foreign_key: true, null: false t.timestamps t.index [:user_id, :board_id], unique: true # 追加 end end
t.index [:user_id, :board_id], unique: trueと書き足してDBレベルで一意性(ユニーク)を保ちます。モデルとDB両方に一意性を保つことでより安全性が高まります。
ここでいう一意性とは1人のユーザーが同じ投稿を複数回bookmarkできないようにすることです。ターミナル$ rails db:migrate上記コマンド実行で中間テーブル完成!
UserモデルとBoardモデルのアソシエーション
user.rbclass User < ApplicationRecord has_many :boards, dependent: :destroy has_many :bookmarks, dependent: :destroy has_many :bookmark_boards, through: :bookmarks, source: :board end
dependent: :destroyでユーザーが削除されたとき、そのユーザーに関連する情報を削除するよう紐付けます。注目すべきは
has_many :bookmark_boards, through: :bookmarks, source: :boardです。
has many throughオプションでユーザーがブックマークした投稿を直接アソシエーションで取得できます。
後ほどboard_controller.rb実装時に使用しますので、覚えておいてください。
sourceでは参照するモデルを指定しています。board.rbclass Board < ApplicationRecord belongs_to :user has_many :bookmarks, dependent: :destroy # boardのお気に入り判定 → vies側で呼び出し def bookmark_by?(user) bookmarks.where(user_id: user.id).exists? end endこちらで注目するのは
def bookmark_by?(user) bookmarks.where(user_id: user.id).exists? endこのインスタンスメソッドです。
ここではbookmark_by?(user)というアクションを明記してcurrent_userに特定の投稿がブックマークされているかされていないかの判定をするメソッドを記述しています。後々記述しますが引数の
(user)にはcurrent_userが引き渡されています。インスタンスメソッド...インスタンスに使用するメソッド。
ルーティング設定
routes.rbresources :boards, shallow: true do resource :bookmarks, only: %i[create destroy] get :bookmarks, on: :collection endブックマーク一覧ページを
boards/bookmarksにルーティンングを設定したいのでcollectionオプションを使用します。
ネスト(入れ子)すると外部キーのboard_idを取得するのに容易になります。
また単数形のメソッドであるresourceとしたのはbookmarkのidが必要ないため。
shallowオプション
参照:resources を nest するときは shallow を使うと幸せになれるBookmarkコントローラー作成
ターミナル$ rails g controller bookmarks create destroy上記コマンドで
bookmarks_controller.rbが作成されます。bookmarks_controller.rbclass BookmarksController < ApplicationController def create bookmark = current_user.bookmarks.build(board_id: params[:board_id]) bookmark.save! redirect_to boards_path, success: t('.flash.bookmark') end def destroy current_user.bookmarks.find_by(board_id: params[:board_id]).destroy! redirect_to boards_path, success: t('.flash.not_bookmark') endここの記述でリクエストが送られた際のブックマーク機能を管理しています。
createbookmark = current_user.bookmarks.build(board_id: params[:board_id])ここでcurrent_userのBookmarkインスタンスを生成(buildはnewと同じ意味で、アソシエーションしながらインスタンスを作成するときに形式的に使用される模様)
createbookmark.save! redirect_to boards_path, success: t('.flash.bookmark')登録して、リダイレクト先を指定。
success以降はフラッシュメッセージ関連です。destroycurrent_user.bookmarks.find_by(board_id: params[:board_id]).destroy! redirect_to boards_path, success: t('.flash.not_bookmark')ここではブックマークしているユーザー情報を取得、ブックマークを解除して、リダイレクト先を指定。
destroyやsaveではなくdestroy!やsave!にしているのは条件分岐使わない場合は失敗したときに例外を発生させて処理を終了させるのがベターと見聞きしたのでこの記述にしています。boards_controller実装
boards_controller.rbdef index @boards = Board.all.includes(:user).recent end . . . def bookmarks @boards = current_user.bookmark_boards.includes(:user).recent end今回関係あるのはこの2つのアクションだけなので他は割愛します。
上から見ていきます。def index @boards = Board.all.includes(:user).recent end
indexアクションでは@boardsインスタンス変数にboardsテーブルから全てのデータを取得しています。
includesはn+1問題解消のため。
参照:Rails「N+1問題」超分かりやすい解説・解決方法【includesを使おう】
recentはScopeを用いて可読性を保つために記述しているもので、掲示板を降順で表示するためのオプションをモデルで設定しています。
今回は関係ないので削除しても問題ありません。def bookmarks @boards = current_user.bookmark_boards.includes(:user).recent end
bookmarksアクションでは@boardsインスタンス変数にログインしているユーザー(current_user)がブックマークしている全てのデータを取得しています。
current_user.bookmark_boardsこういう書き方でユーザーがブックマークしてる投稿を取得できるのは先ほどhas many throughでリレーションを組んだことによる効果です。ビュー実装
views/boards/index.html.erb<div class="row d-flex"> <%= render @boards %> </div>パーシャルを読み込んで
views/boards/_board.html.erb<% if current_user.own_board?(board) %> <div style='display: inline; float: right;'> <%= link_to icon('fas', 'pen'), edit_board_path(board), id: :"button-edit-#{board.id}" %> <%= link_to icon('fas', 'trash-alt'), board_path(board), id: :"button-delete-#{board.id}",method: :delete, data: { confirm: '削除してよろしいですか?' } %> </div> <% else %> <div style='display: inline; float: right;'> <%= render 'boards/bookmark_area', board: board %> </div> <% end %>
<% if current_user.own_board?(board) %>で投稿をログインユーザーか他ユーザーかを条件分岐させてます。
own_board?(board)は自身で作成したインスタンスメソッドなので、このままコピペしても動きません。
own_board?メソッド中身はこちら↓
[Rails]ログインidと投稿者が一致した時のみ編集・削除アイコンを表示させる条件式をモデルに書き出すviews/boards/_bookmark_area.html.erb<% if board.bookmark_by?(current_user) %> <%= render 'boards/bookmark', board: board %> <% else %> <%= render 'boards/unbookmark', board: board %> <% end %>
bookmark_by?は先ほどboard.rbで定義したブックマーク判定をするインスタンスメソッドです。引数はログインユーザーであるcurrent_userのインスタンスを引き渡しています。views/boards/_bookmark.html.erb<%= link_to icon('fas', 'star'), board_bookmarks_path(board.id), method: :delete, id: :"js-bookmark-button-for-board-#{board.id}" %>views/boards/_unbookmark.html.erb<%= link_to icon('far', 'star'), board_bookmarks_path(board.id), method: :post, id: :"js-bookmark-button-for-board-#{board.id}" %>参考記事
- 投稿日:2020-01-07T19:09:22+09:00
【Rails】Bookmark機能
備忘録です。
掲示板におけるブックマーク機能追加し、ブックマーク一覧ページを作成。
※初心者です。ご指摘あればお願いします!環境
Rails 5.2.3
mysql 5.7.28
gem font-awesome-sass
gem Sorcery
→installしていない場合、後述のcurrent_userメソッドが使用できません。ER図
中間テーブル(Bookmark)使用。
中間テーブル...userとboardのidだけを保存するテーブル。
User:Board = 1:多
User:Bookmark = 1:多
Board:Bookmark = 1:多あくまでブックマーク機能実装の記事ですので、UserとBoardモデルはすでに作成されているものとして進行しますのでご注意ください。
実装
それでは実装していきます。
Bookmarkモデル作成
ターミナル$ rails g model Bookmark user:references board:references上記コマンドで
bookmark.rb(モデルファイル)とxxxxxxxx_create_bookmarks.rb(マイグレーションファイル)が作成されます。
referencesを指定することで外部キー制約がついてインデックスも貼られるので便利です。bookmark.rbbelongs_to :user belongs_to :board validates :user_id, uniqueness: { scope: :board_id } # 追加
uniqueness: trueでモデルレベルで一意性(ユニーク)を保ちます。
Railsガイドバリデーションxxxxxxx_create_bookmarks.rbdef change create_table :bookmarks do |t| t.references :user, foreign_key: true, null: false t.references :board, foreign_key: true, null: false t.timestamps t.index [:user_id, :board_id], unique: true # 追加 end end
t.index [:user_id, :board_id], unique: trueと書き足してDBレベルで一意性(ユニーク)を保ちます。モデルとDB両方に一意性を保つことでより安全性が高まります。
ここでいう一意性とは1人のユーザーが同じ投稿を複数回bookmarkできないようにすることです。ターミナル$ rails db:migrate上記コマンド実行で中間テーブル完成!
UserモデルとBoardモデルのアソシエーション
user.rbclass User < ApplicationRecord has_many :boards, dependent: :destroy has_many :bookmarks, dependent: :destroy has_many :bookmark_boards, through: :bookmarks, source: :board end
dependent: :destroyでユーザーが削除されたとき、そのユーザーに関連する情報を削除するよう紐付けます。注目すべきは
has_many :bookmark_boards, through: :bookmarks, source: :boardです。
has many throughオプションでユーザーがブックマークした投稿を直接アソシエーションで取得できます。
後ほどboard_controller.rb実装時に使用しますので、覚えておいてください。
sourceでは参照するモデルを指定しています。board.rbclass Board < ApplicationRecord belongs_to :user has_many :bookmarks, dependent: :destroy # boardのお気に入り判定 → vies側で呼び出し def bookmark_by?(user) bookmarks.where(user_id: user.id).exists? end endこちらで注目するのは
def bookmark_by?(user) bookmarks.where(user_id: user.id).exists? endこのインスタンスメソッドです。
ここではbookmark_by?(user)というアクションを明記してcurrent_userに特定の投稿がブックマークされているかされていないかの判定をするメソッドを記述しています。後々記述しますが引数の
(user)にはcurrent_userが引き渡されています。インスタンスメソッド...インスタンスに使用するメソッド。
ルーティング設定
routes.rbresources :boards, shallow: true do resource :bookmarks, only: %i[create destroy] get :bookmarks, on: :collection endブックマーク一覧ページを
boards/bookmarksにルーティンングを設定したいのでcollectionオプションを使用します。
ネスト(入れ子)すると外部キーのboard_idを取得するのに容易になります。
また単数形のメソッドであるresourceとしたのはbookmarkのidが必要ないため。
shallowオプションについてはこちら
resources を nest するときは shallow を使うと幸せになれるBookmarkコントローラー作成
ターミナル$ rails g controller bookmarks create destroy上記コマンドで
bookmarks_controller.rbが作成されます。bookmarks_controller.rbclass BookmarksController < ApplicationController def create bookmark = current_user.bookmarks.build(board_id: params[:board_id]) bookmark.save! redirect_to boards_path, success: t('.flash.bookmark') end def destroy current_user.bookmarks.find_by(board_id: params[:board_id]).destroy! redirect_to boards_path, success: t('.flash.not_bookmark') endここの記述でリクエストが送られた際のブックマーク機能を管理しています。
createbookmark = current_user.bookmarks.build(board_id: params[:board_id])ここでcurrent_userのBookmarkインスタンスを生成(buildはnewと同じ意味で、アソシエーションしながらインスタンスを作成するときに形式的に使用される模様)
createbookmark.save! redirect_to boards_path, success: t('.flash.bookmark')登録して、リダイレクト先を指定。
success以降はフラッシュメッセージ関連です。destroycurrent_user.bookmarks.find_by(board_id: params[:board_id]).destroy! redirect_to boards_path, success: t('.flash.not_bookmark')ここではブックマークしているユーザー情報を取得、ブックマークを解除して、リダイレクト先を指定。
destroyやsaveではなくdestroy!やsave!にしているのは条件分岐使わない場合は失敗したときに例外を発生させて処理を終了させるのがベターと見聞きしたのでこの記述にしています。boards_controller実装
boards_controller.rbdef index @boards = Board.all.includes(:user).recent end . . . def bookmarks @boards = current_user.bookmark_boards.includes(:user).recent end今回関係あるのはこの2つのアクションだけなので他は割愛します。
上から見ていきます。def index @boards = Board.all.includes(:user).recent end
indexアクションでは@boardsインスタンス変数にboardsテーブルから全てのデータを取得しています。
includesはn+1問題解消のため。
Rails「N+1問題」超分かりやすい解説・解決方法【includesを使おう】
recentはScopeを用いて可読性を保つために記述しているもので、掲示板を降順で表示するためのオプションをモデルで設定しています。
今回は関係ないので削除しても問題ありません。def bookmarks @boards = current_user.bookmark_boards.includes(:user).recent end
bookmarksアクションでは@boardsインスタンス変数にログインしているユーザー(current_user)がブックマークしている全てのデータを取得しています。
current_user.bookmark_boardsこういう書き方でユーザーがブックマークしてる投稿を取得できるのは先ほどhas many throughでリレーションを組んだことによる効果です。ビュー実装
views/boards/index.html.erb<div class="row d-flex"> <%= render @boards %> </div>パーシャルを読み込んで
views/boards/_board.html.erb<% if current_user.own_board?(board) %> <div style='display: inline; float: right;'> <%= link_to icon('fas', 'pen'), edit_board_path(board), id: :"button-edit-#{board.id}" %> <%= link_to icon('fas', 'trash-alt'), board_path(board), id: :"button-delete-#{board.id}",method: :delete, data: { confirm: '削除してよろしいですか?' } %> </div> <% else %> <div style='display: inline; float: right;'> <%= render 'boards/bookmark_area', board: board %> </div> <% end %>
<% if current_user.own_board?(board) %>で投稿をログインユーザーか他ユーザーかを条件分岐させてます。
own_board?(board)は自身で作成したインスタンスメソッドなので、このままコピペしても動きません。
<% current_user == board.board.id %>で上記判断ができると思います。views/boards/_bookmark_area.html.erb<% if board.bookmark_by?(current_user) %> <%= render 'boards/bookmark', board: board %> <% else %> <%= render 'boards/unbookmark', board: board %> <% end %>
bookmark_by?は先ほどboard.rbで定義したブックマーク判定をするインスタンスメソッドです。引数はログインユーザーであるcurrent_userのインスタンスを引き渡しています。views/boards/_bookmark.html.erb<%= link_to icon('fas', 'star'), board_bookmarks_path(board.id), method: :delete, id: :"js-bookmark-button-for-board-#{board.id}" %>views/boards/_unbookmark.html.erb<%= link_to icon('far', 'star'), board_bookmarks_path(board.id), method: :post, id: :"js-bookmark-button-for-board-#{board.id}" %>参考記事
- 投稿日:2020-01-07T19:02:19+09:00
Linuxサーバからリモートリポジトリにpush & リモートリポジトリからローカルPCにclone
目標
- linuxサーバ上で運用されているrailsアプリのソースコードをGitlab.comのリモートリポジトリにプッシュする。
- リモートリポジトリからローカルPCのローカルリポジトリにクローンする。
環境
- linux(GCE, Debian)
- Gitlab.com
- Mac(OSX 10.15.2)
準備:git install (linuxサーバ、ローカルPCにGitをインストール)
下記サイトなどを参考にしてください。
https://git-scm.com/book/ja/v2/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-Git%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB1. linuxの操作
git config(USER_NAMEとEMAILは環境による)
ターミナルgit config --list git config --global user.name "USER_NAME" git config --global user.email "EMAIL"ファイル権限(USERNAMEとUSERGROUPは環境による)
権限を間違えるとgit push時に権限エラーになります。
ターミナルsudo chown -R USERNAME:USERGROUP ./ sudo find ./ -type d -exec chmod 755 {} + sudo find ./ -type f -exec chmod 644 {} +SSH鍵(gitlab_rsaは好きな名前をつける)
- 秘密鍵は~/.ssh/に置いてください。
- .pubの内容をGitlab.comのユーザーのssh鍵に貼り付けてください。
ターミナルssh-keygen -t rsa -f gitlab_rsa mv ./gitlab_rsa ~/.ssh/ mv ./gitlab_rsa.pub ~/.ssh/ cat gitlab_rsa.pub =>.pubの内容をGitlab.comに貼り付け eval $(ssh-agent -s) ssh-add ~/.ssh/gitlab_rsa ssh -T git@gitlab.comgit init ~ git pushまで(:repoは環境による)
gitコマンドの詳細の説明は省略します。
サーバのローカルリポジトリを初期化+初期コミットして、リモートリポジトリにプッシュしています。ターミナルgit init vi .gitignore =>rails用のテンプレートから持ってくるとラク git add . git commit . git remote add origin git@gitlab.com:repo git push origin master2. ローカルPC操作
プロジェクト用ディレクトリ作成(好きな名前のディレクトリを作成する)
ターミナルmkdir GitlabSSH鍵(gitlab_rsa_userは好きな名前をつける)
- 秘密鍵は~/.ssh/に置いてください。
- .pubの内容をGitlab.comのユーザーのssh鍵に貼り付けてください。
ターミナルssh-keygen -t rsa -f gitlab_rsa_user mv gitlab_rsa_user ~/.ssh/ mv gitlab_rsa_user.pub ~/.ssh/ cat gitlab_rsa_user.pub =>Gitlabに貼り付け eval $(ssh-agent -s) ssh-add ~/.ssh/gitlab_rsa_user ssh -T git@gitlab.comgit config(USERNAMEとEMAILは環境による)
リモートリポジトリからローカルPCのローカルリポジトリにクローンしています。
ターミナルgit config --global user.name "USERNAME" git config --global user.email EMAILgit clone(/repo.gitは環境による)
ターミナルgit clone https://gitlab.com/repo.gitbundle ~ rails sまで
ローカルPCにクローンしてきたディレクトリでbundleとrails sが実行可能か確認する。
サーバ環境と同じrubyバージョン、railsバージョンで実行すると環境依存のエラーを回避できる。
rbenvを使用するとプロジェクトディレクトリ毎にrubyバージョンを指定できるのでラク。
windowsでrbenvを使用する場合は、wslを有効化してubuntuターミナル上で作業する。
参考:
https://qiita.com/chimame/items/8130aa2c07a152a865b1エラーが出たらエラーメッセージを読んで不足するファイルをサーバから直接持ってくる。
(.gitignoreで指定したファイルはgit管理から外れるため。)ターミナルbundle rails s
- 投稿日:2020-01-07T18:23:09+09:00
application_helperを使う
長くてみにくかったviewの記述を
application_helper.rbに移動させてcontent_tagと言うものを使ってhtmlタグを生成する
content_tagについて
参考: https://qiita.com/yusaku_/items/d6e98b77124131e628fbrails/app/helpers/try_helper.rbdef discount_text(service, provider) discount_price = provider.key == "noe-jx-group" ? service['discount'].to_f : service['discount'].to_i discount_from_energy = if SetPlan.is_discount_from_energy?(service) "/kWh" elsif SetPlan.yearly?(service) "/年" elsif SetPlan.monthly?(service) "/月" end content_tag(:div, class: "e__saving") do content_tag(:span, "割引額", class: "e__tag") + content_tag(:span, discount_price, class: "e__number e__deals" ) + "円" + discount_from_energy end endrails/app/views/try/_set_discount.html.erb// 修正前 <div class="e__saving"><span class="e__tag">割引額</span><span class="e__number e__deals"><%= service['discount'].to_i %></span>円<% if SetPlan.is_discount_from_energy?(service) %>/kWh<% elsif SetPlan.monthly?(service) %>/月<% elsif SetPlan.yearly?(service) %>/年<% end %></div> // 修正後(とっても短くなった!) <%= discount_text(service, @provider) %>
- 投稿日:2020-01-07T17:42:03+09:00
【学習まとめ】 Railsアプリケーションのテスト
なぜテストですか。
ソフトウェア開発の仕事は、機能しているコードを書くことと思います。
問題は、正確さをどうやって確保できるのか
一つの方法は、コードを書いた後で、実行してみます。この方法は、小さいプロジェクトに対して効果がありますが、ある時点で機能が多すぎて追跡できません。新しいコード(フィーチャー)を追加すると、他のコードが予期せず壊れてしまいます。これは、
regression(リグレックション)と呼ばれています。より良い方法があり、自動テストです。コードで作成したコードを自動的にテストしてもらいます。自動テストは、私たちのプログラムが機能していること、そして今後も機能して続いていることを確認します。
お金や時間の節約
自動テストは、バグをより早く発現し、本番に不正な状態を展開されるのを防ぎます。
コードに自信がある
良いテストがあると、
何か壊すことを恐れことなく、コードに大きな変更を加えることができます。
金曜日の午後でも、リリースする自信があります。より良いドキュメント
ドキュメントは、コードを更新するとフルいくなります。テストは、いつもコードによって更新しなければならないものである。
TDD(テスト駆動開発)
TDDは、テストを利用してアプリケーションの設計や開発の推進するプロセスである。
Red, Green, Refactorと呼ばれているサイクルから始めます。Red
最初に、適用する予定のメソッドやロジックのテストを先に書きます。この時点でコードはどのように見えるかを知る必要がありません、それが何をするかを知るだけで十分です。
テストを実行すると、失敗するはずです。(テストがRed色になります)
Green
失敗するテストから、エラーメッセじを読んで、コードを書きます。この時点、テストを合格するのに十分なコードを書くだけです。コードの品質に焦点を合わせなくていいです。
Refactor
コードをクリーンニングし、複数なコードを削除する。アプリケーションのコードではなくテストコードもします。
コードに何か変更しても壊れない自信があるまでします。
TDDアプローチ
Outside-In Development
アウトサイド ・イン開発は、最初は最高レベルアブストラクション(抽象化)から始めます。というのは、ユーザがブラウザ(UI)を操作し、ページ上の要素と対話する観点である。これは、受け入れテストと呼ばれています。
受け入れテストが緑色になったら、よりコードを記述する必要はありません。
Inside-Out Development
時々、最終のソリューションがどのように見えるかわからない場合、インサイド・アウト開発はお勧めします。コンポーネントごとを構築します。
テスト駆動とテストファースト
最初にテストを書くだけで、テスト駆動と呼ばれているのは違います。
赤、緑、リファクタリングのサイクルに沿って、失敗テストに対して必要なコードのみを記述することは重要です。これにより、ソリューションのスコープ外の設計、テストされていない機能を実装しなくなります。
また、リファクタリングのスッテプをスキップしないことも重要です。これは、TDDの最も重要な部分の一つであります、コードを保守しやすく、将来変更しやすいくようにします。
TDDの利点
- Confidence(自信)
- Time Savings(時間節約)
- Flow(フロー)
- Improved Design(設計の改善)
TDDしない時(実用的)
- アプリケーションが小さい、変更が少ない(ほとんどない)
- 短い時間で利用するつもりであるプログラム
- アプリケーションの重要性が低い、壊れても影響がない
効果的なテストスイートの特性
- 速度 (speed)
- 完成度 (complete)
- 信頼性ある (reliable)
- 孤立 (isolated)
- 保守可能 (maintainable)
テストタイプ
Refs
testing-rails/testing-rails.md at master · thoughtbot/testing-rails · GitHub
- 投稿日:2020-01-07T16:20:39+09:00
Pay.jpとRailsで決済機能実装してみた。
投稿経緯
payjpの実装記事そのものはたくさんあるのですが、hamlで書かれてるのがほとんど。
正直僕はまだslimやhamlのような短縮系での書き方がわからず手間取ったので、今回通常盤での記載で投稿しようと思いました。実装
APIキー取得
1. Payjpにログイン
https://pay.jp/login
※アカウントがなければ↑からも作成可能。2. ログイン後APIをクリック
クリック後が写真の画面になります。
大事な情報になるので、基本的には第三者に見せないようにしましょう。gemの導入
1.Gemfileに記載する。
Gemfile# 決済 gem 'payjp'2.インストール
ターミナルbundle installコントローラー
1.決済情報アクションを作成
pays.controller.rbdef index end def pay Payjp.api_key = 'sk_test_c6a7dfaf173ad9733cd904e9' Payjp::Charge.create( #amountは値段を記載 amount: 3500, card: params['payjp-token'], currency: 'jpy' ) endActionController::InvalidAuthenticityTokenが出た場合
protect_from_forgery except: :payを一番上に記載してください。
有効ではないトークンみたいな感じで弾いてしまうみたいなので、
例外としてpayアクションを指定して通すようにします。pays.controller.rbprotect_from_forgery except: :pay def index end def pay Payjp.api_key = 'sk_test_c6a7dfaf173ad9733cd904e9' Payjp::Charge.create( #amountは値段を記載 amount: 3500, card: params['payjp-token'], currency: 'jpy' ) endView
1.Payjoが用意しているUIを使用する
data-keyの箇所は先ほどのPayjpのAPIに記載されいるものを入れる。
※今回は簡単な導入方法になりますので、セキュリティー面では直かきはよくないみたいなので、本番でやる場合は違う場所書いて参照するようにお願いします。index.html.erb<h1>決済画面</h1> <form action="/pay" method="post"> <script src="https://checkout.pay.jp/" class="payjp-button" data-key="テスト公開鍵"></script> </form>2.トークン
トークンを作成するために必要なものになりますので、indexの一番下に書きます。
index.html.erb<script> $(document).on('turbolinks:load', function() { var form = $("#charge-form"); Payjp.setPublicKey('pk_test_0383a1b8f91e8a6e3ea0e2a9'); $("#charge-form").on("click", "#submit-button", function(e) { e.preventDefault(); form.find("input[type=submit]").prop("disabled", true); var card = { number: parseInt($("#payment_card_no").val()), cvc: parseInt($("#payment_card_security_code").val()), exp_month: parseInt($("#payment_card_expire_mm").val()), exp_year: parseInt($("#payment_card_expire_yy").val()) }; Payjp.createToken(card, function(s, response) { if (response.error) { alert("error") form.find('button').prop('disabled', false); } else { $(".number").removeAttr("name"); $(".cvc").removeAttr("name"); $(".exp_month").removeAttr("name"); $(".exp_year").removeAttr("name"); var token = response.id; $("#charge-form").append($('<input type="hidden" name="payjp_token" class="payjp-token" />').val(token)); $("#charge-form").get(0).submit(); } }); }); }); </script>ルーティング
今回はわかりやすく/payだけのURLで作成します。
変更する場合はindex.html.erbのformのaction="~"で場所を買えてくださいconfig/routes.rbpost '/pay', to: 'pays#pay'完成
index.html.erbにカードで支払うボタンが出てるのそれをクリック
すると入力フォームが出現しますので、記入してカードで支払うボタンをクリックすると元のページへリダイレクトするので、次はpayjpに移動
サイドバーの売上をクリックすると
先ほどの金額で支払済みと確認できましたね。まとめ
今回はかなり簡略的に書きましたので、これをもとに各々に合わせた形にアレンジしていっていただけたらと思いまいす。
- 投稿日:2020-01-07T15:44:05+09:00
画像ファイルについてしまった[ ]を取り除く
はじめに
画像ファイルを複数登録するときに、multipleを使うと簡単に実装できます。
が、(自分の環境だけなのか)保存されるデータに含まれる画像ファイル名に
[ ]がついてしまい、実際に保存されている画像ファイル名を齟齬が生じ
エラーとなる自体が発生していました。
そこで、Model側にこれを取り除くメソッドを追加しましたが、同じような環境で
困っている方はご利用ください
最近、某プログラミングスクールではこれの影響なのかmultipleを使わないようにと
御達しが出たようですね。前提条件
ItemモデルはImagesを複数持つアソシエーションが組まれていること
コード
app/models/image.rbclass Image < ApplicationRecord belongs_to :item, optional: true validates_presence_of :item mount_uploaders :image_url, ImageUploader def image_path return '' if self.image_url[0].try(:file).nil? if Rails.env.production? self.image_url[0].url.gsub(/%5B%22/, "").gsub(/%22%5D/, "") else self.image_url[0].file.file.sub(/.*public/,'').sub(/\["/,'').sub(/"\]/,'') end end end今回はS3に画像を保存するようにしており、本番環境とローカルでは指定する画像パスが異なってくるので
production?を使って分岐させています。使い方
app/controllers/items_controller.rbdef show @item = Item.find_by(id: params[:id]) @image_path = @item.images.map{|img| img.image_path} endparamsで渡されたidのアイテムを@itemに格納し、@itemのimagesに対して
modelで作成したimage_pathメソッドを実行して[ ]を削除したパスを@image_pathに
格納して使えるようにします。
あとはビュー側でimage_tagに@image_path[n]とすれば格納したパスを
取り出すことができます。@image_pathは配列になっていることに注意です。おわりに
細かいことですが、私は最初Controllerに[ ]を取り除く処理を書いていましたが、メンバーが
MVCモデルの法則に則ってModelにメソッドを書き直してくれました。
開発の基準をしっかりと把握していないと他のメンバーに迷惑をかけてしまいますね・・・猛省
- 投稿日:2020-01-07T15:27:01+09:00
haml-railsでerbファイルをhamlに変換する方法
個人アプリ開発において新しく立ち上げる度に何度も調べてしまうので備忘録として残す。
結論
このgemをGemfileに記述
Gemfilegem "haml-rails"bundle installを実行
ターミナル$ bundle install #bundle でも可下記コマンドを実行し、erbファイルをhamlに変換。
ターミナル$ rails haml:erb2haml元のerbファイルを削除するかどうかを聞かれる。不要な場合はyを選択。
ターミナルWould you like to delete the original .erb files? (This is not recommended unless you are under version control.) (y/n) y Deleting original .erb files. -------------------------------------------------------------------------------- Task complete! No .erb files found. Task will now exit.hamlで開発を行う事の利点とは
hamlはdivタグ自体を書く必要がなく、また各タグを閉じる必要もない為、コード量の削減、簡略化ができる。rubyも使用可。
インデントによる管理である事から、誰が書いても似たような構造になり、可読性が高い。
逆にインデントが少しでもずれるとすぐエラーを吐くため慣れるまでが大変。rails newを叩く際にデフォルトで生成されるerbファイルはhtmlとほとんど同じ記述で書けて且つ、rubyも実行できる。
ただhamlと違いタグ1つ1つに対しての閉じタグが必要になる為、コードが冗長になりやすい。
学習し始めのうちは視覚的に理解しやすいので使うのも有り。まとめ
爆速で開発を行いたいのであれば時間が掛かっても少しずつhamlに慣れていくのが良いであろう。
似たような書き方でslimというのもあるが、基本的な書き方はhamlと変わらず、2020年1月現在ではhamlの方が若干使用比率が高いようなので、現場に合わせ必要に応じて学ぶと良いのではないだろうか。
- 投稿日:2020-01-07T14:34:23+09:00
【Rails】resourcesメソッド
config/routes.rbRails.application.routes.draw do # 追記する resources :blogs end
$ rails routesPrefix Verb URI Pattern Controller#Action blogs GET /blogs(.:format) blogs#index POST /blogs(.:format) blogs#create new_blog GET /blogs/new(.:format) blogs#new edit_blog GET /blogs/:id/edit(.:format) blogs#edit blog GET /blogs/:id(.:format) blogs#show PATCH /blogs/:id(.:format) blogs#update PUT /blogs/:id(.:format) blogs#update DELETE /blogs/:id(.:format) blogs#destroy
- 投稿日:2020-01-07T12:53:38+09:00
Mix-inはやめてくれ。「関数的モジュール」だ!
TL;DR
- Mix-inは危険な機能だ
- Mix-inは必要なシーンにだけ使おう
- 関数だけを提供するだけのモジュールを作るのが、弊害が少なくシンプル
Mix-in は弊害が多い
Mix-inはRubyの基本的な機能であり、入門書でも序盤で紹介されます。
それゆえか単に処理をクラス間で共有するためだけにMix-inを使おうとしているのをしばしば見かけます。
実際には、Mix-inにはうかつに使うと後々痛い目に会う機能であり、大抵のケースではMix-inを使うのは適切ではありません。
落とし穴1: インスタンス変数やメソッドが上書きされる
includeがやっているのは、「単にMix-inのメソッドをクラスにコピーする」ことだけです1。なので同じ名前のメソッドをクラス側で定義すると、Mix-inのメソッドを警告なしに上書きしてしまいます。同様にMix-inのインスタンス変数を、クラス側で参照したり変更したりできてしまいます。
module HttpRequestable def get(uri) request(:get, uri) end private def request(http_method, uri) # HTTPリクエストする処理 end end class StoreAPI include HttpRequestable ... # 商品の入荷をリクエストする機能を追加しよう! # (実はHttpRequestableのメソッドを上書きしてしまっている) def request(product_id, count) end end落とし穴2: メソッドの関係が複雑になる
クラスからMix-inのメソッドを呼び出せるだけでなく、Mix-inからクラスのメソッドを呼び出したり、Mix-inから別のMix-inのメソッドを呼び出すことができるため、
クラスのメソッド => Mix-in Aのメソッド => Mix-in Bのメソッド => クラスのメソッド => ...のような複雑な参照関係が生じてしまうことがあります。
呼び出しが適切に管理されていればTemplate Method パターンと呼べるのですが、
おっ、親クラスの〇〇っていうメソッドを呼べば動かせるぞ。よし!!
と、深く考えずに呼んでしまうことが、稀によくあります。
落とし穴3: メソッドの定義場所が分かりにくい
最近はIDEが良くなったので問題になりにくいのですが、includeするモジュールが増えてくると、メソッドの定義箇所がわかりにくくなりがちです。
RailsのActionMailer::Baseには12個のモジュールがincludeされているのですが、この中から
relative_url_rootの定義箇所をIDEなしで見つけるのは一苦労です。落とし穴4: 確信が持てない
最大の問題は、上記のような落とし穴を踏んでいないか確信を持てないことです。Rubyは動的言語なので、静的なチェックが難しく、
これは private メソッドだから、変更しても安全だな!!
と思っていたら、実はMix-inで誤って呼び出していないとも限らないのです。
そこで「関数的モジュール」
(以下の「関数的モジュール」は私の造語です。もっと適切な用語があるのかもしれませんが、調べ方が悪いのか見つからなかったので、ここでは「関数的モジュール」と呼びます)
関数的モジュールとは、特異メソッドだけを提供するモジュールのことです。
module HttpRequestable class << self def get(uri) request(:get, uri) end private def request(http_method, uri) # HTTPリクエストする処理 end end end使うときは、includeせずメソッドを直接呼び出します。
class StoreApi # メソッド名が被っても大丈夫!! def request HttpRequestable.get(uri) end end関数的モジュールでは、Mix-inのような問題は起きません。
- インスタンス変数を使わない(使えない2)
- メソッドがコピーされることが無い
- クラス側のメソッドを呼び出すことがない(できない)
- どのモジュールのメソッドを呼んでいるかは明らか
それでもMix-in を使うケース
そうはいっても、Mix-inを定義するのが便利なケースもあります。
Mix-inを定義する際にはTemplate Method パターンとして正しく定義することを心がけましょう。
具体的には・・・
- Mix-inがクラスのどのメソッドを呼ぶか明らかにする
- クラスからはMix-inのどのメソッドを呼んでよいのか明らかにする
- インスタンス変数を避ける
- privateメソッドを避ける(RubyのprivateはC++やJavaのprivateと異なることに気をつける)
- 投稿日:2020-01-07T11:44:18+09:00
Deviseを使ってController側からログアウトさせる
1. 経緯
userテーブルにflgを持たせて、0以外の人はログインさせたくないなぁ・・・
ということで調べてみたところ以下の内容でできました2. 結果
appllication_controller.rbbefore_action :sign_out_user, if: :user_signed_in? protected # ログイン後のパス def after_sign_in_path_for(resource) root_path end # flgが0以外はログアウトさせる def sign_out_user sign_out_and_redirect(current_user) if current_user.flg == 0 end3. 詳しい内容
after_sign_in_path_for
ユーザーがログイン後、どこに飛ばすか
https://rubydoc.info/search/github/plataformatec/devise/master?q=after_sign_in_path_forsign_out_and_redirect
ユーザーがログイン後、ログアウトさせる
https://rubydoc.info/github/plataformatec/devise/master/Devise%2FControllers%2FHelpers:sign_out_and_redirect4. ネットの記事
ネットの記事見てると以下の内容とかもあったんですが、サインアウトはHTTPリクエストからしか
受け付けないみたいで以下の書き方をしてもダメでした・・・。redirect_to :controller=>"user/sessions", :action=>"destroy"4. 最後に
いいね!もらえると励みになるのでよろしくお願いします!
- 投稿日:2020-01-07T10:59:36+09:00
emun のform select対応 実際に使えたもの
上記ものもを日本語対応させたい場合、下のように書く
<%= form.select :status, Post.statuses.keys,class:"form-control" %><%= form.select :status, Post.statuses.keys.map {|k| [I18n.t("enums.post.status.#{k}"), k]} ,class:"form-control" %>
- 投稿日:2020-01-07T10:21:55+09:00
条件付きバリデーション(特定の状況においてバリデーションを発生させる方法)
実現したいこと
PostモデルのFormにてGenreモデルのnameはuniquenessかつnameは空でもバリデーションに引っかからないようにしたい。そして空のデータは表示させたくない。
整理すると、
1. カラムはuniqueness、しかしカラムが空であった場合でもデータ送信ができる。
2. 空の状態を保存したものは出現させない。課題
カラムが空であった場合データ送信ができる=空の場合uniquenessのバリデーションには引っかからないようにする。解決策
条件付きバリデーションを作成する前提
新規投稿を作るformに置いてPostモデルとGenreモデルの2つのデータ送信を同時に行いたい。
Formの一部(ここでPostモデルのFormでGenreモデルのデータも同時に送信)
<%= fields_for @genre, :genres do |form| %> <%= form.label :新しくジャンルを作る %> <%= form.text_field :name, class:"form-control" %> <% end %>Form全体
<div class="container"> <%= form_with(model: [:mypage, post], local: true) do |form| %> <% if post.errors.any? %> <div id="error_explanation"> <h2><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h2> <ul> <% post.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> </div> <% end %> <div class="form-group"> <%= form.text_field :title, class:"form-control", placeholder:"タイトル" %> </div > <div class="form-group"> <%= form.text_area :body, class:"form-control", placeholder:"自分の辞書をマークダウン記法で記入してみよう" %> </div> <div class="field"> <%= form.label :status %> <%= form.select :status, Post.statuses.keys,class:"form-control" %> </div> <div class="field"> <%= form.label :posted_at %> <%= form.datetime_select :posted_at %> </div> <div class="form-group"> <%= form.text_area :reason, class:"form-control", placeholder:"メモした経緯を書いてみよう" %> </div> <div class="field"> <%= form.label :rank %> <%= form.select :rank, Post.ranks.keys, class:"form-control" %> </div> <div class="form-group"> <%= form.label :summary %> <%= form.text_field :summary, class:"form-control" %> </div> <div class="form-group"> <%= form.label :URL %> <%= form.text_field :url, class:"form-control" %> </div> <%= form.label :genre, 'ジャンル' %> <%= form.collection_check_boxes(:genre_ids, current_user.genres.where.not(name:""), :id, :name) do |genre| %> <%= genre.label do %> <%= genre.check_box %> <%= genre.text %> <% end %> <% end %><br> <%= fields_for @genre, :genres do |form| %> <%= form.label :新しくジャンルを作る %> <%= form.text_field :name, class:"form-control" %> <% end %> <div class="actions"> <%= form.submit class:"btn btn-info" %> </div> <% end %> </div>Genreモデルでの条件付きバリデーションの作成
これによってから以外でuniquenessが発動するようになったvalidates :name, uniqueness: true, unless: :name_check? def name_check? return true if self.name == "" end空は表示させない
where.not<%= form.collection_check_boxes(:genre_ids, current_user.genres.where.not(name:""), :id, :name) do |genre| %>
- 投稿日:2020-01-07T09:28:00+09:00
ruby: 個人でよく使うtrue falseを返す正規表現の書き方
※備忘録
半角小文字の英文字かどうかを判定
/\A[a-z]+\z/.match?("kaye") => true半角大文字の英文字かどうかを判定
/\A[A-Z]+\z/.match?("KAYE") => true半角数字かどうかを判定
/\A[0-9]+\z/.match?("21") => true半角英文字と半角数字かどうかを判定
/\A[a-zA-Z0-9]+\z/.match?("kayeN21") => true半角英文字と半角数字かどうかを判定
/\A[a-zA-Z0-9]+\z/.match?("kayeN21") => true半角英文字と半角数字と特定の記号のみを許容する判定
/\A[a-z0-9[.][_]]+\z/.match?("kaye.nr") => true適宜暇なときに追記していきます。
なお、こんな書き方の方がいいよとかがあればご教示いただけると嬉しいです。
- 投稿日:2020-01-07T05:38:09+09:00
serverが起動せず"Usage: rails new APP_PATH [options]..."となってしまう場合の解決法[Ruby on Rails]
経緯
私がRailsの環境を構築する際「Rails s」でサーバーが起動しなかったが解決に至ったためここに記載したいと思う。
投稿に至った経緯は以下の通り。
Web上で私と同じように悩んでいる方が多く、またほとんどの記事において解決に至っていなかったため。
該当する記事がそうないように感じたため。
同じ状況に陥っている同志の助けになりたいと考えたため。
陥った状況
- 前提として使用OSは Windows10
- コマンドプロンプトで
rails sを実行すると「Usage: rails new APP_PATH [options] ...(以下省略)」が表示されてサーバが起動できていない。- Ruby、SQLite、Ruby on Railsはインストールされている。
rails new プロジェクト名を実行済み ( 新しいrailsプロジェクトを生成するコマンド )cd プロジェクト名を実行済み ( プロジェクトのrootに移動するコマンド )詳細な状況
- 本来は
rails sを実行した際、下記のようになればよい。C:¥Users¥leone> rails s => Booting Puma => Rails 5.2.4.1 application starting in development => Run `rails server -h` for more startup options *** SIGUSR2 not implemented, signal based restart unavailable! *** SIGUSR1 not implemented, signal based restart unavailable! *** SIGHUP not implemented, signal based logs reopening unavailable! Puma starting in single mode... * Version 3.12.2 (ruby 2.6.4-p104), codename: Llamas in Pajamas * Min threads: 5, max threads: 5 * Environment: development * Listening on tcp://localhost:3000 Use Ctrl-C to stop
- しかし問題の状態では下記のようになってしまう。
C:¥Users¥leone> rails s Usage: rails new APP_PATH [options] Options: [--skip-namespace], [--no-skip-namespace] # Skip namespace (affects only isolated applications) -r, [--ruby=PATH] # Path to the Ruby binary of your choice # Default: C:/Ruby26-x64/bin/ruby.exe -m, [--template=TEMPLATE] # Path to some application template (can be a filesystem path or URL) -d, [--database=DATABASE] # Preconfigure for selected database (options: mysql/postgresql/sqlite3/oracle/frontbase/ibm_db/sqlserver/jdbcmysql/jdbcsqlite3/jdbcpostgresql/jdbc) # Default: sqlite3 [--skip-yarn], [--no-skip-yarn] # Don't use Yarn for managing JavaScript dependencies [--skip-gemfile], [--no-skip-gemfile] # Don't create a Gemfile -G, [--skip-git], [--no-skip-git] # Skip .gitignore file [--skip-keeps], [--no-skip-keeps] # Skip source control .keep files -M, [--skip-action-mailer], [--no-skip-action-mailer] # Skip Action Mailer files -O, [--skip-active-record], [--no-skip-active-record] # Skip Active Record files [--skip-active-storage], [--no-skip-active-storage] # Skip Active Storage files -P, [--skip-puma], [--no-skip-puma] # Skip Puma related files -C, [--skip-action-cable], [--no-skip-action-cable] # Skip Action Cable files -S, [--skip-sprockets], [--no-skip-sprockets] # Skip Sprockets files [--skip-spring], [--no-skip-spring] # Don't install Spring application preloader [--skip-listen], [--no-skip-listen] # Don't generate configuration that depends on the listen gem [--skip-coffee], [--no-skip-coffee] # Don't use CoffeeScript -J, [--skip-javascript], [--no-skip-javascript] # Skip JavaScript files [--skip-turbolinks], [--no-skip-turbolinks] # Skip turbolinks gem -T, [--skip-test], [--no-skip-test] # Skip test files [--skip-system-test], [--no-skip-system-test] # Skip system test files [--skip-bootsnap], [--no-skip-bootsnap] # Skip bootsnap gem [--dev], [--no-dev] # Setup the application with Gemfile pointing to your Rails checkout [--edge], [--no-edge] # Setup the application with Gemfile pointing to Rails repository [--rc=RC] # Path to file containing extra configuration options for rails command [--no-rc], [--no-no-rc] # Skip loading of extra configuration options from .railsrc file [--api], [--no-api] # Preconfigure smaller stack for API only apps -B, [--skip-bundle], [--no-skip-bundle] # Don't run bundle install [--webpack=WEBPACK] # Preconfigure for app-like JavaScript with Webpack (options: react/vue/angular/elm/stimulus) Runtime options: -f, [--force] # Overwrite files that already exist -p, [--pretend], [--no-pretend] # Run but do not make any changes -q, [--quiet], [--no-quiet] # Suppress status output -s, [--skip], [--no-skip] # Skip files that already exist Rails options: -h, [--help], [--no-help] # Show this help message and quit -v, [--version], [--no-version] # Show Rails version number and quit Description: The 'rails new' command creates a new Rails application with a default directory structure and configuration at the path you specify. You can specify extra command-line arguments to be used every time 'rails new' runs in the .railsrc configuration file in your home directory. Note that the arguments specified in the .railsrc file don't affect the defaults values shown above in this help message. Example: rails new ~/Code/Ruby/weblog This generates a skeletal Rails installation in ~/Code/Ruby/weblog.原因
"Usage: rails new APP_PATH [options]"が表れるということは考えられることはアプリケーションがないことが原因と考えられますが、前提として
rails new プロジェクト名、cd プロジェクト名は実行されているはずです。そこから察するに、実行はされたが何らかが原因で生成されたプロジェクトが認識されてないのではないかと考えました。ではなぜ認識されないのか考えたところ、予想として
rails new プロジェクト名で生成されるファイルが足りないのではないかと考えたため、私はプロジェクトとして生成されたディレクトリ内を確認したのです。すると予想は的中し明らかにファイルが足りなかったのでした。下記は本来、プロジェクト生成時に生成されるはずのファイル、またはその処理
C:¥Users¥leone> rails new アプリケーション名 create create README.md create Rakefile create .ruby-version create config.ru create .gitignore create Gemfile run git init from "." Initialized empty Git repository in C:/Users/leone/アプリケーション名/.git/ create package.json create app create app/assets/config/manifest.js create app/assets/javascripts/application.js create app/assets/javascripts/cable.js create app/assets/stylesheets/application.css create app/channels/application_cable/channel.rb create app/channels/application_cable/connection.rb create app/controllers/application_controller.rb create app/helpers/application_helper.rb create app/jobs/application_job.rb create app/mailers/application_mailer.rb create app/models/application_record.rb create app/views/layouts/application.html.erb create app/views/layouts/mailer.html.erb create app/views/layouts/mailer.text.erb create app/assets/images/.keep create app/assets/javascripts/channels create app/assets/javascripts/channels/.keep create app/controllers/concerns/.keep create app/models/concerns/.keep create bin create bin/bundle create bin/rails create bin/rake create bin/setup create bin/update create bin/yarn create config create config/routes.rb create config/application.rb create config/environment.rb create config/cable.yml create config/puma.rb create config/storage.yml create config/environments create config/environments/development.rb create config/environments/production.rb create config/environments/test.rb create config/initializers create config/initializers/application_controller_renderer.rb create config/initializers/assets.rb create config/initializers/backtrace_silencers.rb create config/initializers/content_security_policy.rb create config/initializers/cookies_serializer.rb create config/initializers/cors.rb create config/initializers/filter_parameter_logging.rb create config/initializers/inflections.rb create config/initializers/mime_types.rb create config/initializers/new_framework_defaults_5_2.rb create config/initializers/wrap_parameters.rb create config/locales create config/locales/en.yml create config/master.key append .gitignore create config/boot.rb create config/database.yml create db create db/seeds.rb create lib create lib/tasks create lib/tasks/.keep create lib/assets create lib/assets/.keep create log create log/.keep create public create public/404.html create public/422.html create public/500.html create public/apple-touch-icon-precomposed.png create public/apple-touch-icon.png create public/favicon.ico create public/robots.txt create tmp create tmp/.keep create tmp/pids create tmp/pids/.keep create tmp/cache create tmp/cache/assets create vendor create vendor/.keep create test/fixtures create test/fixtures/.keep create test/fixtures/files create test/fixtures/files/.keep create test/controllers create test/controllers/.keep create test/mailers create test/mailers/.keep create test/models create test/models/.keep create test/helpers create test/helpers/.keep create test/integration create test/integration/.keep create test/test_helper.rb create test/system create test/system/.keep create test/application_system_test_case.rb create storage create storage/.keep create tmp/storage create tmp/storage/.keep remove config/initializers/cors.rb remove config/initializers/new_framework_defaults_5_2.rb run bundle install Fetching gem metadata from https://rubygems.org/............. Fetching gem metadata from https://rubygems.org/. Resolving dependencies.... Using rake 13.0.1 Using concurrent-ruby 1.1.5 Using i18n 1.7.0 Using minitest 5.13.0 Using thread_safe 0.3.6 Using tzinfo 1.2.6 Using activesupport 5.2.4.1 Using builder 3.2.4 Using erubi 1.9.0 Using mini_portile2 2.4.0 Using nokogiri 1.10.7 (x64-mingw32) Using rails-dom-testing 2.0.3 Using crass 1.0.5 Using loofah 2.4.0 Using rails-html-sanitizer 1.3.0 Using actionview 5.2.4.1 Using rack 2.0.8 Using rack-test 1.1.0 Using actionpack 5.2.4.1 Using nio4r 2.5.2 Using websocket-extensions 0.1.4 Using websocket-driver 0.7.1 Using actioncable 5.2.4.1 Using globalid 0.4.2 Using activejob 5.2.4.1 Using mini_mime 1.0.2 Using mail 2.7.1 Using actionmailer 5.2.4.1 Using activemodel 5.2.4.1 Using arel 9.0.0 Using activerecord 5.2.4.1 Using mimemagic 0.3.3 Using marcel 0.3.3 Using activestorage 5.2.4.1 Using public_suffix 4.0.3 Using addressable 2.7.0 Using io-like 0.3.0 Using archive-zip 0.12.0 Using bindex 0.8.1 Using msgpack 1.3.1 (x64-mingw32) Using bootsnap 1.4.5 Using bundler 1.17.2 Using byebug 11.0.1 Using regexp_parser 1.6.0 Using xpath 3.2.0 Using capybara 3.30.0 Using childprocess 3.0.0 Using chromedriver-helper 2.1.1 Using coffee-script-source 1.12.2 Using execjs 2.7.0 Using coffee-script 2.4.1 Using method_source 0.9.2 Using thor 1.0.1 Using railties 5.2.4.1 Using coffee-rails 4.2.2 Using duktape 2.3.0.0 Using ffi 1.11.3 (x64-mingw32) Using jbuilder 2.9.1 Using puma 3.12.2 Using sprockets 3.7.2 Using sprockets-rails 3.2.1 Using rails 5.2.4.1 Using rb-fsevent 0.10.3 Using rb-inotify 0.10.1 Using rubyzip 2.0.0 Using sass-listen 4.0.0 Using sass 3.7.4 Using tilt 2.0.10 Using sass-rails 5.1.0 Using selenium-webdriver 3.142.7 Using sqlite3 1.4.2 Using turbolinks-source 5.2.0 Using turbolinks 5.2.1 Using tzinfo-data 1.2019.3 Using uglifier 4.2.0 Using web-console 3.7.0 Bundle complete! 16 Gemfile dependencies, 76 gems now installed. Use `bundle info [gemname]` to see where a bundled gem is installed.下記は陥った状況
C:¥Users¥leone> rails new アプリケーション名 create create README.md create Rakefile create .ruby-version create config.ru create .gitignore create Gemfile //ここらで終わっていた。ではなぜこのようなことが起こるのか。
それはgitがインストールされていない、または上手くインストールされていないためです。
既にしている場合は、gitbashしかgitコマンド使用の許可がされていない。つまりはpathが通っていないことが原因ということになります。解決方法
Gitをインストールする
既にインストールしてある場合は再インストール、またはpathを設定し直す。
pathを設定し直すのが早くC:\Program Files\Git\cmdをpathに追加。
再インストールする際は、インストール前にアンインストールを行う。アンインストール手順
デスクトップ > スタート > 設定 > ホーム > アプリ > Git version〇〇を選択 > アンインストールGitインストール手順
Gitのインストール方法は検索して該当したサイトを参考にインストールして構いませんが、下記に記す部分は注意してほしい。
https://proengineer.internous.co.jp/content/columnfeature/6893(こちらのサイトを参考にするとよい)上記の画面に進んだら画像のように真ん中を選んでください。これはbash以外のシェルでもgitコマンドを使えるようにするためです。もし上を選んでインストールしてしまったら環境変数からpathを追加することをおすすめしますが、pathの概念がわからなければ再インストールしても問題はありません。
最後に
私はこのような方法で解決に至ったのですが、皆さんはどうだったでしょうか。当投稿でお力添え出来たら幸いです。
解決出来た、または役に立ったという方がいればグッドボタンを押して頂けると励みになります。
- 投稿日:2020-01-07T05:38:09+09:00
[Ruby on Rails] serverが起動せず"Usage: rails new APP_PATH [options]..."となってしまう場合の解決法
経緯
私がRailsの環境を構築する際「Rails s」でサーバーが起動しない問題に陥ったが解決に至ったためここにその方法を記載したいと思う。
投稿に至った経緯は以下の通り。
Web上で私と同じように悩んでいる方が多く、またほとんどの記事において解決に至っていなかったため。
該当する記事がそうないように感じたため。
同じ状況に陥っている同志の助けになりたいと考えたため。
陥った状況
- 前提として使用OSは Windows10
- コマンドプロンプトで
rails sを実行すると「Usage: rails new APP_PATH [options] ...(以下省略)」が表示されてサーバが起動できていない。- Ruby、SQLite、Ruby on Railsはインストールされている。
rails new プロジェクト名を実行済み ( 新しいrailsプロジェクトを生成するコマンド )cd プロジェクト名を実行済み ( プロジェクトのrootに移動するコマンド )詳細な状況
- 本来は
rails sを実行した際、下記のようになればよい。C:¥Users¥leone> rails s => Booting Puma => Rails 5.2.4.1 application starting in development => Run `rails server -h` for more startup options *** SIGUSR2 not implemented, signal based restart unavailable! *** SIGUSR1 not implemented, signal based restart unavailable! *** SIGHUP not implemented, signal based logs reopening unavailable! Puma starting in single mode... * Version 3.12.2 (ruby 2.6.4-p104), codename: Llamas in Pajamas * Min threads: 5, max threads: 5 * Environment: development * Listening on tcp://localhost:3000 Use Ctrl-C to stop
- しかし問題の状態では下記のようになってしまう。
C:¥Users¥leone> rails s Usage: rails new APP_PATH [options] Options: [--skip-namespace], [--no-skip-namespace] # Skip namespace (affects only isolated applications) -r, [--ruby=PATH] # Path to the Ruby binary of your choice # Default: C:/Ruby26-x64/bin/ruby.exe -m, [--template=TEMPLATE] # Path to some application template (can be a filesystem path or URL) -d, [--database=DATABASE] # Preconfigure for selected database (options: mysql/postgresql/sqlite3/oracle/frontbase/ibm_db/sqlserver/jdbcmysql/jdbcsqlite3/jdbcpostgresql/jdbc) # Default: sqlite3 [--skip-yarn], [--no-skip-yarn] # Don't use Yarn for managing JavaScript dependencies [--skip-gemfile], [--no-skip-gemfile] # Don't create a Gemfile -G, [--skip-git], [--no-skip-git] # Skip .gitignore file [--skip-keeps], [--no-skip-keeps] # Skip source control .keep files -M, [--skip-action-mailer], [--no-skip-action-mailer] # Skip Action Mailer files -O, [--skip-active-record], [--no-skip-active-record] # Skip Active Record files [--skip-active-storage], [--no-skip-active-storage] # Skip Active Storage files -P, [--skip-puma], [--no-skip-puma] # Skip Puma related files -C, [--skip-action-cable], [--no-skip-action-cable] # Skip Action Cable files -S, [--skip-sprockets], [--no-skip-sprockets] # Skip Sprockets files [--skip-spring], [--no-skip-spring] # Don't install Spring application preloader [--skip-listen], [--no-skip-listen] # Don't generate configuration that depends on the listen gem [--skip-coffee], [--no-skip-coffee] # Don't use CoffeeScript -J, [--skip-javascript], [--no-skip-javascript] # Skip JavaScript files [--skip-turbolinks], [--no-skip-turbolinks] # Skip turbolinks gem -T, [--skip-test], [--no-skip-test] # Skip test files [--skip-system-test], [--no-skip-system-test] # Skip system test files [--skip-bootsnap], [--no-skip-bootsnap] # Skip bootsnap gem [--dev], [--no-dev] # Setup the application with Gemfile pointing to your Rails checkout [--edge], [--no-edge] # Setup the application with Gemfile pointing to Rails repository [--rc=RC] # Path to file containing extra configuration options for rails command [--no-rc], [--no-no-rc] # Skip loading of extra configuration options from .railsrc file [--api], [--no-api] # Preconfigure smaller stack for API only apps -B, [--skip-bundle], [--no-skip-bundle] # Don't run bundle install [--webpack=WEBPACK] # Preconfigure for app-like JavaScript with Webpack (options: react/vue/angular/elm/stimulus) Runtime options: -f, [--force] # Overwrite files that already exist -p, [--pretend], [--no-pretend] # Run but do not make any changes -q, [--quiet], [--no-quiet] # Suppress status output -s, [--skip], [--no-skip] # Skip files that already exist Rails options: -h, [--help], [--no-help] # Show this help message and quit -v, [--version], [--no-version] # Show Rails version number and quit Description: The 'rails new' command creates a new Rails application with a default directory structure and configuration at the path you specify. You can specify extra command-line arguments to be used every time 'rails new' runs in the .railsrc configuration file in your home directory. Note that the arguments specified in the .railsrc file don't affect the defaults values shown above in this help message. Example: rails new ~/Code/Ruby/weblog This generates a skeletal Rails installation in ~/Code/Ruby/weblog.原因
"Usage: rails new APP_PATH [options]"が表れるということはプロジェクトがないことが原因と考えられますが、前提として
rails new プロジェクト名、cd プロジェクト名は実行されているはずです。そこから察するに、実行はされたが何らかが原因で生成されたプロジェクトが認識されてないのではないかと考えました。ではなぜ認識されないのか考えたところ、予想として
rails new プロジェクト名で生成されるファイルが足りないのではないかと考えたため、私はプロジェクトとして生成されたディレクトリ内を確認したのです。すると予想は的中し明らかにファイルが足りなかったのでした。下記は本来、プロジェクト生成時に生成されるはずのファイル、またはその処理
C:¥Users¥leone> rails new アプリケーション名 create create README.md create Rakefile create .ruby-version create config.ru create .gitignore create Gemfile run git init from "." Initialized empty Git repository in C:/Users/leone/アプリケーション名/.git/ create package.json create app create app/assets/config/manifest.js create app/assets/javascripts/application.js create app/assets/javascripts/cable.js create app/assets/stylesheets/application.css create app/channels/application_cable/channel.rb create app/channels/application_cable/connection.rb create app/controllers/application_controller.rb create app/helpers/application_helper.rb create app/jobs/application_job.rb create app/mailers/application_mailer.rb create app/models/application_record.rb create app/views/layouts/application.html.erb create app/views/layouts/mailer.html.erb create app/views/layouts/mailer.text.erb create app/assets/images/.keep create app/assets/javascripts/channels create app/assets/javascripts/channels/.keep create app/controllers/concerns/.keep create app/models/concerns/.keep create bin create bin/bundle create bin/rails create bin/rake create bin/setup create bin/update create bin/yarn create config create config/routes.rb create config/application.rb create config/environment.rb create config/cable.yml create config/puma.rb create config/storage.yml create config/environments create config/environments/development.rb create config/environments/production.rb create config/environments/test.rb create config/initializers create config/initializers/application_controller_renderer.rb create config/initializers/assets.rb create config/initializers/backtrace_silencers.rb create config/initializers/content_security_policy.rb create config/initializers/cookies_serializer.rb create config/initializers/cors.rb create config/initializers/filter_parameter_logging.rb create config/initializers/inflections.rb create config/initializers/mime_types.rb create config/initializers/new_framework_defaults_5_2.rb create config/initializers/wrap_parameters.rb create config/locales create config/locales/en.yml create config/master.key append .gitignore create config/boot.rb create config/database.yml create db create db/seeds.rb create lib create lib/tasks create lib/tasks/.keep create lib/assets create lib/assets/.keep create log create log/.keep create public create public/404.html create public/422.html create public/500.html create public/apple-touch-icon-precomposed.png create public/apple-touch-icon.png create public/favicon.ico create public/robots.txt create tmp create tmp/.keep create tmp/pids create tmp/pids/.keep create tmp/cache create tmp/cache/assets create vendor create vendor/.keep create test/fixtures create test/fixtures/.keep create test/fixtures/files create test/fixtures/files/.keep create test/controllers create test/controllers/.keep create test/mailers create test/mailers/.keep create test/models create test/models/.keep create test/helpers create test/helpers/.keep create test/integration create test/integration/.keep create test/test_helper.rb create test/system create test/system/.keep create test/application_system_test_case.rb create storage create storage/.keep create tmp/storage create tmp/storage/.keep remove config/initializers/cors.rb remove config/initializers/new_framework_defaults_5_2.rb run bundle install Fetching gem metadata from https://rubygems.org/............. Fetching gem metadata from https://rubygems.org/. Resolving dependencies.... Using rake 13.0.1 Using concurrent-ruby 1.1.5 Using i18n 1.7.0 Using minitest 5.13.0 Using thread_safe 0.3.6 Using tzinfo 1.2.6 Using activesupport 5.2.4.1 Using builder 3.2.4 Using erubi 1.9.0 Using mini_portile2 2.4.0 Using nokogiri 1.10.7 (x64-mingw32) Using rails-dom-testing 2.0.3 Using crass 1.0.5 Using loofah 2.4.0 Using rails-html-sanitizer 1.3.0 Using actionview 5.2.4.1 Using rack 2.0.8 Using rack-test 1.1.0 Using actionpack 5.2.4.1 Using nio4r 2.5.2 Using websocket-extensions 0.1.4 Using websocket-driver 0.7.1 Using actioncable 5.2.4.1 Using globalid 0.4.2 Using activejob 5.2.4.1 Using mini_mime 1.0.2 Using mail 2.7.1 Using actionmailer 5.2.4.1 Using activemodel 5.2.4.1 Using arel 9.0.0 Using activerecord 5.2.4.1 Using mimemagic 0.3.3 Using marcel 0.3.3 Using activestorage 5.2.4.1 Using public_suffix 4.0.3 Using addressable 2.7.0 Using io-like 0.3.0 Using archive-zip 0.12.0 Using bindex 0.8.1 Using msgpack 1.3.1 (x64-mingw32) Using bootsnap 1.4.5 Using bundler 1.17.2 Using byebug 11.0.1 Using regexp_parser 1.6.0 Using xpath 3.2.0 Using capybara 3.30.0 Using childprocess 3.0.0 Using chromedriver-helper 2.1.1 Using coffee-script-source 1.12.2 Using execjs 2.7.0 Using coffee-script 2.4.1 Using method_source 0.9.2 Using thor 1.0.1 Using railties 5.2.4.1 Using coffee-rails 4.2.2 Using duktape 2.3.0.0 Using ffi 1.11.3 (x64-mingw32) Using jbuilder 2.9.1 Using puma 3.12.2 Using sprockets 3.7.2 Using sprockets-rails 3.2.1 Using rails 5.2.4.1 Using rb-fsevent 0.10.3 Using rb-inotify 0.10.1 Using rubyzip 2.0.0 Using sass-listen 4.0.0 Using sass 3.7.4 Using tilt 2.0.10 Using sass-rails 5.1.0 Using selenium-webdriver 3.142.7 Using sqlite3 1.4.2 Using turbolinks-source 5.2.0 Using turbolinks 5.2.1 Using tzinfo-data 1.2019.3 Using uglifier 4.2.0 Using web-console 3.7.0 Bundle complete! 16 Gemfile dependencies, 76 gems now installed. Use `bundle info [gemname]` to see where a bundled gem is installed.下記は陥った状況
C:¥Users¥leone> rails new アプリケーション名 create create README.md create Rakefile create .ruby-version create config.ru create .gitignore create Gemfile //ここらで終わっていた。ではなぜこのようなことが起こるのか。
それはgitがインストールされていない、または上手くインストールされていないためです。
既にインストールしている場合は、gitbashしかgitコマンド使用の許可がされていない。つまりはpathが通っていないことが原因ということになります。解決方法
Gitをインストールする
既にインストールしてある場合は再インストール、またはpathを設定し直す。
pathを設定し直すのが早くC:\Program Files\Git\cmdをpathに追加。
再インストールする際は、インストール前にアンインストールを行う。アンインストール手順
デスクトップ > スタート > 設定 > ホーム > アプリ > Git version〇〇を選択 > アンインストールGitインストール手順
Gitのインストール方法は検索して該当したサイトを参考にインストールして構いませんが、下記に記す部分は注意してほしい。
サイトは、こちらのサイトがオススメです。
https://proengineer.internous.co.jp/content/columnfeature/6893上記の画面に進んだら画像のように真ん中を選んでください。これはbash以外のシェルでもgitコマンドを使えるようにするためです。もし上を選んでインストールしてしまったら環境変数からpathを追加することをおすすめしますが、pathの概念がわからなければ再インストールしても問題はありません。
最後に
私はこのような方法で解決に至ったのですが、皆さんはどうだったでしょうか。当投稿でお力添え出来たら幸いです。
解決出来た、または役に立ったという方がいればグッドボタンを押して頂けると励みになります。
- 投稿日:2020-01-07T01:47:29+09:00
RubyとRailsの気になる単語
時々あの、あれ、あの〜意味なんだっけって単語を記していきます。
あくまで一言で行きたい。深追いはしない派。
- オブジェクト
クラスの参照とインスタンス- クラス
入れるべきデータとメソッドを記載した設計図- クラスの参照
オブジェクトの所属するクラス- インスタンス
クラスの設計図から出来たもの- インスタンス変数
クラス内であれば全メソッドで使用することができる、@で定義- module
ミックスイン、ネームスペースを提供- include
インスタンスとしてメソッドを追加- extend
クラスとしてメソッドを追加- ブロック
do~endもしくは{}で囲まれた処理のカタマリ- Proc
ブロックを持ち運び便利なオブジェクトにしたもの- Lambda
Procオブジェクトを作る方法の一つ。Procとの違いは引数チェックする&returnした後もメソッドを実行し続ける- joins
sqlでINNER JOIN- INNER JOIN
関係があるデータだけを取ってきてくれる- includes
データの先読みをしてキャッシュしてくれる- Gemfile
Railsアプリで利用するgemが記述されているファイル- Gemfile.lock
Gemfileをもとに実際にインストールしたgemリスト- Private
オブジェクトの外側からコールはできない- Protected
同じクラスのオブジェクトからならコールは可能- セッション
サーバー側に保存するユーザー情報- クッキー
ブラウザを通じて配布され、パソコンのハードディスクドライブ上に一時的に保存される「小さいファイル」終わりなんてない。
- 投稿日:2020-01-07T01:18:53+09:00
Vue.js入門としてWEBブラウザで使える会社の歓送迎会用費用計算機を作った。
はじめに
会社の歓送迎会の幹事。会社員ならば必ずと言っていいほどやらされる面倒くさい仕事。
2019年12月、ちょうど参加者20人を超える歓送迎会の幹事をやることになった。そこには歓送迎者に加え部長、課長、平社員勢揃いで、全員から同じ参加費を取るわけにもいかないので傾斜計算をする必要があった。そして、いざ計算する時にやっぱり思う、「めちゃくちゃ面倒くさい...」
ゲスト3人タダで、部長が6000円で課長3人が5000円で平社員20人が4000円で…え?●●さんやっぱ出れない?→再計算が始まる。悪夢。できたもの
さっそくできたサイトは以下。着想からリリースまで1週間、15時間ぐらい。
「歓送迎会の会費計算 | Cocktail -f liquor」
使ったもの
簡単に傾斜計算をするためのWEBサービスを入門書だけ読んだVue.jsで作る事にした。
読んだ本→動かして学ぶ!Vue.js開発入門 (NEXT ONE)既に自分はカクテルレシピ検索サイト「Cocktail -f liquor」を持っていたので、そこに機能として追加した。
レシピ検索サイト自体はPaaSにheroku、フレームワークにRails、CSSフレームワークにUIKitを使っているため、PCスマホどちらでもWEBブラウザ上で利用可能にした。傾斜計算をするにあたって考えたこと
歓送迎会の傾斜計算をする場合に必要なものを考えた。いわゆる画面設計。
- 参加する全体の人数と一人分のコース料金のための予約情報の入力欄
- ゲスト、部長、課長、平社員といった参加費用の異なるグループごとの人数と参加費用の入力欄
- 全グループ参加費の合計と人数の合計
- 全グループの情報と予約情報が一致しているかの判定結果
- 残りの参加費を自動的に計算できるようにする機能(これが結構考えるの面倒だった)
- 結果を残しておけるように結果コピー機能
Vue.js部分
自身のスキルが入門書レベルということもあり、コンポーネントは使わない非常にシンプルな構成でVue.jsは記述した。
大枠としては以下の通りで、filter,data,computed,watch,methodsの基本構成で作成することができた(全体のソースコードは最後に記述)。今回はお金と人数を扱うこともあり、Vue.filterを使用して20,000のようにコンマを自動的につけれるようにした。<script> Vue.filter('number_format', function (value) { ... }); new Vue({ el: "#app", data: { price: null, ... }, computed :{ ... }, watch :{ ... }, methods :{ ... } }) </script>少し止まった部分
各グループ情報ごとのグループ参加費合計(グループ人数×グループごとの参加費)を出す必要がある。グループごとの情報は連想配列を配列で保持しており、watchで各グループ情報を監視する際に連想配列の中身をwatchする場合はdeepを指定する必要があった。
参考
[Vue]watchフックで連想配列を監視する場合、ディープウォッチャーにしておく必要がある件 - Qiitadata: { calcs: [{c_name:"",c_price:null,c_person:null,c_total:0,c_auto:false}], }, watch :{ calcs: { handler: function(val){ for (var i = 0; i < this.calcs.length; i++ ){ this.calcs[i].c_total = this.calcs[i].c_price * this.calcs[i].c_person; } }, deep: true } },最後に
歓送迎会用の費用計算機の感想・意見を募集中です。
Twitter @anemoi42 までリプライまたはDMを送っていただけると助かります。以上、ありがとうございました。
ソースコード
<% @page_title = '歓送迎会の会費計算' %> <% content_for :header do %> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.min.js"></script> <% end %> <body> <div class='uk-card uk-card-default uk-card-small uk-card-body uk-margin-small'> <h3 class="box8 uk-margin-remove">歓送迎会の会費計算</h3> <div class="uk-margin-small"> 参加費用に傾斜をつける歓送迎会の会費シミュレーションが可能です。コース料金、全体参加人数を入力後、支払う金額ごとのグループを作成して最終的に参加費用と人数が予約と一致しているか確認できます。ゲストは無料、一般社員は3000円、課長は5000円、部長は6000円といった際の計算が簡単にできます。 </div> </div> <div id="app"> <div class='uk-card uk-card-default uk-card-small uk-card-body uk-margin-small'> <div class='uk-h4 uk-margin-small'>予約情報</div> <div> 全体の参加費合計を出すために、一人分のコース料金と全体の参加人数を入力して下さい。 </div> <hr> <div class='uk-grid uk-margin-small uk-flex uk-flex-middle uk-text-center' > <div>1人分のコース料金:</div> <div> <input v-model.number="price" type="number" placeholder="例)5000" class="uk-input uk-form-width-medium" v-on:blur="complementPriceReserve">円 </div> <div> <input v-model="tax" type="checkbox" class="uk-checkbox"> 税別(10%) </div> </div> <div class='uk-grid uk-margin-small uk-flex uk-flex-middle uk-text-center' > <div> 参加人数: </div> <div> <input v-model.number="person" type="number" placeholder="例)10" class="uk-input uk-form-width-small" v-on:blur="complementPersonReserve">人 </div> </div> <hr> <div class='uk-h4 uk-margin-small uk-align-right'>予約上の参加費合計: {{ total_price|number_format }}円</div> </div> <div class="tmpcalc uk-card uk-card-default uk-card-small uk-card-body uk-margin-small"> <div class='uk-h4 uk-margin-small'>グループ情報</div> 支払う金額ごとのグループを作成して下さい。 <hr> <div v-for="(calc,c) in calcs"> <div class="tmpcalc uk-card uk-card-group uk-card-small uk-card-body uk-margin-small"> <div class='uk-grid uk-margin-small uk-flex uk-flex-middle uk-text-center' > <div> グループ名(任意): </div> <div> <input v-model.number="calc.c_name" type="text" placeholder="例)ゲスト、平社員、課長" class="uk-input uk-form-width-auto"> </div> </div> <div class='uk-grid uk-margin-small uk-flex uk-flex-middle uk-text-center' > <div> グループ人数: </div> <div> <input v-model.number="calc.c_person" type="number" placeholder="例)5" v-on:blur="complementPerson(c)" class="uk-input uk-form-width-small">人 </div> </div> <div class='uk-grid uk-margin-small uk-flex uk-flex-middle uk-text-center' > <div> グループ参加費(1人分): </div> <div> <input v-model.number="calc.c_price" type="number" placeholder="例)4000" v-on:blur="complementPrice(c)" class="uk-input uk-form-width-medium">円 </div> <div> <button v-on:click="autoCalculate(c)" class="uk-button uk-button-default" uk-tooltip="title: 予約の参加費合計と一致するようにこのグループの参加費を計算します。自動計算をするには事前に他のグループ情報と、このグループの人数を入力して下さい。; pos: right">自動計算</button> </div> </div> <hr> <div class='uk-h4 uk-margin-small uk-text-right'>グループ参加費合計: {{ calc.c_total|number_format }}円</div> <div class='uk-flex uk-flex-center' > <div class='uk-padding-small uk-padding-remove-vertical'> <button v-on:click="addList(c)" class="uk-button uk-button-default" uk-tooltip="title: グループを追加します。; pos: bottom"><span uk-icon="icon: plus-circle; ratio: 1.0" type="button" class="cursor_to_point"></span> 追加</button> </div> <div class='uk-padding-small uk-padding-remove-vertical'> <button v-show="minus_circle" v-on:click="delList(c)" class="uk-button uk-button-default " uk-tooltip="title: このグループを削除します。; pos: bottom"><span uk-icon="icon: minus-circle; ratio: 1.0" type="button" class="cursor_to_point"></span> 削除</button> </div> </div> </div> </div> <hr> <div class='uk-h4 uk-margin-small ' align="right">全グループ参加費合計: {{calc_total_price|number_format}} 円</div> <div class='uk-h4 uk-margin-small ' align="right">全グループ参加人数合計: {{calc_total_person|number_format}} 人</div> <div v-if="sub_total_price > 0"> <div class="uk-alert-warning uk-text-center" uk-alert> 予約に対して<font color="#ff4500"> {{sub_total_price|number_format}}円</font> 多く回収しています。 端数の場合は幹事が貰ってしまいましょう。 </div> </div> <div v-else-if="sub_total_price < 0"> <div class="uk-alert-danger uk-text-center" uk-alert> 予約に対して<font color="#ff4500"> {{-sub_total_price|number_format}}円</font> 少なく回収しています。 </div> </div> <div v-else> <div class="uk-alert-success uk-text-center" uk-alert> 予約上の参加費合計と全グループ参加費合計は一致しています。 </div> </div> <div v-if="sub_total_person > 0"> <div class="uk-alert-warning uk-text-center" uk-alert> 予約に対して<font color="#ff4500"> {{sub_total_person|number_format}}人</font> 多く参加しています。 </div> </div> <div v-else-if="sub_total_person < 0"> <div class="uk-alert-danger uk-text-center" uk-alert> 予約に対して<font color="#ff4500"> {{-sub_total_person|number_format}}人</font> 少なく参加しています。 </div> </div> <div v-else> <div class="uk-alert-success uk-text-center" uk-alert> 予約上の参加人数と全グループ参加人数は一致しています。 </div> </div> <textarea id="copyTarget" class="uk-textarea" v-model="outputText" rows="5" placeholder="Textarea" readonly></textarea> <div class='uk-flex uk-flex-center uk-margin-small' > <button v-on:click="copyResult" class="uk-button uk-button-default " uk-tooltip="title: 結果をクリップボードにコピーします; pos: bottom" ><span uk-icon="icon: copy; ratio: 1.0" type="button" class="cursor_to_point"></span> 結果をコピー</button> </div> </div> </div> <div class="uk-flex uk-flex-center uk-margin"> <a class="uk-button uk-button-secondary" href="#topanchor" uk-scroll>ページトップへ</a> </div> <script> Vue.filter('number_format', function (value) { return addComma(value); }); var addComma = function(value){ if (! value) { return 0; } return value.toString().replace( /([0-9]+?)(?=(?:[0-9]{3})+$)/g , '$1,' ); } new Vue({ el: "#app", data: { price: null, person: null, tax: false, calcs: [{c_name:"",c_price:null,c_person:null,c_total:0,c_auto:false}], }, computed :{ total_price: function(){ var total = this.price * this.person; if (this.tax){ total *= 1.1; } return Math.round(total); }, calc_total_price: function(){ var tmp_total = 0; for (var i = 0; i < this.calcs.length; i++ ){ tmp_total += this.calcs[i].c_total; } return tmp_total; }, calc_total_person: function(){ var tmp_person = 0; for (var i = 0; i < this.calcs.length; i++ ){ tmp_person += this.calcs[i].c_person; } return tmp_person; }, sub_total_price: function(){ return this.calc_total_price - this.total_price; }, sub_total_person: function(){ return this.calc_total_person - this.person; }, minus_circle: function(){ if (this.calcs.length > 1){ return true; }else{ return false; } }, outputText: function(){ var resultText = ""; resultText += "◆予約情報◆\n"; resultText += "1人分のコース料金:" + addComma(this.price) + "円\n"; resultText += "参加人数:" + addComma(this.person) + "人\n"; resultText += "予約上の参加費合計:" + addComma(this.total_price) + "円\n"; resultText += "--------------------\n"; resultText += "◆グループ情報◆\n"; for (var i = 0; i < this.calcs.length; i++ ){ if(this.calcs[i].c_name == ""){ resultText += "◇グループ" + (i+1) + "◇\n"; }else{ resultText += "◇" + this.calcs[i].c_name + "◇\n"; } resultText += "参加費:" +addComma(this.calcs[i].c_price) + "円 "; resultText += "人数:" +addComma(this.calcs[i].c_person) + "人 "; resultText += "合計:" +addComma(this.calcs[i].c_total) + "円\n"; } resultText += "--------------------\n"; resultText += "全グループ参加費合計:" + addComma(this.calc_total_price) + "円\n"; resultText += "全グループ参加人数合計:" + addComma(this.calc_total_person) + "人\n"; if(this.sub_total_price > 0){ resultText += "※予約に対して " + addComma(this.sub_total_price) + "円 多く回収\n"; }else if(this.sub_total_price < 0){ resultText += "※予約に対して " + addComma(-this.sub_total_price) + "円 少なく回収\n"; } if(this.sub_total_person > 0){ resultText += "※予約に対して " + addComma(this.sub_total_person) + "人 多く参加\n"; }else if(this.sub_total_person < 0){ resultText += "※予約に対して " + addComma(-this.sub_total_person) + "人 少なく参加\n"; } return resultText; } }, watch :{ calcs: { handler: function(val){ for (var i = 0; i < this.calcs.length; i++ ){ this.calcs[i].c_total = this.calcs[i].c_price * this.calcs[i].c_person; } }, deep: true } }, methods :{ addList: function(c){ //残りの人数を計算 var left_person = this.person - this.calc_total_person; if (left_person < 0){ left_person = 0; } this.calcs.splice(c+1,0,{c_name:"",c_price:0,c_person:left_person,c_total:0}); }, delList: function(c){ if(this.calcs.length > 1){ this.calcs.splice(c,1); } }, autoCalculate: function(target){ var left_person = 0; var left_price = 0; var conf_price = 0; for (var i = 0; i < this.calcs.length; i++ ){ //自動計算対象外の人数と確定金額を取得 if (!this.calcs[i].c_person){ this.calcs[i].c_person = 1; } if (!this.calcs[i].c_price){ this.calcs[i].c_price = 0; } if (i == target){ left_person += this.calcs[i].c_person; } else { conf_price += this.calcs[i].c_price * this.calcs[i].c_person; } } //残額計算 left_price = (this.total_price - conf_price) / left_person; //空欄につめる this.calcs[target].c_price = Math.round(left_price); }, complementPriceReserve: function(){ if(!this.price){ this.price = 0; }else if (this.price < 0){ this.price = 0; } }, complementPersonReserve: function(){ if(!this.person){ this.person = 0; }else if (this.person < 0){ this.person = 0; } }, complementPerson: function(target){ if(!this.calcs[target].c_person){ this.calcs[target].c_person = 0; }else if (this.calcs[target].c_person < 0){ this.calcs[target].c_person = 0; } }, complementPrice: function(target){ if(!this.calcs[target].c_price){ this.calcs[target].c_price = 0; }else if (this.calcs[target].c_price < 0){ this.calcs[target].c_price = 0; } }, copyResult: function(){ var copyTarget = document.getElementById("copyTarget"); copyTarget.select(); document.execCommand("Copy"); } } }) </script> </body>
- 投稿日:2020-01-07T00:01:13+09:00
異業種・異職種からIT業界への転職
はじめに
IT業界の有効求人倍率が上がり、IT人材の雇用待遇はどんどん良くなり、異業種からIT業界へ転職したい人が増えているかと思います。
しかし、全ての人にIT業界を進めるというようなことはしたくなく、どういう仕事であれば自分が頑張っていけるのかということを自己分析した上でIT業界が合っていると考えてくださった方へ向けた記事となります。
とういうのも、定年退職の年齢は60歳でしたが、それが65歳、70歳、・・・とどんどん引き上げられてきています。(再雇用も同様です。)
誰かが言っていた言葉ですが、労働の形が今までの長時間労働から長期間労働に変化していきます。
上記のような現状から筆者としての考えとしては、長い期間楽しく働くために、好きなことを仕事にして生きていくことがこれからの時代で一番重要なことになってくると考えています。大学などでプログラムを扱ってきた人と比べると異業種からのIT業界への転職は積み重ねの数が圧倒的に違います。
この積み重ねの差を埋めるために、追いつくための努力は並大抵のものではありません。
IT業界への転職がうまくいったからと言って必ずしも幸せになれるとは限りません。筆者も異業種からIT業界へ転職した人間の一人として、その経験を綴ることによって誰かの参考になることを強く望んでいます。
好きなこととしてはじめたその仕事はあなたを幸せへと導いてくれるでしょう。
関連リンク
未掲載ですが今後載せていく予定の関連リンクを下記に載せておくので、必要であれば参考にしてください。。
仮タイトルのものも含まれています。掲載し次第、こちらにもリンクを順次貼っていきます。
- スキルアップの軌跡(未経験、転職、入社後まで)
- URL
- メモの魔力、活用術
- URL
- Progate活用術
- URL
- ドットインストール活用術
- URL
- paiza スキルチェック活用術
- URL
- 1ヶ月1個、アプリケーション制作
- URL
- Ruby Silver取得までの道のり
- URL
- Ruby Gold取得までの道のり
- URL
- 入社後の勉強方法
- URL
転職を思いたった理由
大学で電気電子工学を修了し技術的な仕事をしたいと思い自動車メーカーへ入社したものの、配属されたのは事務職の部署でした。
部署ローテーションが3年であると言われその仕事を続けていました。
上司との面談では毎回部署異動したい旨を伝えていて、さらに合格率8%以下の難関な専門資格を取得した上で異動を願い出ましたが、それでも願いは聞き入れてもらえず3年が経ち転職するしかないと踏み切りました。これは前職への恨みとは思っておらず、自分らしい道を進むきっかけとなったと感謝しています。
自己分析
好きなことを仕事にして生きていくために、これが一番重要かもしれません。
メモの魔力
この本を用いて自己分析をすることで、過去の自分から今の自分を振り返ることで、自分の価値観やモチベーションの源泉を知ることができます。
- メモの魔力 -The Magic of Memos- (NewsPicks Book)
自分が何者なのかを知るきっかけを与えてくれたこの本と著者・前田裕司さんに感謝し、他の誰かに勧めることで返していければいいなと考えています。
みなさんもどうぞ読んでみてください。異業種・異職種からIT業界への転職
転職をするときの難易度を並べると下記のようになるそうです。(右が難易度が高い。)
- 同業種・同職種 < 異業種・同職種 < 同業種・異職種 < 異業種・異職種
これは入社してからの難易度(大変さ)も同じ並びになるかと思います。
面接時点で落とされてしまうのは、この会社では大変だよということを教えてくれていると割り切りましょう。まとめ - 好きなことをして生きていこう。
全てがうまくいく訳ではありません。何かを犠牲にしないと何かを達成できないといったトレードオフの関係のものもあると思います。
自己分析をして、人生の軸を見つけることで、取捨選択できる力を身につけましょう。僕も少しずつかもしれませんが進んでいます。スキルアップの時系列を書こうと思って書き始めましたが、人生論みたいなものになってしまいました。
この記事を軸にして、どのように技術力をつけてきたのか、スキルアップの時系列など、上げていきますのでそちらも参考にしてみてください。参考
- 異職種・異業種への挑戦は厳しい







































