20200601のRailsに関する記事は15件です。

メモ

偶数か奇数か

puts "数字入れて"
n = gets.to_i

if n.even?
 puts "偶数です"
else n.odd?
  puts "奇数です"
end  

to_i to_s

  • to_iメソッドが文字→数値
  • to_sメソッドが数値→文字

getsは文字列で保存する。
数値に変換するため→gets.to_i

each_with_index

fruits=[“りんご”, “メロン”, “イチゴ”]

fruits.each_with_index do |fruit, i|
puts “#{i+1}番目の要素は#{fruit}です。”
end
【結果】
1番目の要素はりんごです。
2番目の要素はメロンです。
3番目の要素はイチゴです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

マイグレーション up, downメソッド

マイグレーション up, downメソッド

マイグレーションファイルで定義されるup, downメソッドについて考えていきます

テーブルの定義が書いてあるこんなマイグレーションファイルがあるとする

テーブルを定義

class CreateTasks < ActiveRecord::Migration[6.0]
  def change
    create_table :tasks do |t|
      t.string :name
      t.text :description

      t.timestamps
    end
  end
end

このテーブルの :name属性に
30文字以内という文字制限をつけたい場合にどのようなマイグレーションファイルを作るか、というのが今日のテーマ

普通に考えればこれでいい。

limit制約を付ける

class ChangeTasksNameLimit30 < ActiveRecord::Migration[6.0]
  def change
    change_column :tasks, :name, :string, limit: 30
  end
end

テーブルには望み通りの制限を課すことができる。

ところが後日、やっぱりlimit: 30はなくそうという話になった。
そこでこんなコマンドを叩いてバージョンを一つ戻そうとすると...

マイグレーションをロールバック

rails db:rollback
# => not automatically reversible エラーが発生

つまり定義されたマイグレーションファイルを自動的に戻すことができないよ
って怒られてしまう。

何が起こったの??

Railsはchange_columnのバージョンを戻す処理をバージョンを上げる際のコードから自動生成できないため、こう言ったエラーが起こってします。
つまりRailsが「このマイグレーションファイルを消した後の元の姿がわからん!!」
って言ってエラーを吐き出します。

どうするか?

upメソッドとdownメソッドを使う

ruby.rb
class ChangeTasksNameLimit30 < ActiveRecord::Migration[6.0]
  def up
    change_column :tasks, :name, :string, limit: 30
  end

  def down
    change_column :tasks, :name, :string
  end
end

upメソッドは rails db:migrateのときの処理
downメソッドは rails db:rollbackのときの処理

つまりバージョンを上げるときはupメソッドで処理をしてください。
下げるときはdownメソッドで処理をしてください。と伝えることで、

rails db:rollbackをした時にアプリケーションがどんな処理をするべきかを
伝えることができるんですね。こうすることでnot automatically reversible エラーの発生も防ぐことができますし、コードをみた人がどんな処理をしたいかもわかりやすいということですね。

めでたしめでたし。

本日はここまでです。

一人前のエンジニアになるまであと88日

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

【Rails5.2+Rspec/TDD】Rspecを導入して簡単にテストする手順(テスト駆動開発)

スクリーンショット 2020-05-31 1.36.03.png

環境

ruby 2.6.4

Rails 5.2.4.1

rbenv 1.1.2

mysql2 0.5.3

やりたいこと

TDD(テスト駆動開発)をするためにRspecを使っていきます

Rspecを使う手順を簡単に説明している記事がそこまで多くないので自分用にメモしておきます

今回は簡単な導入方法を残しておきます

元記事:【Rails5.2/TDD】Rspecを超簡単に導入する簡単手順(テスト駆動開発)

カンタン導入手順

ステップ1. 新規アプリ作成

$ rails new sample_project --api -T

ステップ2. TDD用にGem追加

Gemfile
group :development, :test do
  gem 'rspec-rails', '~> 3.5'
end

group :test do
  gem 'factory_bot_rails', '~> 4.0'
  gem 'shoulda-matchers', '~> 3.1'
  gem 'faker'
  gem 'database_cleaner'
end

ステップ3. gemインストール

$ bundle install

ステップ4. Rspecファイル生成

$ rails generate rspec:install

ステップ5. factoriesディレクトリ作成

$ mkdir spec/factories

ステップ6. rails_helper.rb修正

spec/rails_helper.rb
require 'database_cleaner'

# 追加
Shoulda::Matchers.configure do |config|
  config.integrate do |with|
    with.test_framework :rspec
    with.library :rails
  end
end

# 追加
RSpec.configure do |config|
# 追加
  config.include FactoryBot::Syntax::Methods
# 追加
  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
    DatabaseCleaner.strategy = :transaction
  end

# 追加
  config.around(:each) do |example|
    DatabaseCleaner.cleaning do
      example.run
    end

end

今回は導入のみですが実際のテストで下の記事がとても参考になります
スクリーンショット 2020-06-01 18.46.00.png

参考文献

参考にした記事です
スクリーンショット 2020-06-01 18.47.54.png

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

【Rails5】[ Turbolinks ] ページ遷移やブラウザバックでJSが動かないときの対処法

実装した機能

開発環境

ruby > 2.6.5
rails > 5.2.4.2

実装したJS

$(document).ready(function(){
   $("#menu").on("click", function() {
      $(this).next().slideToggle();
   });
});

jqueryを使って、なんの変哲もない開閉式ハンバーガーメニューをつけました。
JSのコード自体の良し悪しはおいておいて、動作としては問題ないはずです。

状況

初期ロード時には問題なく動作する。
ページ遷移、ブラウザバックのときに挙動がおかしい。
クリックで発火はしているが、開閉をループしたり、不安定。
リロードすると通常動作する。

考察と対策

動いてはいるので、おそらく読み込みのタイミングが間違っている?
ready onload ajaxStop など一通り試してみてもダメ。

グーグル先生に相談したら、こんな記述を発見

$(document).on('turbolinks:load', function () {
...
});

turbolinks:load なにこれ見たことない…
どうやらRails独自の記述らしいです。

Turbolinksの扱い

こちらの記事を参考にさせていただきました。
turbolinksチートシート

Turbolinksとは?

  • Ajaxによるページ遷移の高速化のためのライブラリ(Gem)
  • ユーザ側から見て、通常のページ遷移と同じように表示される/動作する
  • Rails4からデフォルトでインストールされている

つまり、この機能が今回のJSに影響してしまっているようです。

turbolinksをどう扱うか

Gemなので、消してしまえば解消はできますが解決にはならないので
どう扱うべきかリサーチしてみました。

主にこのような扱いがあります。

  1. <a>タグごとにturbolinksを無効にする
  2. turbolinks自体を無効化(削除)する
  3. JSの読み込み時にturbolinksを適応しない、タイミングを変える

1.<a>タグごとにturbolinksを無効にする

リンク自体に{"turbolinks" => false}を指定すると
そのリンクはturbolinksが無効になります。

<%= link_to "HOGE", root_path, data: {"turbolinks" => false} %>
<%# => <a data-turbolinks="false" href="/">HOGE</a> %>

これを記述すれば、間違いなくturbolinksを外すことができます。
特定のスクリプトのみ制御する場合は良さそうですが、さすがに全部に記述するのは厳しそうですね…

2.turbolinks自体を無効化(削除)する

Gemを削除

この一行を削除

Gemfile
#gem 'turbolinks', '~> 5'
ターミナル
$ bundle update

application.jsを編集

app/assets/javascripts/application.js
//= require turbolinks #この行を削除

application.html.erbを編集

'data-turbolinks-track': 'reload' を削除します。

app/views/layouts/application.html.erb
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

これで無効化されました。
JSなどを多用するサイトでなければ無効化してしまうのが確実かもしれません。

3.JSの読み込みにturbolinksを適応しない

ready onload などと同じように、
この記述でturbolinksを適応せずにロードできます。

$(document).on('turbolinks:load', function () {
...
});

他にも、turbolinksを適応するタイミングも変更ができます。
詳しく知りたい方はこちらを参照ください。
その他のライフサイクルイベントをとる

スクリプトごとに微調整が効くので、今回はこれが最適解だと思います。

まとめ

果たして、Turbolinksは優れた機能なのか、おせっかい機能なのか…
今の所どちらとも言えません笑
デフォルトでインストールされているということは、きっとあったほうが良いのだろうと思いますが…
もっと効果的な使用法をご存じの方はぜひコメントを下さい!

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

heroku に push しようとするとprecompiling assets failed. が起きてしまう件

環境

rails 5.2.3
Vs code

基本的な解決法

多くの場合 config/application.rb
内に config.assets.initialize_on_precompile=false
の記述を加えればこの問題は解決される。

これ以外の場合

RAILS_ENV=production bundle exec rake assets:precompile
を行いどのファイルが悪さをしているのかを調べる

自分の場合 application.css の
@import="bulma";
が悪さをしており これを削除したところdeployがうまくった
(うまくいったがbulmaを消したためビューが崩れてしまった。)

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

app/assetsやアップロードされたS3上のファイルはCloudFrontで速度改善しよう

TL;DR

コンテンツの表示速度改善にはCDN配信が有効です。
【対応前】
スクリーンショット 2020-05-06 15.35.03.png
【対応後】
スクリーンショット 2020-05-06 15.34.53.png

はじめに

アプリケーションで使用するCSSやJavascript、デザインアイコン、アップロードした画像など同一ページ内にそれらが入り混じっていると表示にかなり時間がかかりますよね。lazyloadやCache-Controlをしているけどさらに全体最適を考えている方はCDN配信を利用してみるのは如何でしょうか。

今回は詰まった箇所をまとめていくので以下の部分は省略します。

  • S3バケットの作成方法
  • Carrierwaveの初期設定
  • CloudFrontの作成方法

作成方法などは丁寧な記事がたくさんあるのでそちらを確認したほうがわかりやすいです。
S3バケットの作成、Carrierwaveの接続設定、CloudFrontの作成は済んでいる前提で進めていきます。

CloudFrontの設定

config/initializer/carrierwave.rb
config.asset_host = 'https://d3if231hoge.cloudfront.net'

https:// を付け忘れるとエラーになります。

config/environments/production.rb
config.assets.compile = true

config.action_controller.asset_host = '//d3if231hoge.cloudfront.net'

compile=false だとエラーになるようです。

ActionView::Template::Error(The asset "d1234.cloudfront.net/../hoge.png" is not present in the asset pipeline.

app/assets/

上記、各自作成したhostを設定後にbundle exec rake assets:precompileを実行するとapp/assetsにあるファイルは自動的にS3に配置されます。
 
表示する際はasset_pathで指定。相対パスではなくファイル名指定。

= image_tag asset_path('hoge.png')

Heroku運用している場合は、デプロイ時に自動でプリコンパイルしたいと思います。

その場合はheroku.ymlのreleaseブロックに追記すると自動プリコンパイルしてくれます。

heroku.yml
release:
  command:
    - rake assets:precompile 

app/assets/以外のS3配置のファイル

アプリケーション経由でS3に直接配置されたファイルはassets:precompileの対象外です。(考えてみたら当然なのですが、S3のassets配下に画像設置しているのにプリコンパイルされない!みたいなよくわからない思考になっていた時がありました..)

おわりに

app/assets周りの画像を多用しているページでCDN対応ができると、GoogleのPageSpeed Insightsで10ポイントほど上がりました。

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

metaを用いたページの自動遷移メモ(デプロイ後URL有)

3秒後に、指定のリンク先のURLに自動遷移させたい場合は下記の様なコードを記述する。

htmlファイル
%meta{content: "3;URL=指定のリンク先のURL", "http-equiv": "REFRESH"}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

has-oneとhas_manyの違いについて、まとめてみる

はじめに

railsしっかり勉強し始めて、半年くらいたちます。(多分)
最近学んだこと多いので、アウトプットしていきますー。
ちょっと説明下手だったり、間違ってたりする部分あるかもしれないので、ご了承ください!!

has_oneとhas_manyって?

両方とも、モデルの関係定義に使われるものです。

has_oneとは、1つのモデル(親)に対して、1つのモデル(子)を持つこと(1対1の関係を持つ)ができるということを定義する場合に使います。
例:)1つの投稿に対して、画像を1枚添付することができる。

has_manyとは1つのモデル(親)に対して、たくさんの同じモデル(子)を持つこと(1対多の関係を持つ)ができることを定義する場合に使います。
例:)1つの投稿に対して、画像を複数枚添付することができる。

違いについて

has_onehas_manyで関連づけられたモデルを親と関連づけて作成したい場合、それぞれ作成方法が異なるので、気をつけましょう!

実際のコードを見てみる

画像.rb
class Image < ApplicationRecord
  mount_uploader :image, ImageUploader
  belongs_to :tweet_image, foreign_key: :tweet_id, optional: true  #optional: trueをつけることによって、外部キーがなくても、保存できる
end
モデル.rb
class TweetImage < Tweet
  validates :content, presence: true, length: { maximum: 140 }
  belongs_to :user
  has_one :image, foreign_key: :tweet_id
  accepts_nested_attributes_for :image, allow_destroy: true
end

ここのコードだと、accepts_nested_attributes_for :imageを使って、TweetImageを保存する時、同時に子モデルのImageを保存するので、Imageモデルのファイルにoptional: trueをつけて、外部キーが存在しなくても保存できるようにしておくことが必要です。

class TweetsController < ApplicationController
  before_action :authenticate_user!
  def new
    @tweet = TweetImage.new
    @tweet.build_image #has_oneの関係の場合
  end
class TweetsController < ApplicationController
  before_action :authenticate_user!
  def new
    @tweet = TweetImage.new
    @tweet.images.build #has_manyの関係の場合
  end

上記は私が、制作物を作った際につかっているコードです。
関係性を図で表すとこんな感じです。

image.png

TweetとTweetImageはSTIを使った継承関係で、
TweetImageはhas_oneで画像(Imageモデル)を持っています。
コントローラはTweetのコントローラのみで管理しているので、画像を添付する場合のために必ずはじめはTweetImageである必要がありました。(accepts_nested_attributes_forを利用しているため、Formの部分に画像添付の部分を出せなくなってしまうため。)

newでモデルを作ることもできますが、IDを1回ごとに渡さないといけないので、少し面倒です。buildを使うと、自動でIDを入れてくれるので、簡潔にコードを書くことができます。

buildとnewの違い参考ページ

最後に

説明が物足りてないところがありますが、ここで終わります!
ここ違うよってとこありましたら、コメントでご指摘お願いします!!

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

【Rails】マイグレーションコマンドまとめ

開発環境

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

マイグレーションコマンドの書き方

$ rails g migration ChangeColumnToBooks は、
$ rails generation migration change_column_to_books と書くのと同じ。

つまり、generationgと略す事ができ、
AddBodyToBooksの様に、単語の先頭を大文字にする事で「 _ 」を書く手間が省ける。

基本コマンド

1.モデルとテーブルを作成

$ rails g model モデル名 カラム名:型名

ターミナル
$ rails g model Book title:string
migrate/~_create_books.rb
class CreateBooks < ActiveRecord::Migration[5.2]
  def change
    create_table :books do |t|
      t.string :title

      t.timestamps
    end
  end
end

2.モデルとテーブルを削除

rails d model モデル名

ターミナル
$ rails d model Book

3.マイグレーションを実行

ターミナル
$ rails db:migrate

4.マイグレーションの内容を戻す

①1ステップ前に戻る場合

ターミナル
$ rails db:rollback

①複数ステップ前に戻る場合

ターミナル
$ rails db:rollback STEP=5 # 数字は自由に変更可能

4.マイグレーションのステータス確認

ターミナル
rails db:migrate:status

テーブル関係

1.テーブルのみを削除

$ rails g migration Dropテーブル名

ターミナル
$ rails g migration DropBooks
migrate/~_drop_books.rb
class DropBooks < ActiveRecord::Migration[5.2]
  def change
    drop_table :books # 追記
  end
end

2.テーブル名を変更

$ rails g migration Rename変更前のテーブル名To変更後のテーブル名

ターミナル
$ rails g migration RenameBooksToArticles
migrate/~_rename_books_to_articles.rb
class RenameBooksToArticles < ActiveRecord::Migration[5.2]
  def change
    rename_table :books, :articles # 追記
  end
end

カラム関係

1.カラムを追加

①単体

$ rails g migration Addカラム名Toテーブル名 カラム名:型名

ターミナル
$ rails g migration AddBodyToBooks body:text
migrate/~_add_body_to_books.rb
class AddBodyToBooks < ActiveRecord::Migration[5.2]
  def change
    add_column :books, :body, :text
  end
end

②複数

$ rails g migration AddColumnsToテーブル名 カラム名:型名 カラム名:型名 カラム名:型名

ターミナル
$ rails g migration AddColumnsToBooks body:text introduction:text price:integer
migrate/~_add_columns_to_books.rb
class AddColumnsToBooks < ActiveRecord::Migration[5.2]
  def change
    add_column :books, :body, :text
    add_column :books, :introduction, :text
    add_column :books, :price, :integer
  end
end

2.カラムを削除

①単体

$ rails g migration Removeカラム名Fromテーブル名 カラム名:型名

ターミナル
$ rails g migration RemoveTitleFromBooks title:string
migrate/~_remove_title_from_books.rb
class RemoveTitleFromBooks < ActiveRecord::Migration[5.2]
  def change
    remove_column :books, :title, :string
  end
end

②複数

$ rails g migration RemoveColumnsFromテーブル名 カラム名:型名 カラム名:型名 カラム名:型名

ターミナル
$ rails g migration RemoveColumnsFromBooks body:text introduction:text price:integer
migrate/~_remove_columns_from_books.rb
class RemoveColumnsFromBooks < ActiveRecord::Migration[5.2]
  def change
    remove_column :books, :body, :text
    remove_column :books, :introduction, :text
    remove_column :books, :price, :integer
  end
end

3.カラムのデータ型を変更

$ rails g migration ChangeDataカラム名Toテーブル名 カラム名:型名

ターミナル
$ rails g migration ChangeDataTitleToBooks
migrate/~_change_data_title_to_books.rb
class ChangeDataTitleToBooks < ActiveRecord::Migration[5.2]
  def change
    change_column :books, :title, :text # 追記
  end
end

4.カラムのオプションを追加

$ rails g migration ChangeOptionカラム名Toテーブル名 カラム名:型名

ターミナル
$ rails g migration ChangeOptionTitleToBooks
migrate/~_change_option_title_to_books.rb
class ChangeOptionTitleToBook < ActiveRecord::Migration[5.2]
  def change
    change_column :books, :title, :string, null: false # 追記
  end
end

5.データ型一覧

型名 役割
string 短い文字列
text 長い文字列
integer 整数
float 浮動少数
decimal 精度の高い少数
datetime 日時
timestamp タイムスタンプ
time 時間
date 日付
binary バイナリ文字列
boolean 真偽値

6.よく使うオプション

オプション名 役割
default 初期値を設定
null 空欄の真偽
limit 長さを制限
unique 一意制約を付与
unique インデックスを付与
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【リファクタリング】ルーティングの書き方

概要

ルーティングをスッキリ書く方法です:relaxed:

背景
ルーティングの指定をする際、7つのアクションのうち6つを使用する場合、onlyで書いたらダラダラと長くなってしまって、個人的に自分ダサっ:weary:っとなったので備忘録として残します:bow_tone1:

Railsの7つのアクション

まずは、Railsの7つのアクションについておさらい:writing_hand:

Action 役割
index 一覧を表示する
new 追加する
create 追加内容を登録す
edit 編集する
update 編集内容を更新する
destroy 削除する
show 個別内容を表示する

書き方

:warning:ここでは「tweets」というリソースにルーティングを行います

7つのアクション全てを実装する場合

routes.rb
  resources :tweets

使用するアクションを限定する場合

:warning:ここでは「index」「new」「create」を使用することとします

routes.rb
  resources :tweets, only: [:index, :new, :create]

不要なアクションを削除する場合

:warning:ここでは「show」以外のアクションを使用することとします

routes.rb
  resources :tweets, except: [:show]

まとめ

ついつい、onlyで記入しがちですが、exceptを使用することでコードがスッキリし読みやすくなります:point_up:
私もスッキリ:sparkles:を心掛けてまいります:laughing:

参考

https://web-camp.io/magazine/archives/16815

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

メディアクエリ

レスポンシブWebデザインのメディアクエリについてのメモ

cssファイルやscssファイル内にてメディアクエリを指定することで、
タブレットやスマートフォン、または規定外の大画面にも対応できる様なcssを作成できる。
width等でのcssが切り替わる境目をブレイクポイントと呼ぶ。
ブレイクポイントは実際のビューが崩れそうなタイミングをとっても良いが、特に何もなければ、
1170pxと670px付近でブレイクポイントを取ると良い。

scssファイル
@media (min-width: 1170px {
  h1 {
    color: pink;
  }
}
@media (min-width: 670px {
  h1 {
    color:white;
  }
}
@media (max-width 670px {
  h1 {
    color: blue;
  }
}

別件だが、width: 25%; を4つ並べてビュー崩れが起こる場合は、
borderやpaddingも含まれているため、box-sizing: border-box;を与えてやると直る。
これは全てに与えてやることが推奨されている。

scssファイル
* {
  box-sizing: border-box;
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vagrant+Docker+Rails+Nuxt.js+MySQL+SSL化

はじめに

ポートフォリオ作成まで、環境構築が辛すぎたのでその過程を書きました。
完全に全ての技術に対して初心者だったので、毎日絶望していました。

ポートフォリオのために快適な開発環境をまず作りたくて試行錯誤していました。
Docker for Macが重すぎ、しかもfrontendとbackendに分けて、
しかもNginxを使ってSSL化までする記事がなさすぎて絶望したので実験しながら作りました。

今後忘れないために備忘録として・・・。
とりあえずそれぞれHello World出来るまで。

こんな人へ

とりあえずサクサクっと開発環境をつくりたいぜ。
Dockerとかの知識はちょっとあるぜ。

これを読むとわかること/おおまかな流れ

  • Vagrant環境構築
  • Nuxt.js環境構築
  • Docker環境構築
  • nuxtとRails(APIモード)とMySQLの開発環境構築
  • Nginxの環境構築
  • SSL化(オレオレ証明書)

 環境

Mac OS
ruby:2.6.3
Rails 5.2.4.3

フォルダ構成

app
├─docker-compose.yml
├─mutagen.yml
├─Vagrantfile
├─back #Rails
| ├─Dockerfile
| ├─Gemfile
| └─Gemfile.lock
├─front #Nuxst.js
| └─Dockerfile
├─nginx #nginx
| └─nginx.conf
└─ssl #nginxに読み込ませる鍵
  ├─server.crt
  ├─server.csr
  └─server.key

Vagrant

おおまかな流れ

  • VirtualBoxをinstall
  • Vagrantをinstall
  • Vagrantfile作成
  • Mutagenをinstall
  • VagrantにSSH接続する

Vagrant/Virtualboxダウンロード

https://www.vagrantup.com/
https://www.virtualbox.org/

brew cask install virtualbox
brew cask install vagrant

VagrantBox

VagrantBox(OS)のダウンロード
今回はubuntuで構築します。

vagrant box add ubuntu/xenial64
vagrant box list #確認しておきましょう

Vagrant plugin

vagrant plugin install vagrant-disksize vagrant-hostsupdater vagrant-mutagen vagrant-docker-compose

Vagrantセットアップ

作業フォルダの作成(名前はなんでも)

mkdir app
cd app

Vagrantfileの作成

/app
vagrant init ubuntu/xenial64

Vagrantfileを以下の内容に書き換えてください。

/app/Vagrantfile
Vagrant.configure('2') do |config|
  config.vm.box = 'ubuntu/xenial64'

  config.vm.hostname = 'app' #任意のホストネーム

  config.vm.network :private_network, ip: '192.168.50.10' #ここがVagrant内にアクセスするIP

  config.vm.provider :virtualbox do |vb|
    vb.gui = false
    vb.cpus = 4 #割り当てるCPUコア数
    vb.memory = 4096 #割り当てるメモリ
    vb.customize ['modifyvm', :id, '--natdnsproxy1', 'off']
    vb.customize ['modifyvm', :id, '--natdnshostresolver1', 'off']
  end

  config.disksize.size = '30GB' #ディスクサイズ
  config.mutagen.orchestrate = true

  config.vm.synced_folder './', '/home/vagrant/app', type: "rsync",
    rsync_auto: true,
    rsync__exclude: ['.git/', 'node_modules/', 'log/', 'tmp/']

  config.vm.provision :docker, run: 'always'
  config.vm.provision :docker_compose
end

MutagenのInstall

ファイル同期ソフトであるmutagenのインストールをします。
https://mutagen.io/

brew install mutagen-io/mutagen/mutagen
/app
touch mutagen.yml
vim mutagen.yml
/app/mutagen.yml
sync:
  app:
    mode: "two-way-resolved"
    alpha: "./"
    beta: "app:/home/vagrant/app" #同期させるフォルダ/Vagrantfileで設定したホストネームと合わせてください。
    ignore:
      vcs: true
      paths:
        - "/node_modules"
        - "/log"
        - "/tmp"

Vagrant起動

/app
vagrant up

はじめてVirtualBoxを入れたタイミングで「セキュリティとプライバシー」で弾かれるそうなのでダウンロードしたアプリケーションの許可をして再度upしてください。

: No such file or directory @ rb_sysopen - /Users/hoge/.ssh/config (Errno::ENOENT)

また、こんな感じのエラーが出たら、

touch /Users/hoge/.ssh/config

.ssh/configを作成してあげましょう。

仮想環境にssh接続

vagrant ssh
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-179-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

 * MicroK8s passes 9 million downloads. Thank you to all our contributors!

     https://microk8s.io/

2 packages can be updated.
0 updates are security updates.

New release '18.04.4 LTS' available.
Run 'do-release-upgrade' to upgrade to it.


Last login: Sat May 30 12:32:45 2020 from 10.0.2.2

こんな感じのログが出るとSSH接続完了です。

ちなみに

vagrant halt

も覚えておくと良いです。
同期されてねー!とか思ったらやります。vagrant環境の破棄です。(Vagrantfileが有る限りupで再度作成できるので安心)

参考記事

Docker For Macが遅い:対策の実験
Vagrantを使う「Mac最速のDocker環境」を初心者向けに解説【遅いMac for Dockerを卒業】
vagrantとDockerで環境構築をした
Docker for MacからVagrant + CoreOSに切り替えた

Docker

Dockerfile

/front/Dockerfile
FROM node:12.5.0-alpine

ENV HOME="/app" \
    LANG=C.UTF-8 \
    TZ=Asia/Tokyo

WORKDIR ${HOME}

RUN apk update && \
    apk upgrade && \
    npm install -g n && \
    yarn install &&\
    rm -rf /var/cache/apk/* s

ENV HOST 0.0.0.0

おそらく最低限の構成(もっとシンプルにできたら教えてください。)
npmとyarnをinstallしてます。VagrantなのでIPをバインディング
以下参照
rails s -b 0.0.0.0 のオプション-bの意味/バインディングアドレスとは

/back/Dockerfile
FROM ruby:2.6.3-alpine3.10

#おまじない的
ENV RUNTIME_PACKAGES="linux-headers libxml2-dev make gcc libc-dev nodejs tzdata mysql-dev mysql-client yarn" \
    DEV_PACKAGES="build-base curl-dev" \
    HOME="/app" \
    LANG=C.UTF-8 \
    TZ=Asia/Tokyo

WORKDIR ${HOME} #ワークスペースの確保

ADD Gemfile ${HOME}/Gemfile #GemfileをDocker内にコピー
ADD Gemfile.lock ${HOME}/Gemfile.lock #Gemfile.lockをDocker内にコピー

RUN apk update && \
    apk upgrade && \
    apk add --update --no-cache ${RUNTIME_PACKAGES} && \
    apk add --update --virtual build-dependencies --no-cache ${DEV_PACKAGES} && \
    bundle install -j4 && \
    apk del build-dependencies && \
    rm -rf /usr/local/bundle/cache/* \
    /usr/local/share/.cache/* \
    /var/cache/* \
    /tmp/* \
    /usr/lib/mysqld* \
    /usr/bin/mysql*

ADD . ${HOME}

ところどころわからないところがありますが・・・。ご存知の方コメントくださると有り難いです。

/app/docker-compose.yml
version: "3"

services:
  db:
    image: mysql:5.7
    env_file:
      - ./back/environments/db.env
    restart: always
    volumes:
      - db-data:/var/lib/mysql:cached

  back:
    build: back/
    command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    env_file:
      - ./back/environments/db.env
    volumes:
      - ./back:/app:cached
    depends_on:
      - db
    ports:
      - 3000:3000

  front:
    build: front/
    command: yarn run dev
    volumes:
      - ./front:/app:cached
    ports:
      - 8080:3000
    depends_on:
      - back

  nginx:
    image: nginx
    ports:
      - 443:443
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./ssl/server.crt:/etc/nginx/ssl/server.crt
      - ./ssl/server.key:/etc/nginx/ssl/server.key


volumes:
  public-data:
  tmp-data:
  log-data:
  db-data:

Gemfile

/app/back/Gemfile
source 'https://rubygems.org'
gem 'rails', '~>5'
/app/back
touch Gemfile.lock

docker-composeを使ってbuild

vagrant内/app
docker-compose build

Nuxt.js

/app
$ docker-compose run --rm front npx create-nuxt-app

? Project name                   --> sample   # アプリ名
? Project description            --> sample    # アプリの説明
? Author name                    --> me        # アプリの作成者
? Choose the package manager     --> Npm
? Choose UI framework            --> None
? Choose custom server framework --> None
? Choose Nuxt.js modules         --> Axios
? Choose linting tools           --> -
? Choose test framework          --> None
? Choose rendering mode          --> Universal (SSR)
Vagrant内/app
docker-compose up front

http://192.168.50.10:8080にアクセスしてHello World!

参考記事

Nuxt.js + Rails(API) on DockerのHello Worldするべ!

Rails

今回のRailsはAPIモードで作成するので、 --api引数をば

/app
docker-compose run --rm back rails new . -f -d mysql --api
back/config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV.fetch('MYSQL_USER') { 'root' } %>
  password: <%= ENV.fetch('MYSQL_PASSWORD') { 'password' } %>
  host: db

development:
  <<: *default
  database: webapp_development

test:
  <<: *default
  database: webapp_test

DBの環境変数のファイルを作ります。

/app/back
mkdir environments
/app/back/environments
vim db.env
/app/back/environments/db.env
MYSQL_ROOT_PASSWORD=rootpassword
MYSQL_USER=username
MYSQL_PASSWORD=userpassword

DB権限設定をするためのSQLを作ります。

/app/back/db
vim grant_user.sql
grant_user.sql
GRANT ALL PRIVILEGES ON *.* TO 'username'@'%';
FLUSH PRIVILEGES;

DBへクエリを流し込む

Vagrant内/app
docker-compose build
docker-compose up
Vagrant内/app
docker-compose ps

ちゃんとDBが動いている状態を確認

Vagrant内/app
docker-compose exec db mysql -u root -p -e"$(cat back/db/grant_user.sql)"

先ほど設定したrootpasswordを入力

Vagrant内/app
docker-compose exec db mysql -u username -p -e"show grants;"

権限の確認
先ほど設定したuserpasswordを入力

+------------------------------------------------+
| Grants for user_name@%                         |
+------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'username'@'%' |
+------------------------------------------------+

こうなればOK

Vagrant内/app
docker-compose exec app rails db:create

http://192.168.50.10:3000にアクセスしてHello World!

参考記事

Docker + Rails + Puma + Nginx + MySQL

Nginx

app/nginx/nginx.conf
worker_processes auto;

events {
  worker_connections 1024;
}

http {
  server {
    listen 443  ssl;
    ssl_certificate     /etc/nginx/ssl/server.crt; #SSL証明書
    ssl_certificate_key /etc/nginx/ssl/server.key; #秘密鍵

    proxy_set_header    Host    $host;
    proxy_set_header    X-Real-IP    $remote_addr;
    proxy_set_header    X-Forwarded-Host       $host;
    proxy_set_header    X-Forwarded-Server    $host;
    proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for;

    location /api/ {
      proxy_pass http://192.168.50.10:3000;
      proxy_buffering off;
    }

    location / {
      proxy_pass http://192.168.50.10:8091;
      proxy_buffering off;
    }
  }
}

オレオレ証明書の作成

app/
#秘密鍵の作成
sudo openssl genrsa -out app/ssl/server.key 2048
#CSR(証明書署名要求)の作成
sudo openssl req -new -key app/ssl/server.key -out app/ssl/server.csr
#CRT(SSLサーバ証明書)の作成
sudo openssl x509 -days 3650 -req -signkey app/ssl/server.key -in app/ssl/server.csr -out app/ssl/server.crt 
Vagrant内/app
docker-conpose up

https://192.168.50.10:8080にアクセスしてHello World!

Chromeで警告が出る場合

自分で発行したサーバー証明書(オレオレ証明書)をブラウザに登録する方法
こちらを参考に、ブラウザに証明書を登録してください。

参考記事

Nuxt.jsでlocalhostをSSL化する方法

最後に

かなり駆け足・長文になってしまい申し訳ありません。
読んでくださってありがとうございます。
とりあえずの備忘録として書きましたので、間違っていたらコメントで教えていただけると有り難いです。

Vagrant環境内で、Nuxt.jsとRails、しかもDockerで構築してNginxでリッスン、しかもSSL化とかいう記事は無くて
それぞれの記事をつなぎ合わせてようやく完成しました。

Docker、Vagrant、Nginx、Rails、Nuxt.jsに関しては完全に初心者です。
初めて作成するにはかなり無謀なチャレンジでした・・・。

優しいマサカリ投げていただけると嬉しいです。

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

【Rails】gretelを使ってパンくずリストを追加してみる。

パンくずリストとは

パンくずリストとはWEBサイト上で自分がどこにいるかをわかりやすく表示しているものになります。
下記サイト参考
https://www.asobou.co.jp/blog/web/breadcrumb-list

パンくずリストを導入することで
・ユーザビリティが高くなる
・SEOに強くなる
というメリットがあります。

今回はrailsにてパンくずリストを導入する手順を書いていきます。

導入

railsでパンくずを導入するには「gretel」というgemを使うと便利です。
■gem gretelのGithub
https://github.com/lassebunk/gretel

まずはGemfileに追記して、bundle installを行う。

Gemfile

gem 'gretel'
$ bundle install

その後起動コマンドを入力

$ rails generate gretel:install

このコマンドを入力すると、config配下にbreadcrumb.rbというファイルが生成されます。
そのファイルにパンくずの定義を書いていきます。

書き方の例を下記に示します。

breadcrumbs.rb
crumb :admin_dashboard do
  link '<i class="fa fa-dashboard"></i> Home'.html_safe, admin_dashboard_path
end

crumb :edit_admin_site do
  link '設定', edit_admin_site_path
  parent :admin_dashboard
end

crumb :admin_users do
  link 'ユーザー', admin_users_path
  parent :admin_dashboard
end
crumb crumsの名前を指定 do
  link '表示させたい文字', その文字のリンク先
  parent 親の指定
end

といった使い方になります。

ビュー側の表示は下記のように指定します。

<% breadcrumb :admin_users %>

slimの場合は

- breadcrumb :admin_users

参考

■パンくずリストについて参考にしたサイト
https://www.asobou.co.jp/blog/web/breadcrumb-list

■gem gretelのGithub
https://github.com/lassebunk/gretel

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

rails active_storage: install実行時に追加されるテーブルについて

active_storage使用時に作成されるテーブルとカラムの役割について自分なりにまとめてみました

参考

https://railsguides.jp/active_storage_overview.html

環境

  • Rails 5.2.4
  • PostgreSQL
  • Tweetモデルにactive_storageでtweet_imageを追加したとする
  • 同様に、Userモデルにprofile_imageを追加

$ rails dbconsoleを使ってDBの中身を見ていきます

select * from Tweet

 id | content |         created_at         |         updated_at         
----+---------+----------------------------+----------------------------
  1 | first   | 2020-05-31 09:15:39.315909 | 2020-05-31 09:15:39.34726
  2 | second  | 2020-05-31 09:41:35.573983 | 2020-05-31 09:42:03.209896

各テーブルについて

active_storage_blobs

画像データを保存するためのテーブル

select * from active_storage_blobs;

 id |           key            |                      filename                       | content_type |              metadata               | byte_size |         checksum         |         created_at         
----+--------------------------+-----------------------------------------------------+--------------+-------------------------------------+-----------+--------------------------+----------------------------
  1 | g8VoNYkesyKi779tsSdQ2q2W | first_image.jpg                                     | image/jpeg   | {"identified":true,"analyzed":true} |      8237 | zcwCqc6RTr8QFI4elbnF+w== | 2020-05-31 09:15:39.270823
  2 | uzRSGT69i5cNhoWDdoQ2gu8C | second_image.jpg                                    | image/jpeg   | {"identified":true,"analyzed":true} |   2481215 | m5LFOmNS4v3ddFGrtN/byA== | 2020-05-31 09:42:03.191085
  3 | 9o2qkgbC77MixCiYKc3thCdx | user_image.jpg                                      | image/png    | {"identified":true,"analyzed":true} |    254885 | 0+RUqCki1Yn4sZB1ZjpJCw== | 2020-05-31 19:02:28.999065

active_storage_attachment

使うモデルのクラス名を保存するポリモーフィックjoinテーブル

select * from active_storage_attachments;

 id |    name      | record_type | record_id | blob_id |         created_at         
----+--------------+-------------+-----------+---------+----------------------------
  1 | tweet_image  | Tweet       |         1 |       1 | 2020-05-31 09:15:39.324196
  2 | tweet_image  | Tweet       |         2 |       2 | 2020-05-31 09:42:03.199872
  3 | profile_image| User        |         1 |       3 | 2020-05-31 19:02:29.025411
  • name
    • 紐づけるモデルの画像用カラム
  • record_type
    • 紐づけるモデル名
  • record_id
    • record_typeのモデルのid
  • blob_id
    • active_storage_blobsに保存された画像のid

name, record_type, record_idでモデルと画像カラムを決めて、blob_idで画像を紐づけることで一意な画像投稿機能ができると考えています

最後に

おかしい部分があればご指摘いただけると嬉しいです!

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

【Rails5.2】RESTful APIをRailsで簡単に実装する手順(APIモード)

スクリーンショット 2020-05-23 17.38.46.png

環境

ruby 2.6.4

Rails 5.2.4.1

rbenv 1.1.2

mysql2 0.5.3

やりたいこと

APIモードで簡単なtodoアプリを実装します

RESTfulなAPIをRailsで実装する手順を書いていきます

わかりやすさを追求して書いていきます

元記事:【Rails5.2】RESTful APIをRuby on Railsで実装する簡単手順(APIモード)

カンタン実装手順

ステップ1. APIモードで新規アプリを作成

$ rails new sample_app --api -T

ステップ2. TDD(テスト駆動開発)用にGem追加

Gemfile
group :development, :test do
  gem 'rspec-rails', '~> 3.5'
end

group :test do
  gem 'factory_bot_rails', '~> 4.0'
  gem 'shoulda-matchers', '~> 3.1'
  gem 'faker'
  gem 'database_cleaner'
end

ステップ3. gemインストール

$ bundle install

ステップ4. Rspecファイル生成

$ rails generate rspec:install

ステップ5. factories作成

$ mkdir spec/factories

ステップ6. rails_helper.rb修正

spec/rails_helper.rb
require 'database_cleaner'

# 追加
Shoulda::Matchers.configure do |config|
  config.integrate do |with|
    with.test_framework :rspec
    with.library :rails
  end
end

# 追加
RSpec.configure do |config|
# 追加
  config.include FactoryBot::Syntax::Methods
# 追加
  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
    DatabaseCleaner.strategy = :transaction
  end

# 追加
  config.around(:each) do |example|
    DatabaseCleaner.cleaning do
      example.run
    end
end

今回は導入部分だけですがapiモードで開発する際に参考になればと思います

参考文献

今回の記事の続きはこちらです
スクリーンショット 2020-06-01 1.44.45.png

参考にした記事です
スクリーンショット 2020-06-01 1.46.35.png

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