20200426のRailsに関する記事は30件です。

ActiveModel::SerializerのRspec

はじめに

SerializerのRSpecについて備忘録で残しておきます。

参考にしたのはこちらのドキュメント

ソースコード

Serializerを使って、idnameemailのみを返すjsonを実装しました。

user_serializer.rb
class UserSerializer < ActiveModel::Serializer
  attribute :id
  attribute :name
  attribute :email
end

そのテストコードがこちら

ポイントだと思うところはこちらの2つ
1. Serializerのインスタンスを生成する必要がある
2. .to_jsonメソッドのオプションを使用して、返ってくるデータのカラムを指定する必要がある

アソシエーションがある場合は、includeオプションを利用するとうまいこと書けると思います。

user_serializer_spec.rb
require 'rails_helper'

RSpec.describe "UserSerializer", type: :serializer do
  context "when create user" do
    let(:user) { create(:user) }
    it "matches to serialized JSON" do
      serializer = UserSerializer.new(user)
      expect(serializer.to_json).to eq(user.to_json(:only => [:id, :name, :email]))
    end
  end
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Capistranoを噛み砕く

近況報告

 実はコーヒーマイスターを前職で取得した経緯がありまして,若干のコーヒーの知識があるので,少しひけらかしたいと思います。まず,コーヒーってどんな飲み物のイメージがあります?多分,苦いイメージですよね。では,現在世界的に高品質なコーヒーはどのように評価されているでしょうか。実は苦さの評価はありません。酸味の評価が主流です。

 理由はいたって簡単。苦味は焙煎によって生まれるものであり,酸味はコーヒー豆がそもそも持っているものだからです。細かい説明はしませんが,生のコーヒー豆は食べられたものではありません,それを美味しくするために火を入れます。その時に豆の成分が焦げて苦味になります。酸味は熱によって分解されていくので,結果として深煎りのコーヒーは酸味のないものになります。一方,苦味は焙煎度合いや焙煎師の腕,設備により変化します。ということは,豆が本来持っている酸味が評価の基準になるのはまあ納得ですね。

 ただ,この評価はスペシャリティコーヒー(世界のコーヒー生産のうち10%程度に該当する)の概念が生まれた10数年前のものであり,以前は苦味,そもそもそんな評価なかったかも。。。今後も同じ評価をしていくとは限りません。やはり常に情報は更新されていきます。だから,常にアンテナを張っていないと時代遅れになっちゃいますね。全てが動いているのに自分が動かなかったら動いている相手から見たら不安定です。だから動くこと,不安定であることこそが安定ってね。

今回の目標

Capistranoで実施していることの言語化

大まかな流れ

・Capistranoについて
・Capistrano導入
・各ファイルの設定

事前準備

デプロイ環境整備
rails5.2以降ならマスターキーを本番環境に環境変数にして入れといてね
ruby 2.5.1

Capistranoについて

一言で言えば,自動デプロイツールです。

デプロイには
SSH内の情報(アプリケーション)の更新
SSH接続
アセットコンパイル更新
Unicorn再起動
といくつかコードを打ち込んでいく必要があります。ただCapistranoを導入さえできれば,
** bundle exec cap production deploy**
これだけで上の作業が終了します。
個人的にはCircleCiを勉強して導入したかったのですが,間に合わずカリキュラムのこちらを

Capistrano導入

railsにおいてCapistranoにはGemが存在します。そこからチョチョイと生成しましょう。

gemfile.
group :development, :test do
  gem 'capistrano'
  gem 'capistrano-rbenv'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano3-unicorn'
end
terminal.
$ bundle install
$bundle exec cap install
⇨gemfileにあるものを参照してcap(istrano)の関連ファイルをインストール

これで1つのフォルダと2つのファイルが生成されます

◆capfile----capistranoで実行することを決めるファイル
◆deploy-----デプロイする環境ごとに設定されるファイル
 ・staging.rb-----ステージング環境(つまり開発環境,テスト環境)に適用される
 ・pruduction.rb--本番環境に適用される
◆deploy.rb--デプロイする内容を決めるフォルダ
capfileで実行することをきめて,残りがGithubへの接続に必要なsshキーの指定、デプロイ先のサーバのドメイン、AWSサーバへのログインユーザー名、サーバにログインしてからデプロイのために何をするか、といった設定が入るわけです。

各ファイルの設定

capfile

capfile.
require "capistrano/setup" ←準備しますー(これ抜けてたら動かない)
require "capistrano/deploy" ←デプロイ実行するねー
require 'capistrano/rbenv' ←rbenvの状態みるね
require 'capistrano/bundler' ←必要なGem確認するね
require 'capistrano/rails/assets' ←アセットファイルをコンパイルするね
require 'capistrano/rails/migrations' ←DB:migrateするね
require 'capistrano3/unicorn' ←unicorn再起動するね
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r } 
⇨ディレクトリ内の.rakeを昇順で抽出

に編集
pruduction.rb

pruduction.rb
 server '12.345.678.90'←用意したElastic I, user: 'ec2-user', roles: %w{app db web} |

「どのサーバーつなぐ?」,「ユーザー名は?」「マイグレートするのは(データベース選択)」
staging.rbは今回必要ないので無視

deploy.rb

deploy.rb
# capistranoのバージョンを記載。固定のバージョンを利用し続け、バージョン変更によるトラブルを防止する
lock '<Capistranoのバージョン>'←ローカルで確認

# Capistranoのログの表示に利用する
set :application, '自身のアプリケーション名'

# どのリポジトリからアプリをpullするかを指定する
set :repo_url,  'git@github.com:<Githubのユーザー名>/<レポジトリ名>.git'

# バージョンが変わっても共通で参照するディレクトリを指定
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')

set :rbenv_type, :user
set :rbenv_ruby, '<このアプリで使用しているrubyのバージョン>' #ローカルで確認

# どの公開鍵を利用してデプロイするか
set :ssh_options, auth_methods: ['publickey'],
                  keys: ['****.pem 自分のに書き換える']

# プロセス番号を記載したユニコーンファイルの場所はここだよ
set :unicorn_pid, -> { "#{shared_path}/tmp/pids/unicorn.pid" }

# Unicornの設定ファイルの場所(ローカルの位置と同じ)
set :unicorn_config_path, -> { "#{current_path}/config/unicorn.rb" }
set :keep_releases, 5

# デプロイ処理が終わった後、Unicornを再起動するための記述
after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
  task :restart do
    invoke 'unicorn:restart'
  end
end

に編集

◆set :xx, xx ⇨DSL(Domain-Specific Language)の一種
ある特定の処理における効率をあげるために特化した形の文法を擬似的に用意したプログラムです。
上記のset :名前, 値について、これは言わば変数のようなものです。
例えばset: Name, 'value' と定義した場合、fetch Name とすることで 'Value'が取り出せます。
また、一度setした値はdeploy.rbやproduction.rbなどの全域で取り出すことができます。
また、ファイル内には、desc '◯◯'やtask:XX doといった記述がよく見受けられます。これは、先ほどCapfileでrequireしたものに加えて追加のタスクを記述している形です。ここで記述したものもcap deploy時に実行されることとなります。

Capistranoによる自動デプロイ後のディレクトリ構成について
 一度Capistranoによる自動デプロイを実行すると、本番環境のアプリケーションのディレクトリが変化します。
Capistranoによるアプリのバックアップなど、複数のディレクトリが作成されます。その中でも特に重要なのが、releases、current、sharedディレクトリです。

releasesディレクトリ
 capistranoを通じてデプロイされたアプリは、releasesというフォルダにひとまとめにされます。
ここに過去分のアプリが残っていることにより、デプロイ時に何か問題が発生しても一つ前のバージョンに戻ったりすることができます。
そして、その過去分の保存数を指定しているのがdeploy.rbのset :keep_releasesの記述となります。今回は5つ、過去のバージョンを保存するよう設定しました。

currentディレクトリ
 releasesフォルダの中で一番新しいものが、自動的にcurrentというフォルダ内にコピーされているような状態になります。そのため、このcurrent内に入っているアプリの内容が、現在デプロイされている内容ということになります。
db:seedもここに入れないと反映されない。
sharedディレクトリ
 バージョンが変わっても共通で参照されるディレクトリが格納されるディレクトリです。具体的には、log、public、tmp、vendorディレクトリが格納されます。

config/unicorn.rb
app_path = File.expand_path('../../', __FILE__)

worker_processes 1

working_directory app_path
pid "#{app_path}/tmp/pids/unicorn.pid"
listen "#{app_path}/tmp/sockets/unicorn.sock"
stderr_path "#{app_path}/log/unicorn.stderr.log"
stdout_path "#{app_path}/log/unicorn.stdout.log"

 ↓↓↓↓↓↓↓ 以下のように変更 ↓↓↓↓↓↓

# ../が一つ増えている
app_path = File.expand_path('../../../', __FILE__)

worker_processes 1
# currentを指定
working_directory "#{app_path}/current"

# それぞれ、sharedの中を参照するよう変更
listen "#{app_path}/shared/tmp/sockets/unicorn.sock"
pid "#{app_path}/shared/tmp/pids/unicorn.pid"
stderr_path "#{app_path}/shared/log/unicorn.stderr.log"
stdout_path "#{app_path}/shared/log/unicorn.stdout.log"

nginxの設定ファイル
同様に、Nginxの設定ファイルも変更が必要です。

これまでは/var/www/以下のアプリケーションに対して連携を設定していたので、/var/www/chat-space以下のcurrent、sharedなどのディレクトリと連携するように設定を変更する必要があります。全て消して編集

$ sudo vim /etc/nginx/conf.d/rails.conf
upstream app_server {
  # sharedの中を参照するよう変更
  server unix:/var/www/<アプリケーション名>/shared/tmp/sockets/unicorn.sock;
}

server {
  listen 80;
  server_name <Elastic IPを記入>;

# クライアントからアップロードされてくるファイルの容量の上限を2ギガに設定。デフォルトは1メガなので大きめにしておく
  client_max_body_size 2g;

  # currentの中を参照するよう変更
  root /var/www/<アプリケーション名>/current/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
    # currentの中を参照するよう変更
    root   /var/www/<アプリケーション名>/current/public;
  }

  try_files $uri/index.html $uri @unicorn;

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;
  }

  error_page 500 502 503 504 /500.html;
}

各サーバー再起動

$ sudo service nginx reload
$ sudo service nginx restart
$ sudo service mysqld restart
$ ps aux | grep unicorn
$ kill [master number]

$ bundle exec cap production deploy

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

Rails attr_accessorを使って、より良いコードを書いてみよう。

どうもチャンクノです。
今個人アプリで勝率を表示するページを作っています。
メソッド作成に困リ果てた結果、attr_accessorを使って解決したお話です。
今回は少し長くなります。
初学者の方が見ると参考になる部分があるかもしれません。

まずは下記のコードを見てみましょう。

viewの記述

<%= @trade.win_rate(current_user) %>
model側の記述

def win_rate(current_user)
  trades     = Trade.where("trades.user_id" => current_user.id)
  win_trades = trades.where("trades.result" => "勝").count
  (win_trades / trades.count.to_f * 100).floor
end

これで一応勝率が導き出せます。
が!!!
はっきり言ってこれは全然よくないコードです。
なぜだかわかりますか?

なぜかというと、月ごとの勝率を出すなど他のパターンが出てきた場合。

メソッド名だけ変えて記述します。

def month_win_rate(current_user)
  trades     = Trade.where("trades.user_id" => current_user.id)
  win_trades = trades.where("trades.result" => "資産増").count
  (win_trades / trades.count.to_f * 100).floor
end

こういう感じでメソッドを作るたびに必ず引数にcurrent_userを取る必要が出てきます。
また、同じ処理を何回も書いてしまう羽目にもなります。
これは保守性に優れていなく、非常によろしくないです。

全体の勝率を表示するだけなら10000歩譲っていいかもしれません。
が、自分は月ごとの勝率などを出すことも考えているのでこのままではダメでした。

そこで何を使ったかというとタイトルにある通りattr_accessorです。
attr_accessorの内容まで書いてしまうと非常に長くなるのでご自身で調べてみてください?‍♂️

参考までに
https://qiita.com/Hassan/items/0e034a1d42b2335936e6

attr_accessorを使った結果先ほどのコードがどのように変化するかというと、、、

controlller

def index
  @trade = Trade.new(current_user_id: current_user.id)
end

view

<%= @trade.win_rate %>
model

attr_accessor :current_user_id

def win_rate
  (search_win_trades_count / search_user_trades.count.to_f * 100)
end

def search_user_trades
  Trade.where("trades.user_id" => current_user_id)
end

def search_win_trades_count
  search_user_trades.where("trades.result" => "勝").count
end

メソッドを作るたびにcurrent_userを引数に取る必要がなくなり、とてもスッキリしましたね。
また、メソッドの処理も別のメソッドに切り分けることで、変更点があっても容易になりました。
同じクラス内にあるメソッドは他のメソッド内でも使うことができるので覚えておくといいと思います。

ちなみに初学者の方がこの内容を理解できたら天才だと思います。
そんなものがあるんだな程度で頭の片隅に置いとけば大丈夫です。
では長くなりましたが今日はこの辺で!
皆様よきプログラミングライフを?

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

I18nについて

I18nとは

国際化という意味で、「Internationalization」の略です。
18の部分は"I"と"n"の間に18文字あることから由来しています。
これを利用することで様々な国の言語に対応させることができます!

使い方

tメソッド(tはtranslateの頭文字からきている。)

日本語のアクセスと英語のアクセスに応じて対応可能となる。

<%= I18t("sports.soccer") %>
config/locales/ja.yml
ja:
  sports:
    soccer: "サッカー"
config/locales/en.yml
en:
  sports:
    soccer: "soccer"

lメソッド(Localizeの頭文字である)

lメソッドは日付や時刻を表す際に用います。

config/locales/ja.yml
ja:
  date:
    formats:
      default: "%Y/%m/%d"
      long: "%Y年%m月%d日(%a)"
      short: "%m/%d"
  time:
    formats:
      default: "%Y/%m/%d %H:%M:%S"
      long: "%Y年%m月%d日(%a) %H時%M分%S秒 %z"
      short: "%y/%m/%d %H:%M"

実行結果

> I18n.l(Date.today)
=> "2020/04/26"                         # 指定がない場合はdefaultを使う
> I18n.l(Date.today, format: :short)
=> "04/26"
> I18n.l(Time.now)
=> "2020/04/26 18:22:54"
> I18n.l(Time.now, format: :long)
=> "2020年04月26日(日) 18時22分54秒 +0900"
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerのproduction環境でのbundle exec方法

DockerでRailsをする時にProduction環境でdb:createができずに調べてもなかなか情報が出てこなかったのでメモ。docker exec-eオプションで環境変数をセットしてコンテナ内部のコマンドを呼べます。

docker exec -e RAILS_ENV='production' myapp bundle exec rake db:create

参考

https://devconnected.com/docker-exec-command-with-examples/

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

bundlerバージョン違いのエラーを解消する

Factory Botをインストールしようとしたらエラー。

version

  • ruby 2.4.9
  • Rails 5.1.1
  • factory_bot_rails ~> 4.10.0
bundle install

The dependency tzinfo-data (>= 0) will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java`.
Fetching gem metadata from https://rubygems.org/............
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies...
Bundler could not find compatible versions for gem "bundler":
  In Gemfile:
    rails (~> 5.1.1) was resolved to 5.1.1, which depends on
      bundler (< 2.0, >= 1.3.0)

  Current Bundler version:
    bundler (2.1.4)
This Gemfile requires a different version of Bundler.
Perhaps you need to update Bundler by running `gem install bundler`?

Could not find gem 'bundler (< 2.0, >= 1.3.0)', which is required by gem 'rails (~> 5.1.1)', in any of the sources.


bundler -v
Bundler version 2.1.4

bundler (< 2.0, >= 1.3.0)が必要なのに2.1.4とバージョンが違うからエラーになるらしい。

# bundlerをインストールできるバージョンを調べる
gem search ^bundler$ --all

*** REMOTE GEMS ***

bundler (2.1.4, 2.1.3, 2.1.2, 2.1.1, 2.1.0, 2.0.2, 2.0.1, 2.0.0, 1.17.3, 1.17.2, 1.17.1, 1.17.0, 1.16.6, 1.16.5, 1.16.4, 1.16.3, 1.16.2, 1.16.1, 1.16.0, 1.15.4, 1.15.3, 1.15.2, 1.15.1, 1.15.0, 1.14.6, 1.14.5, 1.14.4, 1.14.3, 1.14.2, 1.14.1, 1.14.0, 1.13.7, 1.13.6, 1.13.5, 1.13.4, 1.13.3, 1.13.2, 1.13.1, 1.13.0, 1.12.6, 1.12.5, 1.12.4, 1.12.3, 1.12.2, 1.12.1, 1.12.0, 1.11.2, 1.11.1, 1.11.0, 1.10.6, 1.10.5, 1.10.4, 1.10.3, 1.10.2, 1.10.1, 1.10.0, 1.9.10, 1.9.9, 1.9.8, 1.9.7, 1.9.6, 1.9.5, 1.9.4, 1.9.3, 1.9.2, 1.9.1, 1.9.0, 1.8.9, 1.8.8, 1.8.7, 1.8.6, 1.8.5, 1.8.4, 1.8.3, 1.8.2, 1.8.1, 1.8.0, 1.7.15, 1.7.14, 1.7.13, 1.7.12, 1.7.11, 1.7.10, 1.7.9, 1.7.8, 1.7.7, 1.7.6, 1.7.5, 1.7.4, 1.7.3, 1.7.2, 1.7.1, 1.7.0, 1.6.9, 1.6.8, 1.6.7, 1.6.6, 1.6.5, 1.6.4, 1.6.3, 1.6.2, 1.6.1, 1.6.0, 1.5.3, 1.5.2, 1.5.1, 1.5.0, 1.3.6, 1.3.5, 1.3.4, 1.3.3, 1.3.2, 1.3.1, 1.3.0, 1.2.5, 1.2.4, 1.2.3, 1.2.2, 1.2.1, 1.2.0, 1.1.5, 1.1.4, 1.1.3, 1.1.2, 1.1.1, 1.1.0, 1.0.22, 1.0.21, 1.0.20, 1.0.18, 1.0.17, 1.0.15, 1.0.14, 1.0.13, 1.0.12, 1.0.11, 1.0.10, 1.0.9, 1.0.7, 1.0.5, 1.0.3, 1.0.2, 1.0.0, 0.9.26, 0.9.25, 0.9.24, 0.9.23, 0.9.22, 0.9.21, 0.9.20, 0.9.19, 0.9.18, 0.9.17, 0.9.16, 0.9.15, 0.9.14, 0.9.13, 0.9.12, 0.9.11, 0.9.10, 0.9.9, 0.9.8, 0.9.7, 0.9.6, 0.9.5, 0.9.4, 0.9.3, 0.9.2, 0.9.1, 0.9.0, 0.8.1, 0.8.0, 0.7.2, 0.7.1, 0.7.0, 0.6.0, 0.5.0, 0.4.1, 0.4.0, 0.3.1, 0.3.0)

# バージョン指定でインストール
gem install bundler -v 1.9.9
bundler -v

Bundler version 2.1.4

バージョンが変わらない?

こうやるとバージョンを指定して、インストールできるらしい。
エラーなくFactory Botをinstallできた。

bundle _1.9.9_ install

参考サイト
Ruby | bundler を特定のバージョンに切り替えて実行する - Qiita

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

Ruby on Railsの基礎

rails new

Railsで新規アプリケーションを作成する際に使用。
コマンドを実行する際は作成したいアプリケーション名を最後につけてrails new アプリケーション名とコマンドを実行。
また、オプションを付ける場合にはハイフン-を使い-オプション名と追記することで様々なオプションをつけることができる。

$ rails new アプリケーション名 -オプション名
# オプションを付けてアプリケーションを作成

MySQL

データを保存するDBの一種。
RailsではMySQLの他に「SQLite」などのDBも使用することができる。
RailsアプリケーションでMySQLデータベースを使用する場合、
rails newコマンドに「-d mysql」というオプションを付けて新規railsアプリケーションを作成する。
このオプションによって「MySQL」というDBに最適化された設定でアプリケーションが生成される。

rails _5.2.3_ new app -d mysql

rails db:create コマンド

新しくDBを作成するにはrails db:createというコマンドを実行する。
このコマンドはdatabase.ymlというファイルの内容に基づいてDBを新規作成するという機能を持っている。

rails db:create

database.yml(データベース・ヤムル) ファイル

database.ymlにはDBの設定を記述する。Railsは運用環境ごとにDBを持つので、運用環境の分だけDBの設定が記述してある。

運用環境

開発を行う際に、運用環境と呼ばれるものを使い分けることで効率的に作業を行うことができる。運用環境には3つの種類があり、以下のような使い分けをする。

・development 開発環境。通常、開発をする際に使用する環境
・test     テスト環境。アプリケーションの動作をテストする際に使用する環境
・production  本番環境。アプリケーションを実際にリリースする際に使用する環境

rails s コマンド

このコマンドをアプリケーションのディレクトリで実行すると、このアプリケーションを動かすためのサーバーが立ち上がる。起動されるこのサーバーは、開発者だけがPC上でアプリを利用するためのものであり、ローカルサーバーと呼ぶ。

# ローカルサーバーを起動
$ rails s

Control + Cコマンド

サーバーを停止する。

localhost:3000

localhostとは「自分のPC」という意味。自分のPC内にサーバーを立ち上げる。

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

「data()」と「attr()」について

背景

カスタム属性を使う際に必須のメソッドの2つの違いがいまいち理解していなかったため調べて自分なりにまとめてみた。

data()について

「data()」を使うとHTML要素内に付与されたdata属性に対して、取得・設定・変更などが簡単に行える。
独自の属性を作成して付与できるのがdata属性の特徴です。
このようにすることで、あとからJavaScriptやjQueryで取得・変更できるわけです。

attr()について

dataメソッドと似ていますが、属性名の指定は「data-」の部分も一緒に記述しなければならない。

data()の使い方

<body>
<p data-name="sato" data-age="42" data-tel="012-3456-7890">私の名前は佐藤です</p>

<script>
    const result = $('p').data();

    console.log( result );
</script>
</body>
// =>{name: "sato", age: 42, tel: "012-3456-7890"}

対象要素.data( 属性名, 値 )とすると設定・変更できる

<body>
<p>おはよう</p>

<script>
    $('p').data('greet', 'morning');

    console.log( $('p').data('greet') );     // 属性の設定


    $('p').data('greet', 'hello');

    console.log( $('p').data('greet') );   // 属性の更新
</script> 
</body>
// => morning

// => evening

attr()の使い方

対象要素.attr( 属性名, 値 )

<body>
<p>おはよう</p>

<script>
    $('p').attr('data-greet', 'morning');
</script>
</body>
// => morning

違いは?

「attr()」で設定した属性はHTML要素へ直接追加されるが、「data()」で設定した属性はjQuery内へ一時的に保持されるだけで直接HTML要素に追加されるわけではない。

<body>
<p id="one">テスト1</p>
<p id="two">テスト2</p>

<script>
    $('#one').attr('data-name', 'sato');

    console.log( $('#one')[0] );

    $('#two').data('name', 'sato');

    console.log( $('#two')[0] );
</script>
</body>
// => <p id="one" data-name="taro">サンプルテキスト</p>   ←追加されている
// => <p id="two">サンプルテキスト</p>                ←追加されていない

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

Rails で render の後に書かれた処理は実行されるけどレスポンスを返すのは全処理が終わった後

背景

環境

➜ ruby -v
ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-darwin19]
➜ rails -v
Rails 6.0.2.2

調べた結果

  • 普通にタイムアウトした :sob:
  • render head などのレスポンス系のメソッドの後に書かれた処理も実行される
  • ただ、アクションの中で書かれたすべての処理が実行された後に response を返すっぽい
  • 処理の順番が逆になるわけではないので最後に render するのが自然
class HelloController < ApplicationController
  def hello
    render status: 200

    sleep 3.0

    slack_client = Slack::Web::Client.new(
      token: ENV['SLACK_TOKEN']
    )
    res = slack_client.chat_postMessage(
      channel: params[:channel_id],
      text: 'hello world'
    )
  end
end
  • after_action 系を使っても同じ挙動
class HelloController < ApplicationController
  after_action :slack_post

  def hello
    render status: 200
  end

  def slack_post
    sleep 3.0

    slack_client = Slack::Web::Client.new(
      token: ENV['SLACK_TOKEN']
    )
    res = slack_client.chat_postMessage(
      channel: params[:channel_id],
      text: 'hello world'
    )
  end
end
  • ただ before_action で render すると処理がそこで終わる
class HelloController < ApplicationController
  before_action :before_render

  def before_render
    render status: 200
  end

  def hello
    # ここは実行されない
    sleep 3.0

    slack_client = Slack::Web::Client.new(
      token: ENV['SLACK_TOKEN']
    )
    res = slack_client.chat_postMessage(
      channel: params[:channel_id],
      text: 'hello world'
    )
  end
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

bundle installでAn error occurred while installing mysql2

$ rails _5.2.4.1_ new appname --database=mysql --skip-test --skip-turbolinks --skip-bundle

でrailsアプリを新規作成した後、

$ bundle install
...
-----
Don't know how to set rpath on your system, if MySQL libraries are not in path mysql2 may not load
-----
-----
Setting libpath to /usr/local/Cellar/mysql/8.0.19/lib
-----
...
ld: library not found for -lssl
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [mysql2.bundle] Error 1

make failed, exit code 2

Gem files will remain installed in /Users/machoair/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/gems/mysql2-0.5.3 for inspection.
Results logged to
/Users/machoair/.rbenv/versions/2.6.1/lib/ruby/gems/2.6.0/extensions/x86_64-darwin-17/2.6.0/mysql2-0.5.3/gem_make.out

An error occurred while installing mysql2 (0.5.3), and Bundler cannot continue.
Make sure that `gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/'` succeeds before bundling.

のエラーが発生

解決策

上記の通り、エラー内容は

Don't know how to set rpath on your system, if MySQL libraries are not in path mysql2 may not load
Setting libpath to /usr/local/Cellar/mysql/8.0.19/lib
ld: library not found for -lssl

私もよく理解していませんが、「libssl.dylib」を探そうとして、「/usr/local/Cellar/mysql/8.0.19/lib」を探したがありませんというエラーらしいです。

【Rails】MySQL2がbundle installできない時の対応方法
https://qiita.com/fukuda_fu/items/463a39406ce713396403

の記事を参考に、

$ cd アプリ場所
$ brew info openssl
...
For compilers to find openssl@1.1 you may need to set:
  export LDFLAGS="-L/usr/local/opt/openssl@1.1/lib" #ここを参考に次のコマンドを書く
  export CPPFLAGS="-I/usr/local/opt/openssl@1.1/include"  #ここを参考に次のコマンドを書く
...
$ bundle config --local build.mysql2 "--with-cppflags=-I/usr/local/opt/openssl@1.1/include"
$ bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl@1.1/lib"      
You are replacing the current local value of build.mysql2, which is currently "--with-cppflags=-I/usr/local/opt/openssl@1.1/include"
$ bundle install

で解決しました!

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

【Rails】has_secure_passwordでパスワードのセキュリティを強化

目的

パスワードのセキュリティを強化する。

手段

has_secure_passwordを使ってパスワードをハッシュ化する。

・ハッシュ化は、訳のわからない暗号みたいな文字列に変換すること。

・has_secure_passwordでハッシュ化されたパスワードは、同じ文字列で生成すれば常に同じ値になるので一致しているかどうかをチェックする際に使える。

・has_secure_passwordでハッシュ化したパスワードは、元のパスワードそのものに戻すことができないので、ハッシュ化されたパスワードを奪われたとしても何の問題もないのでパスワードのセキュリティが強固になる。

手順

1.Userモデル作成時のパスワード属性をpassword_digestとする。

 ➡︎has_secure_passwordを使う際の命名規則なので必須。

2.Gemfileにbcryptというgemを追加して、インストールする。

 ➡︎bcryptというgemをインストールすることで、has_secure_passwordを使えるようになりパスワードをハッシュ化できるようになる。
 ➡︎$ bundle installコマンドを忘れずに。

3.Userモデルにhas_secure_passwordを記述。

 ➡︎Userモデル内にhas_secure_passwordを記述したことにより、password属性とpassword_confirmation属性の2つの属性が追加される。データベースのカラムとは対応していない属性。

 ➡︎どういうことかというと、この2つはユーザーに入力を求めるためだけの属性で、この2つの属性をユーザーに入力させることで、Railsはこの2つの一致をチェックした後、一致していたらそのパスワードをハッシュ化してデータベースのpassword_digest属性に格納されるようになっている。

以上の記述を行うことで、ユーザーの新規登録時に入力したパスワードはハッシュ化されるようになる。

ターミナル
  $ rails g model user ... ... password_digest:string
db/migrate/[timestamps]_create_users.rb
  class CreateUsers < ActiveRecord::Migration[5.2]
    def change
      create_table :users do |t|
        .
        .
        .
        t.string :password_digest
        .
        .
        .
      end
    end
  end
ターミナル 
  $ rails db:migrate
Gemfile
  gem 'bcrypt', '~> 3.1.7'
ターミナル
  $ bundle install
app/models/user.rb
  class User < ApplicationRecord
    has_secure_password
    .
    .
    .
  end



試しにコンソールで確認してみる。

  $ rails c --sandbox
    > user = User.new(..., password: '123456', password_confirmation: '123456')
    > user.save
    => true
 
    >user.password_digest
    => 'fflafbnalwefhhhawkleufhb'

ユーザーにpasswordとpassword_confirmationに任意の値を入力させれば、2つの属性が一致しているかどうかを検証した後に、ちゃんとハッシュ化されたパスワードがpassword_digest属性に保存されている事がわかる

参考

 現場で使える Ruby on Rails 5速習実践ガイド

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

chmod 600 ←600ってなんやねん

近況報告

とりあえずデプロイは完了しました。readmeを書いて,投稿物を揃え,エラー対応すれば見世物としての体裁はできあがるのかな。某雑食系さんのツイートに,ポートフォリオはサーバーサイドの実力はもちろんのこと,コンテンツ力,そして見た目も評価の対象になりうるとありましたね(めっちゃ噛み砕いた)。自分のはサーバーサイドの記述,実力はまだまだですけど,見た目は手を抜かなければよくできるので,今の自分の最善を尽くした作品を作っていこうと思います。

今回の目的

chmodに続く数字を知る。

結論

ファイルへの権限の種類だよ

詳細

参考

chmodは「change mode」の略で,桁数,数字の組み合わせによって編集の権限とかを設定しています。
これにより,第三者からの不正アクセスの予防に繋がります。

桁数 意味
1桁目(百の位) 所有者のアクセス権限の範囲
2桁目(十の位) グループのアクセス権限の範囲
3桁目(一の位) その他のユーザーのアクセス権限の範囲
数字 意味
4 読み出し許可
2 書き込み許可
1 実行許可
0 権限なし

数字の足し算で権限は増えていきます。例えば全ての権限なら
4+2+1+0で7に
読み出しと書き込みだけなら4+2で6になります。
このように編集できるユーザーを適宜設定できます。

おわりに

Linuxのコマンドは他にもごっそりあるのでそれの一部と考えていただければ。

微量でも参考になったらLGTM,ご指導はコメント欄にお願いします!

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

なぜany?はpresent?より高速と言われるのか

はじめに

「present?メソッドとany?メソッドだったらany?メソッドが高速なのか・・・なぜだろう?」
この疑問を解決すべく、present?メソッドとany?メソッドの処理の違いについて調べてみました。

環境

macOS Catalina Version 10.15.4
Ruby: 2.7.0
Ruby on Rails: 6.0.2.2

present?メソッド、any?メソッドの違い

どちらもテーブルにデータが存在するかを確認するメソッドです。
けれども内部処理はどちらも異なっています。

侍エンジニアブログさんの、any?メソッド記事の一部を抜粋します。

present?メソッドとany?メソッドとの違いについて紹介します。
結論からいうとany?メソッドの方が高速です。
present? → 全てのデータを取得する
any? → 1件のみデータを取得する
Railsが実行する
SQLを比較して違いを確認してみましょう。

> Sample.where(name:"侍1").present?
Sample Load (0.4ms)  SELECT `samples`.* FROM `samples` WHERE `samples`.`name` = '侍1'
=> true
> Sample.where(name:"侍1").any?
Sample Exists (0.4ms)  SELECT  1 AS one FROM `samples` WHERE `samples`.`name` = '侍1' LIMIT 1
=> true

このように、SQLの最後にLIMIT 1 が付与されています。

any?メソッドがpresent?よりも優れているように見えます。
ではなぜこのような処理になっているのか、Ruby on Railsのコードを追ってみました。

なお、modelは侍エンジニアブログさんと同様のSampleモデル(stringのname属性のみ)を作成しています。

present?メソッドの内部処理

present?メソッド実行時のコードの場所はblank.rbとなっています。
このコードを追ってみます。

>Sample.where(name: "侍1").method(:present?).source_location
=> ["/Users/xxxxx/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/activesupport-6.0.2.2/lib/active_support/core_ext/object/blank.rb", 25]
blank.rb
def present?
  !blank?
end
relation.rb
alias :loaded? :loaded

def initialize(klass, table: klass.arel_table, predicate_builder: klass.predicate_builder, values: {})
  @klass  = klass
  @table  = table
  @values = values
  @offsets = {}
  @loaded = false
  @predicate_builder = predicate_builder
  @delegate_to_klass = false
end

def records # :nodoc:
  load
  @records
end

def load(&block)
  unless loaded?
    @records = exec_queries(&block)
    @loaded = true
  end

  self
end

def blank?
  records.blank?
end

よってpresent?メソッドを呼び出した場合、クエリ未発行ならば、exec_queryメソッドでクエリを発行します。
このクエリは、指定されたテーブルの全レコード検索となります。
その後、結果に応じてblank?を行います。
もしクエリ発行済であれば、クエリを発行せずにblank?を行います。

any?の内部処理

any?メソッド実行時のコードの場所はrelation.rbとなっています。
このコードを追ってみます。

>Sample.where(name: "侍1").method(:any?).source_location
=> ["/Users/xxxxx/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/activerecord-6.0.2.2/lib/active_record/relation.rb", 277]
relation.rb
def empty?
  return @records.empty? if loaded?
  !exists?
end

def any?
  return super if block_given?
  !empty?
end

def load(&block)
  unless loaded?
    @records = exec_queries(&block)
    @loaded = true
  end

  self
end
finder_method.rb
def exists?(conditions = :none)
  if Base === conditions
    raise ArgumentError, <<-MSG.squish
      You are passing an instance of ActiveRecord::Base to `exists?`.
      Please pass the id of the object by calling `.id`.
    MSG
  end

  return false if !conditions || limit_value == 0

  if eager_loading?
    relation = apply_join_dependency(eager_loading: false)
    return relation.exists?(conditions)
  end

  relation = construct_relation_for_exists(conditions)

  skip_query_cache_if_necessary { connection.select_one(relation.arel, "#{name} Exists?") } ? true : false
end

よってany?メソッドを呼び出した場合、毎回exists?メソッドにて、テーブルにレコードが1件あるかどうかクエリを発行します。
その後、結果を確認しています。
もしload変数がtrueになった場合は、クエリ発行せずに結果を確認するのみとなります。

まとめ

最初に記載した疑問の答えです。

any?メソッドがpresent?よりも優れているように見えます。
ではなぜこのような処理になっているのか、Ruby on Railsのコードを追ってみました。

present?メソッドの場合、初回のみ全レコードを取得するクエリを発行して判定します。
2回目以降の呼び出しはクエリを発行せずに判定します。

any?メソッドの場合、基本的に毎回、テーブルから1件レコードを取得するクエリを発行して判定します。

このため、全レコードを取り出さないany?メソッドが高速と言われているだと思われます。

ご指摘等あればコメントにご記載をお願い致します。

参考記事

【Rails入門】any?メソッドの便利な使い方を紹介
RailsのActiveRecord::FinderMethodsのSQLクエリ発行の有無について調べる
ActiveRecord::QueryMethodsのselectメソッドについて深掘りしてみた
週刊Railsウォッチ(20191216前編)Rails 6.0.2がリリース、平成Ruby会議01開催、古いRailsのfindメソッド置き換えほか
RailsのArelを調査してみた

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

AWS Cloud9でRuby on Railsを動かしてみた

こんにちは!モリタケンタロウです!
今回はAWSのCloud9で、Ruby on Railsを動かす方法について紹介します。

AWS Cloud9とは

AWS Cloud9については↓をご参考にどうぞ

Ruby on Railsとは

Ruby on RailsはRubyで動作するMVCモデルのフレームワークです。
Webアプリケーション開発に向いていて、世の中のあらゆるサービスがこのRuby on Railsでできています。
Railsはオワコンと言われていたりもしますが、僕が会社でRailsのWebアプリ開発をやっていたときに、勉強しやすくて書きやすかったので、とりあえず今回はRailsを使ってみようと思います。

とにかくやってみよう!

AWS Cloud9では最初からRubyもRailsもインストールされています。
ruby -vrails -vのコマンドで確認できます。
rubyver.png
確認できたら早速アプリを作成してみましょう。
rails new [アプリ名]コマンドで作ります。
newapp.png
そうすると、指定した名前のアプリのディレクトリが作成されました!
作ったアプリのディレクトリの中に入って、rails serverコマンドでアプリを動かしてみましょう。
startapp.png
動いている様子は、Preview > Preview Running Application で確認できます。
previewapp.png
上手くいくと、こんな画面が出てきます。めでたしめでたし!
yayrails.png
上手くいかないと、こんな画面が出てくるかもしれません。
noconnection.png
そんなときは、↓を参考にしてみてください。

ちょっとつまづきながらも無事に「Yay!…」という画面が出せたので、これからコツコツRails開発を始めていきます!
それでは~

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

Railsで新しいアプリを作ったらActiveRecord::ConnectionNotEstablishedが出てきた

こんにちは!モリタケンタロウです!
今回はRailsでアプリを新規作成して動かしてみたら、「ActiveRecord::ConnectionNotEstablished」というエラーが出てきたので、それを解決する方法について紹介します。

開発環境

  • ruby 2.6.3p62
  • Rails 5.0.0

エラー内容

rails serverコマンドでアプリを動かすと、画面にはこんなエラーが出てきます。
noconnection.png
ActiveRecord::ConnectionNotEstablished
No connection pool with id primary found
なにこれ!?分からん…
ということでググると、RailsのORM機能であるActiveRecordが、sqlite3の新しいバージョンに対応してないことが原因らしい。(参考:ActiveRecord::ConnectionNotEstablished No connection pool

対処内容

ということで、Railsがインストールしているパッケージを管理しているGemfileを編集します。

gem 'sqlite3', '~> 1.3.6'
  • 修正前 oldgem.png
  • 修正後 newgem.png

Gemfileを編集したら、bundle installコマンドでインストールパッケージを更新します。
bundleinstall.png
そしてrails serverコマンドでアプリを起動すると…
railsserver.png
yayrails.png
見事、アプリが正常に起動しました。めでたしめでたし!
ということで一件落着(^^)
それでは~

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

【環境構築】Rails6をCloul9で環境構築する

Rails6をCloud9で動かす

試行錯誤を繰り返したが構築できなかったため、cloud9の作成からやり直しました。
その経緯を着ていきます。

  • 環境の作成

以下の記事を参考にしました。
https://skillhub.jp/courses/134/lessons/785

設定画面内の「Rails6ではこちら」が重要かと思います。

- サーバーが立ち上がらない

以上の記事の通り進めましたが、以下のエラーメッセージが出て立ち上がらない。

qiita.rb
Address already in use - bind(2) for "127.0.0.1" port 8080(Errno::EADDRINUSE)

色々と調べ、以下のように試行錯誤。

qiita.rb
 $ lsof -i:8080
COMMAND  PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
ruby    8850 ubuntu   14u  IPv4  42953      0t0  TCP localhost:http-alt (LISTEN)
ruby    8850 ubuntu   15u  IPv6  42954      0t0  TCP ip6-localhost:http-alt (LISTEN)

と表示され、8850の部分をkillすればいいらしく、下記を実行。

qiita.rb
$ kill -9 8850
$ lsof -i:8080

サーバーが立ち上がりました!!

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

【Rails】モデルのオブジェクト生成に対する制限・制御を行ってくれる機能

はじめに

備忘録

目的

データベースに不正なデータが保存されないようにすること。


手段

1.データベースカラムに対して制御を記述する。
2.モデルに対して検証を記述する。

両者の違い

データベースカラムに対する制御
 ➡︎一意性の検証

 ➡︎ユーザーへエラーメッセージを届けられない

 ➡︎モデルでは弾けないような、直接データベースに他のシステムから操作を加える作業に対しての制御

モデルに対する検証
 ➡︎データベースでは制御しきれない部分の補完

 ➡︎ユーザーへエラーメッセージを届ける事ができる

※今回は、制御に関する機能の説明のみです。

1.データベースカラムへの制御でよく行われる方法4つ

※データベースカラムへの制御はマイグレーションファイルに記述していくこと。

1.データ型を付与する。

 ➡︎データ型を付与する事で、そのデータ型以外のデータが格納されることを阻止する。
  →例えば、「名前カラムには文字列しか格納させたくない」場合には、名前カラムに文字列のデータ型を付与すると良い。

2.NOT NULL制約を付与する。

 ➡︎カラムに対して、必ず何かしらの値が格納されるようにしたい場合に空の値が格納されることを阻止する。
  →例えば、ユーザーが新規登録する際に「名前が空のまま保存されることを阻止したい」場合には、この制約を追加すると良い。

3.文字列の長さを制御する。

 ➡︎カラムに対して、文字列の長さを指定することで指定した文字列以上の長さのデータが格納されることを阻止する。
  →例えば、ユーザーが新規登録する際に「名前が20文字以上になることを阻止したい」場合には、文字列の長さを制御してあげると良い。

4.ユニークインデックスを付与する。

 ➡︎カラムに対して、ユニークインデックスを付与する事でそのデータの一意性が確保され、同じデータが格納されることを阻止する。
  →例えば、ユーザーが新規登録する際に「メールアドレスが他のユーザーと被ることを阻止したい」場合には、メールアドレスカラムに対してユニークインデックスを付与してあげると良い。

  コマンドを実行してモデルのクラスファイル(マイグレーションファイル)を作成
  $ rails g model User 
db/migrate/[timestamps]_create_users.rb
  class CreateUsers < ActiveRecord::Migration[5.2]
    def change
      create_table :users do |t|
        t.string :name, limit: 20, null: false
        t.string :email, null: false
 
        t.timestamps
        t.index :email, unique: true
      end
    end
  end
  マイグレーションファイルに変更を加えたらデータベースに変更を保存する
  $ rails db:migrate

t.string :name
 ➡︎データ型の付与

limit: 20
 ➡︎文字列の長さを制御

null: false
 ➡︎NOT NULL制約(SQLのnullとRubyのnilを混同させないこと)

t.index :email, unique: true
 ➡︎ユニークインデックス付与で一意性確保


2.モデルに対する検証方法は主に2つ

※モデルに対する検証はモデルファイルに記述していくこと。
※モデルに対する検証の仕組みは「検証結果が不正だった場合は、エラーメッセージを生成する」であることに注意。なので、例えばユーザーに新規登録をさせる場合は「検証で失敗した結果、何が原因で登録できなかったのかをユーザーに知らせる」事が目的。

1.Railsであらかじめ用意されている、検証用のヘルパーメソッドを使う。

 ➡︎モデルに対して、validatesオプションを使って検証したいヘルパーメソッドを適用させることで、メソッドの内容に準じて検証を行う事ができる。
  →例えば、ユーザーが新規登録する際に「名前未入力による登録する事を阻止したい」場合には、validatesオプションに対してそれ用のヘルパーメソッドを適用させる。
  →その他にもたくさんの検証ヘルパーが用意されている。

2.検証用のメソッドを自分で定義しちゃう。

 ➡︎モデルに対して、「どんな検証を行いたいか」「どんなエラーメッセージを表示させたいか」を考えてメソッドを定義していく。
  →例えば、ユーザーが新規登録する際「名前にハイフンを入れる事を阻止したい」ときには「名前にハイフンを含ませた場合、"名前にハイフンを入れることはできません"というエラーメッセージを生成する」といったメソッドを定義すれば良い。

 ➡︎メソッドを定義したら、validate(単数形であることに注意)オプションに適用させる。

app/models/user.rb
  class User < ApplicationRecors
    validates :name, presence: true
    validate :validate_name_not_include_hyphen
 
    def validate_name_not_include_hyphen
      errors.add(:name, 'にハイフンを入れる事はできません') if name&.include?('-')
    end
  end

validates :name, presence: true
 ➡︎Userモデルのname属性の値が入力されていることをチェックする。

validate_name_not_include_hyphen
 ➡︎メソッド名。

errors.add(:name, 'にハイフンを入れることはできません') if name&.include?('-')
 ➡︎名前にハイフンが含まれていた場合、「(名前)にハイフンを入れることはできません」というエラーメッセージを生成する。

 ➡︎nameに「&」を付けているのは、名前がnilだった場合に例外を発生させないため。nilだった場合はnilを代入させることができる。そうすることでvalidatesオプションのpresence: trueで検証させる。

※エラーメッセージを表示させるまでがゴール

エラーメッセージを生成・表示させるには(ユーザー新規登録を例にする)

1:新規登録ならユーザーコントローラのcreateアクション内で、送信されてきたデータからオブジェクトを@user.saveメソッドで保存・更新する作業を行ってあげる。
 ➡︎ビューで再利用するためにインスタンス変数でオブジェクトを定義してあげること。

2:不正なデータが送信された場合は、saveメソッドの効果により検証が実行され保存されずにfalseを返し、errorsという配列に保存に失敗したオブジェクトが格納される。
 ➡︎saveメソッドやupdate_attributesメソッドなど保存・更新時に検証を行ってくれるメソッドを適用させないと、検証を実行してくれないので注意。
 ➡︎例えば、ユーザーが名前を空のまま保存したとしたら@user.errorsの配列には「@messages ={:name=>["を入力してください"]}」という旨のエラーメッセージが格納される。

3:@user.errors.full_messagesと記述することで、errors配列に格納されているエラーメッセージを取得できる。
 ➡︎名前を入力してください

4:取得した上記のエラーメッセージをビューで表示することで、ユーザーにエラーメッセージを届ける事ができるようになる。

以上の手順を踏む必要がある。

参考

 現場で使える Ruby on Rails 5速習実践ガイド

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

Heroku+Rails+MySQLでデプロイする方法

Heroku+Rails+MySQLでデプロイした際の備忘録として作成いたしました。

環境

MacOS 10.15.4
Ruby 2.5.1
Rails 5.2.3
Mysql2 0.5.3

Heroku上にアプリを作成

※Herokuの新規登録とクレジットカードの登録がまだの方は登録を済ませてから行ってください。

$ heroku login

上記のコマンドでブラウザにログインページが出てくるのでログインしてください。

$ heroku create <アプリ名>
$ git remote

herokuのgit URLが表示されることを確認してください。
下記の様に出力されます。

heroku  https://git.heroku.com/<アプリの名前>.git (fetch)
heroku  https://git.heroku.com/<アプリの名前>.git (push)
origin  git@github.com:shou1012/<アプリの名前>.git (fetch)
origin  git@github.com:shou1012/<アプリの名前>.git (push)

git remoteで表示されたherokuのgit URLをリモートリポジトリに追加します。

$ git remote add heroku https://git.heroku.com/xxxxx-xxxxx-xxxxx.git

環境設定

データベースと環境変数の設定を行なっていきます。
今回は無料のigniteプランで作成致します。

$ heroku addons:create cleardb:ignite
$ heroku config

下記の様にClearDBのURLが表示されますので、コピーしておきます。

CLEARDB_DATABASE_URL: mysql://<ユーザー名>:<パスワード>@<ホスト名>/<データベース名>?reconnect=true

上記のURLを参考に下記を登録していきます。

$ heroku config:add DB_NAME='<データベース名>'
$ heroku config:add DB_USERNAME='<ユーザー名>'
$ heroku config:add DB_PASSWORD='<パスワード>'
$ heroku config:add DB_HOSTNAME='<ホスト名>'
$ heroku config:add DB_PORT='3306'

続いて、DATABASE URLを登録します。
※今回はmysql2で登録しますが、Gemfileを確認して'mysql'を使用している場合は、mysql://で始めてください。

$ heroku config:add DATABASE_URL='mysql2://<ユーザー名>:<パスワード>@<ホスト名>/<データベース名>?reconnect=true'

Railsの環境変数にcredentials.yml.encを使っている場合は下記で登録できます。

$ heroku config:set RAILS_MASTER_KEY='cat config/master.key'

heroku configで登録内容が確認できます。

$ heroku config

本番環境のcompileの設定

config/environments/production.rbに下記を追加します。

config/environments/production.rb

config.assets.compile = true #falseからtrueへ
config.assets.initialize_on_precompile=false

デプロイ

$ git add .
$ git commit -m "コミットメッセージ"
$ git push heroku master

これでうまくいけばデプロイは完了です!!
エラーが出る場合はこちらをご確認ください。

最後にdbマイグレーションをします。

$ heroku run rake db:migrate

では、アプリを開いてみましょう!

$ heroku open

以上でHerokuによるデプロイが完了しました!

最後に

Herokuを使うことで非常に簡単にデプロイができました。
問題がなければこれからも使用していきたいです。

参考

https://kurose.me/heroku-deploy/
https://qiita.com/rainbow___0/items/1789920cf797b5e80a5e
https://qiita.com/daigou26/items/64d87d987652c4108ae6
https://qiita.com/terufumi1122/items/27bf288414569e13e050

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

AWSを用いてrailsアプリをデプロイするプロセスを頑張って噛み砕いてみるvol.6

近況報告

大海に糸を垂らして魚を釣るのと鱒がそこにいるとわかっている生簀で鱒を釣るの,どちらが先に釣れるでしょうか。価値があるから売れるのと,売れるから価値がある,どちらが始まりなのでしょうか。鶏と卵論争ではないけれども,考えていくべきことですよね。

ついに最後,Nginxですね。
まだやりたいことはあって,予定ではCapistranoとベーシック認証があるのでvol.8以上あるのか笑
さあいってみようかぁ!

今回の内容

・インフラ整備での各アクションの言語化
・コードを単に打っているだけでは理解しきれないし,他に応用できないので言語化して整理
・テックキャンプ受講生支援()

大まかな流れ&設定

Nginxインストール

事前準備

vol.1
vol.2
vol.3
vol.4
vol.5

Nginxインストール&設定

EC2.
sudo yum -y install nginx

sudo yum の解説は前の項で触れています。
インストールできたら設定を編集していきます。むやみやたらにいじられたくないファイルなので権限も強いです。sudo権限でvim形式で編集していきます。

EC2.
$ sudo vim /etc/nginx/conf.d/rails.conf
rails.conf
upstream app_server {
  server unix:/var/www/<アプリケーション名>/tmp/sockets/unicorn.sock;
}
  ⇨Unicornと連携させるための設定。アプリケーション名を自身のアプリ名に書き換えることに注意。upstreamは上流の意。ここでunixが登場していることはよくわかんなかった。

server {
⇨ {}で囲った部分をブロックと呼ぶ。サーバの設定ができる
  listen 80;
⇨このプログラムが接続を受け付けるポート番号
  server_name <Elastic IP>;
⇨接続を受け付けるリクエストURL
  client_max_body_size 2g;
⇨クライアントからアップロードされてくるファイルの容量の上限を2ギガに設定。デフォルトは1メガ
  root /var/www/<アプリケーション名>/public;
⇨接続が来た際のrootディレクトリ
  location ^~ /assets/ { ←assetファイルはここに入っているのを参照するよ
    gzip_static on; ←圧縮状態のものを配信。容量が小さくなるのでメモリの負担減らせる
    expires max; ←キャッシュの有効期限。maxは限界までの意
    add_header Cache-Control public; ←キャッシュを受け取る範囲の選択
⇨assetsファイル(CSSやJavaScriptのファイルなど)にアクセスが来た際に適用される設定
  }

  try_files $uri/index.html $uri @unicorn;
⇨ファイルの選択,右の$からアクセスされる

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;
⇨Nginxからユニコーンにむけた設定
  }

  error_page 500 502 503 504 /500.html;
⇨エラーが表示された時のページ
}

と<アプリケーション名>計三箇所直したら,脱出(:wq)

補足
プロキシ
ブラウザとウェブサーバーの中間役。ウェブサーバーの情報をブラウザで写すが,プロキシはウェブサーバーの代理としてウェブサーバーからの情報を写す。 ⇨わかりやすかった説明
location unicornではHTMLメソッドの受け取る方法とか表示の仕方とか設定してるっぽい。

権限変更を行ったあと,再起動をします。

EC2.
$ cd /var/lib
$ sudo chmod -R 775 nginx ←-RはNginxに対してって意味 
$ cd ~
$ sudo service nginx restart
⇨初めにfailed出ても再起動でOKがでれば大丈夫

カリキュラムで分からなかった点
POSTメソッドを用いるとエラーが発生する可能性があるから権限変更を行うらしいのですが,このコマンドが通信量の多いPOSTメソッドのエラーを防ぐのかまだ理解できていません。

●補足chmodについて

UnicornをNginxに接続

config/unicorn.rb
listen 3000

↓以下のように修正

listen "#{app_path}/tmp/sockets/unicorn.sock"

githubに反映後,EC2に読み込み。
unicorn再起動処理をして,ブラウザにElastic IPを直打ちしてアプリケーションのルートページが表示できれば成功。うまく表示できない場合はもう一回やり方を見直す。URLが見つからないことで表示されてない可能性があるので注意して見る。

終わりに

テックキャンプのカリキュラム,はしょりすぎぃ!!!
まあ多分目的は完全理解というより大枠を捉えよ的な教科書みたいなアプローチですな。
10週間でやれることなんてたかがしれてるし,Nginxひとつとっても理解しようとすれば数百ページの本を読まないとだから無難なのかな(しかもオープンソースだから今この瞬間にアップデートされているかもしれない...)。

微量でも参考になったらLGTM,ご指導はコメント欄にお願いします!

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

【Rails】Could not find a JavaScript runtime となる時の解決方法

【事象】
bundle exec rake db:create すると下記のエラーが出る。

rake aborted!
ExecJS::RuntimeUnavailable: Could not find a JavaScript runtime.
See https://github.com/rails/execjs for a list of available runtimes.

【解決策】
Gemfileに下記を追加し、bundle installすると解決した。
image.png
ExecJSとは、RubyからJavaScriptコードを実行できるもの。
エラーの原因は、RubyからJavaScriptを呼び出す役割を持つ
ExecJSのランタイムが見つからないためのようなのでランタイムを追加してあげれば良いと推測。

ExecJSのことを https://github.com/rails/execjs
で見たが、gem therubyracerをインストールするとエラーになったので
また調べてgem mini_racerをインストールすると解決した。

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

[rails] migrate:reset でのエラー

はじめに

railsでアプリを作成していた際、db:migrateをした際に、エラーが発生しめmigrate:resetをしたのですがその際初めてのエラーが発生したので、その備忘録として書きたいと思います。

最初のエラー

新しくテーブルを作成するためにマイグレーションファイルを編集して実行したところファイル内に記述していたテーブル名に記述ミスがあり、エラーが発生しました。

class CreateHoges < ActiveRecord::Migration[5.2]
  def change
    create_table :hoges do |t|
      t.references :huge
      t.text :text
      t.timestamps
    end
    add_foreign_key :hoges, :missname, column: :huge_id  # missnameが記述ミス
  end
end

そのため、記述を直し改めてマイグレーションファイルを実行したところ以下のエラーが発生しました。

rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:

SQLite3::SQLException: table "hoges" already exists: CREATE TABLE "hoges"

どうやらテーブルは既に存在しているといって、エラーが起きているようです。
まさかと思いテーブルを確認しても出来ていません。
rails db:migrate:status で確認してもステータスは downになっていました。

原因

どうやらmigrationの際に、処理が途中まで進んで、残りでエラーが起きているときは、テーブルは生成されているけれどもテーブルを生成したmigrationは未実行のステータスになっていることがあるようです。
(create_tableのあと、add_foreign_keyしたところにエラーがあって、というパターン)

migrate:reset

ならば、一度データベースを全て削除した上で、再度実行したら直りそうです。
以下のコマンドを実行

rails db:migrate:reset

そしたら、またもやエラー

rake aborted!
ActiveRecord::NoEnvironmentInSchemaError:

Environment data not found in the schema. To resolve this issue, run:

        bin/rails db:environment:set RAILS_ENV=development

なんだこれは、と思い調べたところ、どうやら指示されるようにコマンドを入力したら直りそうです。
以下の記事が、とても参考になります。
ActiveRecord::NoEnvironmentInSchemaErrorについて

解決

まず指示されるまま以下のコマンドを実行

 rails db:environment:set

そして、再度以下のコマンドを。

rails db:migrate:reset

ようやく正常にテーブルを作成することができました。

おわり

今回はmigrate:resetで解決しましたが、もし他のテーブルに影響を与えない方法があるならば、教えていただければ幸いです。
最後まで読んでいただき、ありがとうございました。

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

【Rails】wheneverを用いたバッチ処理の実装

目標

登録ユーザー全員に、Googleメールを1日毎に送信する。

開発環境

・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina

前提

・メール送信機能を実装済み。

メール送信機能 ➡︎ https://qiita.com/matsubishi5/items/c88e8c58b1ce39302868

メール送信機能を編集

1.「login_mailer.rb」を編集

daily_mailer.rb
class DailyMailer < ApplicationMailer
    def send_mail(user)
        @user = user
        mail to: @user.email, subject: "定期配信"
    end

    def self.send_when_everyday
        @users = User.all
        @users.each do |user|
            DailyMailer.send_mail(user).deliver
        end
    end
end

2.「send_when_login.html.erb」を編集

daily_mailer/send_mail.html.erb
<%= @user.name %><p>定期配信メールです。</p>

3.「application_controller.rb」を編集

application_controller..rb
#コメントアウト又は削除
def after_sign_in_path_for(resource)
    LoginMailer.send_when_login(current_user).deliver
    root_path
end

バッチ処理を実装

1.Gemを追加

Gemfile
gem 'whenever', require: false

require: false ➡︎ アプリケーションには反映させずに、ターミナルにのみ反映させる

ターミナル
$ bundle

2.「schedule.rb」を作成

ターミナル
$ bundle exec wheneverize .

3.「schedule.rb」を編集

config/schedule.rb
env :PATH, ENV['PATH'] #絶対パスから相対パス指定
set :output, 'log/cron.log' #ログの出力先ファイルを設定
set :environment, :development #環境を設定

every 1.day do #1日毎に実行
#「DailyMailer」の、「send_when_everyday」メソッドを実行
    runner "DailyMailer.self.send_when_everyday" 
end

4.「cron」を反映

ターミナル
$ bundle exec whenever --update-crontab

バッチ処理でよく使うコマンド

$ bundle exec whenever ➡︎ cronの設定を確認

$ bundle exec whenever --update-crontab ➡︎ cronを反映

$ bundle exec whenever --clear-crontab ➡︎ cronを削除

参考サイト

https://freecamp.life/rails-whenever/

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

Rubyの『テスト自動化』(Minitest)について、簡単にまとめてみた。

はじめに

これは、プロを目指す人のためのRuby入門(チェリー本)を読んで理解を自分なりにまとめて書き記した物です。
個人的にわからない箇所を書き記したものとなっていますので、全て書いているわけではありません。
しかし、みんながつまずく箇所は似通っているのでは?と思うのでその点に関しては、要点を絞った内容が書けているのではと思います(たぶん)。

今回書くのは、その中でも『第3章:テストを自動化する』(Minitestの基本)についてです。

それでは、内容の方へ入りましょう!

テストを自動化する

ここで学ぶ事は、
・Minitestの基本
です。

そして、テスト自動化とは名前の通り『勝手にテストを行ってくれて、ミスがないか確認してくれるものの事』です。
ミスがないかの確認を毎回毎回行うことは効率が悪いためです。

●Minitestの基本

まずは、テスト用のフレームワークを用意します。
Rubyにおいてはそのフレームワークの一つとしてMinitestがあります。

Minitestを使うメリットは、
・Rubyと一緒にインストールされるため、セットアップが不要
・学習コストの低さ
・Railsのデフォルトのテスティングフレームワークのため、Railsを開発するときにも知識を生かしやすい。

今回のテストを行うにおいての簡単な手順としては、
1. Rubyプログラム(テストコード)を書く
2. テストコードの実行
3. テスティングフレームワークが結果をチェックして、結果報告

では、実際にテストコードを書いていってみましょう。

test_ruby.rb
require 'minitest/autorun' # Minitestのライブラリの読み込み

class RubyTest < Minitest::Test
  def test_ruby #メソッド名はtest_で始めるのが必須
    assert_equal 'RUBY', 'ruby'.upcase #この部分が検証される部分。
    #assert_equalはMinitestのメソッド。意味は後で説明
  end
end
assert_equal 期待する結果, テスト対象となる値や式

この本で紹介されているのは、以下の3つのメソッド
(他にもメソッドは存在します。知りたい方は、MinitestのAPI公式ドキュメントへ)

#①aとbが等しければテストはパス
assert_equal b, a

#②aが真であればパス
assert a

#③aが偽であればパス
assert a

そして、先ほどのtest_ruby.rbのテストを実行した結果が

$ ruby ruby_test.rb
Run options: --seed 35176

# Running:

. #←テストの進歩状況を表しています。(今回はテストメソッドが1個だけのためドットが一つだけ)

Finished in 0.000979s, 1021.4507 runs/s, 1021.4507 assertions/s. # テストの実行スピード
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips

failuresとerrorsがどちらも0ならテストをパスしたことになります。
今回はテストにパスした例になりますが、次は失敗例をみてみましょう。

●テストの実行結果、失敗例

test_ruby.rb
require 'minitest/autorun' 

class RubyTest < Minitest::Test
  def test_ruby
    assert_equal 'Ruby', 'ruby'.upcase # assert_equal 'Ruby'に変更
  end
end
$ ruby ruby_test.rb
Run options: --seed 18225

# Running:

F

Failure:
RubyTest#test_ruby [ruby_test.rb:5]: ←ruby_test.rb:5からruby_test.rbの5行目でテストが失敗していることが確認できる。
Expected: "Ruby" ←期待された結果
  Actual: "RUBY" ←実際の結果


rails test ruby_test.rb:4



Finished in 0.001320s, 757.5753 runs/s, 757.5753 assertions/s.
1 runs, 1 assertions, 1 failures, 0 errors, 0 skips

実行結果の説明をします。
今度はドットではなく、『F』に変わりましたが、これはFailureのFです。
その後は、どこで失敗したかが記載されています。

●実行結果がエラーの場合

$ ruby ruby_test.rb
Run options: --seed 35712

# Running:

E 

Finished in 0.001649s, 606.4282 runs/s, 0.0000 assertions/s.

  1) Error:
RubyTest#test_ruby:
NoMethodError: undefined method `upcase' for nil:NilClass
Did you mean?  case
    ruby_test.rb:5:in `test_ruby'

1 runs, 0 assertions, 0 failures, 1 errors, 0 skips

今度は、『F』だったところが、Errorの『E』へと変わりました。

1) Error:以降はエラー内容の詳細になります。

1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
から、1件のエラーで終わったことが確認できました。

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

windows10(WSL2)でRailsの環境構築をしてみた~Rails導入/起動まで~(2)

はじめに

前回記事にてWSL2の導入ができましたが、今回はWSL2を用いて実際にUbuntu 18.04に環境を構築していきます。

Ruby(Rails)導入

@ksh-fthr さんの以下記事を参考にしました。
Windows10 で WSL を使って Rails 環境を構築したときのメモ
見出しRails 環境を構築しよう1~8を実施してください。

今回しようとしているのは上記の記事と若干違うので、以下の点だけ異なっています。
Ruby 2.6.6を導入
・sqlite3ではなくmysqlを導入するので7.sqliteを入れようは実施不要

WebPackerの導入

rails6からWebpackerが必須となり、Webpackerを入れないと、Railsアプリ作成の際にエラーが出てしまいます。
Ubuntu 18.04 LST にて以下コマンドを実行してください。

まず、Webpacekrをインストールするためのyarnをインストールします。
単純にapt-get install yarnだけだとバージョンが古くてWebpackerをインストールできなかったので、以下コマンドでバージョンの新しいyarnを入れます。

Ubuntu18.04
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
sudo apt-get update
sudo apt-get install yarn

本命のWebpackerを導入します。

Ubuntu18.04
rails webpacker:install

mysqlの導入

今回はsqliteの代わりにmysqlを導入します。
Ubuntu 18.04 LST にて以下コマンドを実行してください。

mysqlの導入

Ubuntu18.04
sudo apt-get install mysql-server mysql-client

mysqlのバージョン確認

Ubuntu18.04
実行コマンド
mysql --version
実行結果
mysql  Ver 14.14 Distrib 5.7.29, for Linux (x86_64) using  EditLine wrapper

バージョンが表示されれば導入完了です。

mysqlにはデフォルトでrootユーザが用意されていますが、これをrails上で使用するとすると、権限の問題で弾かれてしまいます。
root以外のユーザを作成し、きちんと権限も与えてあげましょう。
以下、コマンド例になります。

ユーザ作成例(rootで実行)

CREATE USER railsuser@'localuser' IDENTIFIED BY '******(パスワード)'

権限付与例(rootで実行)

GRANT ALL ON *.* TO railsuser@'localuser';

Atom導入

今回はエディターとしてAtomを利用します。
Ubuntu 18.04 LST にて以下コマンドを実行してください。

Ubuntu18.04
sudo apt-get install mysql-server mysql-client

以下コマンドを実行すると、Atom がGUIで立ち上がってきます。

Ubuntu18.04
atom

Rails サーバ起動

Ubuntu 18.04 LST上でRailsサーバを起動していきます。

1. アプリ作成

新しいアプリ作成します。

Ubuntu18.04
rails new sample -d mysql
cd sample

2. mysql設定ファイル編集

/config/database.ymlにmysqlのログイン情報を記載します。

database.yml
# MySQL. Versions 5.5.8 and up are supported. 
#
# Install the MySQL driver
#   gem install mysql2
#
# Ensure the MySQL gem is defined in your Gemfile
#   gem 'mysql2'
#
# And be sure to use new-style password hashing:
#   https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html
#
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: railsuser
password: ******(パスワード)
socket: /var/run/mysqld/mysqld.sock

usernamepasswordをmysql導入時に設定した内容にしてください。

また、テスト・開発・本番用のDBはあらかじめmysqlにて作成しておいてください。

3. サーバ起動

サーバを起動します。

Ubuntu18.04
rails s

ブラウザにてlocalhost:3000に接続して以下画面が表示されたら成功です。
2020-04-26 (6).png

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

WSL2でRailsの環境構築をしてみた~WSL2導入まで~(1)

はじめに

web開発に関してはmacユーザが多いと思うが、windowsでも WSL( Windows Subsystem for Linux) なるものでLinuxでのRailsの開発環境をある程度整えることができたので、備忘として残そうと思います。

環境
Windows 10 Home 64bit

WSLを導入する

WSLの導入には@yoshigeさんの以下記事が非常に参考になりました。

まずは、以下の記事を参考にWSL1を導入し、初期設定まで済ませます。
Microsoft StoreでLinuxのディストリビューションを選んで導入することになるが、自分はUbuntu 18.04 LTS を導入しました。
初心者のためのWSL( 1 ) ~初期設定,CUI設定編~

GUIも使えた方が便利なので、以下記事を参考にGUI設定まで済ませます。
初心者のためのWSL( 2 ) ~GUI設定,デスクトップ環境設定編~

WSL2を導入する

WSL2の導入は少し複雑です。

1. Windows10 Insider Preview に登録 ⇒ ビルド更新

WSL2はビルドが18917以上でないと導入できません。

以下URLの手順に沿ってWindows10 Insider Preview に登録しビルドを更新してください。
https://insider.windows.com/ja-jp/getting-started/#register

2. ビルドを確認する

設定システムバージョン情報でOSビルド欄をみて、18917以上であることを確認してください。

3. 仮想マシン有効化

以下コマンドを管理者権限のPowerShellで実行し、再起動してください。
powershell
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform

4. WSL2へ切り替え

以下、コマンドを管理者権限のPowerShellで実行してください。
ビルドが18917以上でないと、以下コマンドは実行できません。

現在のWSLバージョンを確認する

 実行コマンド
 wsl -l -v
 出力結果
  NAME            STATE           VERSION
* Ubuntu-18.04    Running         1

WSLバージョンを2へ切り替える(結構時間がかかるかもしれません)

wsl --set-version Ubuntu 2

切り替え後のバージョンを確認する

 実行コマンド
 wsl -l -v
 出力結果
  NAME            STATE           VERSION
* Ubuntu-18.04    Running         2

WSLのバージョンが「2」になっていることを確認出来たらWSL2の導入は完了です。

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

windows10(WSL2)でRailsの環境構築をしてみた~WSL2導入まで~(1)

はじめに

web開発に関してはmacユーザが多いと思いますが、windowsでも WSL( Windows Subsystem for Linux) なるものでLinuxでのRails開発環境をある程度整えることができました。
備忘として残そうと思います。

環境
Windows 10 Home 64bit

また、今回導入したものは以下となります。

導入したもの
Ruby 2.6.6
Rails 6.0.2.2
mysql for linux 14.14
Atom 1.45.0

WSLを導入する

WSLの導入には@yoshigeさんの以下記事が非常に参考になりました。

まずは、以下の記事を参考にWSL1を導入し、初期設定まで済ませます。
Microsoft StoreでLinuxのディストリビューションを選んで導入することになるが、自分はUbuntu 18.04 LTS を導入しました。
初心者のためのWSL( 1 ) ~初期設定,CUI設定編~

GUIも使えた方が便利なので、以下記事を参考にGUI設定まで済ませます。
初心者のためのWSL( 2 ) ~GUI設定,デスクトップ環境設定編~

WSL2を導入する

WSL2の導入は少し複雑です。

1. Windows10 Insider Preview に登録 ⇒ ビルド更新

WSL2はビルドが18917以上でないと導入できません。

以下URLの手順に沿ってWindows10 Insider Preview に登録しビルドを更新してください。
https://insider.windows.com/ja-jp/getting-started/#register

2. ビルドを確認する

設定システムバージョン情報でOSビルド欄をみて、18917以上であることを確認してください。

3. 仮想マシン有効化

以下コマンドを管理者権限のPowerShellで実行し、再起動してください。

Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform

4. WSL2へ切り替え

以下、コマンドを管理者権限のPowerShellで実行してください。
ビルドが18917以上でないと、以下コマンドは実行できません。

現在のWSLバージョンを確認する

 実行コマンド
 wsl -l -v
 出力結果
  NAME            STATE           VERSION
* Ubuntu-18.04    Running         1

WSLバージョンを2へ切り替える(結構時間がかかるかもしれません)

wsl --set-version Ubuntu 2

切り替え後のバージョンを確認する

 実行コマンド
 wsl -l -v
 出力結果
  NAME            STATE           VERSION
* Ubuntu-18.04    Running         2

WSLのバージョンが「2」になっていることを確認出来たらWSL2の導入は完了です。

WSL2へ切り替えた後の設定

1. .bash_profileを編集

WSL2に切り替えた後だと、ターミナル立ち上げの際に.bashrcを読み込んでくれない仕様になっているようです。

参考
WindowsTerminalやPowerShellからWSL2を実行した際に~/.bashrcが読み込まれない

自分は.bash_profileに以下を追加することで回避しました。

if [[ -f ~/.bashrc ]] ; then
  ~/.bashrc
fi   

3. GUI設定の変更

WSL2はWSLと違い、仮想マシン上でLinuxを動作させています。

参考
https://www.atmarkit.co.jp/ait/articles/1906/14/news019.html

なのでWSLと違い、window環境 ⇔ Linux環境のIPアドレスが別々に扱われます。

以下、windowsのコマンドラインでipconfigを実行した例になります。

Wireless LAN adapter Wi-Fi:

   IPv4 アドレス . . . . . . . . . . . .: xxx.xxx.xxx.xxx
   サブネット マスク . . . . . . . . . .: 255.255.255.0
   デフォルト ゲートウェイ . . . . . . .: xxx.xxx.xxx.1

イーサネット アダプター vEthernet (WSL):

   IPv4 アドレス . . . . . . . . . . . .: yyy.yyy.yyy.yyy
   サブネット マスク . . . . . . . . . .: 255.255.240.0
   デフォルト ゲートウェイ . . . . . . .: yyy.yyy.yyy.1

新しくイーサネット アダプター vEthernet (WSL)が追加されていることがわかります。
IPが起動するたびに変更されるので、Xlaunchの待受け先もそれに伴い修正する必要があります。

GUI設定にて.bashrcにexport DISPLAY=localhost:0と記載していた部分を以下のように修正します。

export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0 

これで、IPアドレスが変更されても、設定しなおすことなくGUIが立ち上がります。

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

HerokuでのデプロイでPrecompiling assets failed.が出たときの対処法

初めてHerokuでデプロイを行なったらPrecompiling assets failed.というエラーが出てきてしまったので備忘録として投稿します。こちらのエラー、原因は色々あるみたいですので、下記の解決法が全てではありません。

開発環境

MacOS 10.15.4
Ruby 2.5.1
Rails 5.2.3

最初に

エラーは目立つ部分が全てではない!!

remote:  !     Precompiling assets failed.

こちらの一文は赤字で目立ちますが、実は大事な部分がターミナルをさかのぼると出てきます。

エラー1

さかのぼるとこの様なエラーが出てきました。

NoMethodError: undefined method `[]' for nil:NilClass

[]を見て思い出しました!!
環境変数セットしてなかった...
私はcredentials.yml.encを使っていたので、下記のコードで環境変数を設定致しました。

$ heroku config:set RAILS_MASTER_KEY=`cat config/master.key`

デプロイします。

$ git push heroku master

エラー2

上記で環境変数をセットしたにもかかわらず、またしてもPrecompiling assets failed.が出現しました。
ターミナルをさかのぼります。
エラー文が変わっている!!先ほどのエラーは解決できた様です。

続いてはこちら

Uglifier::Error: Unexpected token: name (任意の内容). To use ES6 syntax, harmony mode must be enabled with Uglifier.new(:harmony => true).

「ES6を使うにはUglifier.new(:harmony => true)でharmony modeを有効してください」ということらしいです。エラー文で検索するとすぐに対処法が出てきました。
config/environments/production.rbを編集します。

config/environments/production.rb

config.assets.js_compressor = :uglifier #削除
config.assets.js_compressor = Uglifier.new(harmony: true) #追加

gitに変更を上げて、再度

$ git push heroku master

無事デプロイできました!!

最後に

冒頭にも書きましたが、こちらのエラーはターミナルをさかのぼるとエラー内容が分かりますので、まずはそちらのエラー内容でググってみてください!

参考

https://teratail.com/questions/163759
https://qiita.com/terufumi1122/items/27bf288414569e13e050

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

Rails テーブルの制約について


Rails初心者の備忘録です。

制約とは

Railsでテーブルのカラムやデータに制限を加え、想定通りの値が入るようにします。

例えば郵便番号のように数値のデータが欲しいとき、文字列が入ってしまうと機能がおかしくなってしまうこともあります。
そのため、制約を設定します。

制約の種類

データ型

一般的によく使われているのがデータ型で、以下のようなものがあります。

string 短い文字
text 長い文字
integer 数値(整数)
float 数値(浮動小数)
date 日付
datetime 日時
time 時刻
boolean 真偽

NOT NULL制約

空欄を禁止する制約です。null: falseを付けます。

class CreatePostImages < ActiveRecord::Migration[5.1]
  def change
    create_table :post_images do |t|
      t.text :shop_name  
      t.text :image_id, null: false  #これ
      t.text :caption
      t.integer :user_id
      t.timestamps
    end
  end
end

UNIQUE制約

重複を禁止する制約です。unique: trueを付けます。
例えば、同じユーザーネームを登録できないようにしたい時などに使えると思います。

class CreatePostImages < ActiveRecord::Migration[5.1]
  def change
    create_table :post_images do |t|
      t.text :shop_name, unique: true #これ
      t.text :image_id, null: false  
      t.text :caption
      t.integer :user_id
      t.timestamps
    end
  end
end

DEFAULT制約

初期値を設定しておく制約です。:default => ''を付けます。

class CreatePostImages < ActiveRecord::Migration[5.1]
  def change
    create_table :post_images do |t|
      t.text :shop_name, null: false  
      t.text :image_id, unique: true 
      t.text :caption, :null => false, :default => 'これは例です。'  #これ 
      t.integer :user_id
      t.timestamps
    end
  end
end

主キー制約

主キーが必ずあって、重複もしてはいけないという制約です。idなどでよく使われるみたいです。
Railsでは、テーブルを作成する際にidカラムに元々実装されています。

外部キー制約

IDなどのキーを利用してテーブルとテーブルを関連付けているとき、親元のテーブルにデータが存在していなければいけないという制約です。

やり方はいろいろあるみたいですが、reference型のものを記載します。
t.reference :userの後にforeign_key: trueを付けます。

このとき、カラム名は`user_idで、自動でインデックスを割り振ってくれます。嬉しい。笑

class CreatePostImages < ActiveRecord::Migration[5.1]
  def change
    create_table :post_images do |t|
      t.text :shop_name, null: false  
      t.text :image_id, unique: true 
      t.text :caption, :null => false, :default => 'これは例です。' 
      t.references :user, foreign_key: true  #これ 
      t.timestamps
    end
  end
end


他にもいろいろとあるみたいですが、重要なものをメモしてみました。

参考にしたサイト

Railsの外部キー制約とreference型について

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

【Rails】日本語表記化(ページネーション、エラーメッセージ)

railsで英語表記になっているものを日本語にする方法があります。

ページネーション

Railsのgemであるwill_paginateのラベルを日本語に変えます。

■デフォルト
スクリーンショット 2020-04-26 0.33.25.png

■日本語表記後
スクリーンショット 2020-04-26 0.43.19.png

実装

まずconfig/environment.rbに以下を記述します。

config/environment.rb
WillPaginate::ViewHelpers.pagination_options[:previous_label] = '&lt 前へ'
WillPaginate::ViewHelpers.pagination_options[:next_label] = '次へ &gt'

そして該当のページネーションに追記します。

<%= will_paginate %>
↓
<%= will_paginate , previous_label: '&lt 前へ', next_label: '次へ &gt'%>

これで実装できます。

エラーメッセージ

■デフォルト
image.png
■日本語化
image.png

実装

Gemfileにて下記をインストール

Gemfile
gem 'rails-i18n'

次にconfig/application.rbで以下を追記

config/application.rb
config.i18n.default_locale = :ja

これだけでも日本語表記化されますがモデルのカラム名などが英語のままです。
そこでconfig/locales内にja.ymlを追加し下記を入力してください。

config/locales/ja.yml
ja:
  activerecord:
    models:
      user: ユーザー
    attributes:
      user:
        name: 名前
        email: メールアドレス

これで名前とメールアドレスが英語表記になります。

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

Railsの開発環境でサブドメインをテストする

概要

Railsではデフォルトではlocalhost:3000で開発環境にアクセスできますが、
ルーティングをサブドメインで切り替えるテストをしたいなと思った時にハマったので、解決策を示します。

ルーティング

routes.rb
# hostがexample.comの時だけアクセスさせたい
constraints host: example.com do
  get 'top', to: 'top#index'
end

新しいドメインを追加する

OSがmacまたはlinuxの場合は、/etcディレクトリに、windowsの場合はC:\Windows\System32\driversに存在するhostsファイルに新しいドメインを追加します。

hosts
127.0.0.1   localhost   example.com

これで、127.0.0.1というIPアドレスにlocalhostとexample.comというホスト名を設定できました。

Blacked Hostsの設定

Rails6を使用している場合は、アクセス可能なホストにexample.comを追加しましょう。
Blacked HostsはRails6の新機能で、ブラウザがRailsアプリケーションにアクセスする際に使用できるホスト名を制限するためのものです。
デフォルトでlocalhostのみが許可されています。

config/initializers/blocked_hosts.rb
Rails.application.configure do
  config.hosts << "example.com"
end

これで、以下サブドメインにアクセスすることができます。
http://example.com:3000/top

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