20200524のRubyに関する記事は28件です。

Rails6.0でselectboxの複数選択をおしゃれにするJavaScriptライブラリ「select2」の導入方法

はじめに

皆様、こんにちは!
佐久間まゆちゃんのプロデューサーの@hiroki_tanakaです。

先日、Rails6.0系でselectboxの複数選択をおしゃれにするプラグインのselect2を導入することがありました。
その際にRails5系までの導入方法との違いに少しハマったので、調べたことをまとめました。

利用環境

  • Ruby 2.6.6
  • Rails 6.0.2

select2とは

select2とはHTMLのselectboxのデザインをおしゃれにするJavaScriptのライブラリです。
公式サイトはこちらです。→select2
単一選択のselectboxのUIだけでなく、複数選択のselectboxも簡単に実装する事ができるプラグインです。

公式サイト上のサンプル

  • select2導入前
    image.png

  • select2導入後の複数選択プルダウン
    image.png

Rails6.0での導入方法

Rails5系でのselect2の導入はGemを使用しての導入となっていましたが、Rails6.0からはGemではなくWebpacker使用するようになりました。
1つずつ手順を紹介したいと思います。

※Rails5でselect2の導入は下記のページが非常に詳細に説明しています。
【Rails5】Select2で複数選択可能なセレクトボックスを作る

1. yarnでselect2に必要なライブラリ導入

下記のコマンドを実行して、Railsアプリケーションにselect2を導入します。
この時、select2だけではなくselect2の導入に必要なjQuery(及びpopper.js)とselect2のUI部分に当たるbootstrapも併せて導入します。

$ yarn add jquery
$ yarn add popper.js
$ yarn add bootstrap
$ yarn add select2

2. Rails上でjQuery・popper.jsを使用できるように設定

Railsアプリケーションのwebpack/environment.jsにjQueryをRailsのどのファイルからも呼び出せるように設定します。

config/webpack/environment.js
const { environment } = require('@rails/webpacker')

// jQueryとBootstapのJSを使えるように
const webpack = require('webpack')
environment.plugins.prepend(
    'Provide',
    new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery',
        Popper: 'popper.js'
    })
)
module.exports = environment

また、packs/application.jsのマニュフェストにJQueryを追加します。

app/javascript/packs/application.js
require("jquery")

3. Rails上でbootstrapを使用できるように設定。

下記の2つの設定を行い、Railsアプリケーションでbootstrapを使用できるように設定します。

app/javascript/packs/application.js
import 'bootstrap';
import '../stylesheets/application';
app/javascript/stylesheets/application.scss
@import '~bootstrap/scss/bootstrap';

4. erbファイルでwebpackerを使用するように設定。

Railsアプリケーションの全てのViewファイルでwebpackerに導入したbootstrap・jQueryが使用できるように大元のlayouts/application.html.erbに設定します。

app/views/layouts/application.html.erb
<head>
<%= stylesheet_pack_tag "application", media: "all" %>
<%= javascript_pack_tag 'application' %>
</head>

5. selectboxをerb上に定義し、select2を使用するようにJSファイルに記載。

アプリケーションのerb上に複数選択を行うselectboxを定義します。
この時、select_tagはmultiple: trueとoption設定すれば、複数選択可能なselectboxとなります。

そして、該当のselectboxがselect2を使用するようにerbファイルに対応するJSファイルに記載します。

app/views/test.html.erb
<%= javascript_pack_tag 'test' %>
<%= select_tag('animal', options_for_select([['いぬ', 'dog'], ['ねこ', 'cat'], ['とり', 'bird'], ['うし', 'cow'], ['へび', 'snake']]), class: "form-control", multiple: true) %>
app/javascript/packs/test.js
$(function () {
    $('#animal').select2();
});

6. 完成!!

image.png

おまけ:select2のoption利用

select2には様々なoptionが用意されています。→select2 Options
これらのoptionはjQueryで設定することが可能です。
下記はoption設定の一例です。

app/javascript/packs/test.js
$(function () {
    $('#animal').select2({
        width: 'resolve' // 幅をページサイズに併せて動的に変更する。
        theme: "classic" // クラシックUIに変更する。
        debug: true // ブラウザのコンソールにデバッグメッセージを出力する。
    });
});

おわりに

yarnを使用することでselect2の導入が更に簡単になったように感じます。
ただ、select2の内部挙動に関してはわからないことが多いので理解を深めたいです。

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

ActiveModel::Serializerのテストでつまづいたこと

はじめに

ActiveModel::SerializerのRspecでテストの書き方の例を挙げました。
ですが、他のSerializerのテストを書く時につまづいたことがあるので、投稿します。

ソースコード

今回の例は、ArticleとCategoryが多対多の関係にあり、article_category.rbという中間モデルを持っているとします。

article.rb
class Article < ApplicationRecord
  has_many :article_categories
  has_many :categories, through: :article_categories
end
article_serializer.rb
class ArticleSerializer < ActiveModel::Serializer
  attributes :id, :title
  has_many :categories
end

このSerializerのテストを書くとこんな感じ

article_serializer_spec.rb
require 'rails_helper'

RSpec.describe ArticleSerializer, type: :serializer do
  context "新たに記事が作成された時" do
    let(:article) { create(:article) }
    let(:category) { create(:category) }
    let(:article_category) do
      create(:article_category, category: category, article: article)
    end

    it "シリアライズされたJSONが作成されること" do
      serializer = ArticleSerializer.new(article)
      expect(serializer.to_json).to eq(article.to_json(:only => [:id, :title], :include => { :category })
    end
  end
end

テスト結果

テストしてみると、返却されたJSONにhas_many関係のcategoryが含まれておらず、空のままでした。なぜ、、、

解決方法

このテストの書き方が悪かったようで、このように書いたら通りました。

article_serializer_spec.rb
require 'rails_helper'

RSpec.describe ArticleSerializer, type: :serializer do
  context "新たに記事が作成された時" do
    let!(:article) { create(:article) }
    let!(:category) { create(:category) }
    let!(:article_category) do
      create(:article_category, category: category, article: article)
    end

    it "シリアライズされたJSONが作成されること" do
      serializer = ArticleSerializer.new(article)
      expect(serializer.to_json).to eq(article.to_json(:only => [:id, :title], :include => { :category })
    end
  end
end

変更点は、letlet!としたところです。
letのままだとexampleの中で作られるオブジェクトは、articleだけです。
なぜかというと、letではそのオブジェクトがexampleの中に出てくるときにのみオブジェクトが作成されるからです。

というわけで、このような例ではlet!を使うといいですね!

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

【Rails】モデルの使い方がイマイチわからない…(クラスメソッドとか意味不m…)

経緯

現在、とあるプログラミングスクールに通っているのですが、検索機能(検索窓)を実装する際に、処理をモデルとコントローラーを使い分けるように言われました。
えー… 全部コントローラーでいいじゃん…(もちろん、今では積極的に分けて使用していますよ!)

・モデルからデータを取得したり、保存したり単純な処理のみ記載
・モデル取得した値に複雑な処理を行うものを記載
というイメージで使い分けています。

ただ、何故モデルで設定した『処理のカタマリ』をコントローラーで使えるのか理解できなかったので使いたくなかった、、いや使えなかったんですよね。
(この記事は検索機能の解説をするための記事ではありません。あくまでモデルの使い方について私の頭の整理です。)

検索機能の実装

models/tweet.rb(モデル)
class Tweet < ApplicationRecord
  validates :text, presence: true
  belongs_to :user
  has_many :comments

  def self.search(search)
    return Tweet.all unless search
    Tweet.where('text LIKE(?)', "%#{search}%")
  end

end

※2〜4行目は必要のない記載ですが、あえて「モデルに書いてるよ」ってわかるように残してます。
また、見やすいように謎の改行が入っておりますがご容赦ください。

controllers/tweets_controller.rb(コントローラー)
class TweetsController < ApplicationController

  def search
    @tweets = Tweet.search(params[:keyword])
  end

end


理解不明ポイント

①コントローラーの「search」メソットって何?(リファレンスに載ってないぞ??)

リファレンスになんぞ載っていいる訳ないのです。
なぜなら「モデルで自作したメッソド」だから!!

②モデルの「self」ってなに?(ググると、当たり前のように「クラスメソッド」って言われますが…だから何??)

  • ここで詳しい説明はしませんが、こいつにはクラス名が代入されます。 (代入という表現はわかりやすくするために使用しています)
  • tweet.rb(tweetモデル)の一行目を見てください。クラス名、なんだかわかりましたよね?
  • つまり、「self.search(search)」は「「Tweet.search(search)」なんです。(どっかで見たような、)

③何故モデルで設定した『処理のカタマリ』をコントローラーで使えるの?(いよいよ本題です)

なんとなく分かってきましたかね??

  • コントローラーで使用している「Tweet.search(params[:keyword])」はモデルで自作したメソッド「self.search(search)」と同じなんです。

メソッドの正体

我々がよく使っている「findメソッド」や「includeメッソド」等の様々なメソッドって実は、
今回「searchメソッド」を自作したようにRailsのActiveRecordが作ってくれているんです!!

各モデルがActiveRecordを継承しているから、コントローラーでメソッドを使えているんですね!
(厳密には class Tweet < ApplicationRecord < ActiveRecord::Base)
tweet.rb(tweetモデル)の一行目を見れば記載がありますね。

アイツ

さて、長くなってきましたが一つ解決してないヤツがいますよね。
そう、結局「self = クラスメソッド」って何だったのか。

クラスメソッドは読んで字の如く、「クラス」に対して使用できるメソッドです。
「クラス」って何だったか思い出せますか??
わからない方はtweet.rb(tweetモデル)の一行目を見てみてください。

私もこれ以上はまだ理解できてません!!笑

謝辞

ちょっとわかりにくい説明だったかもしれませんが、プログラミング歴2ヶ月なので許してください。
(自分の頭は割と整理できました。)
ここまで長々と書かせていただきましが、最後まで読んでいただきありがとうございます。

もし、解釈が間違っている場合は、教えていただけるととても嬉しいです。

どんどはれ。

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

複数のRedmineインスタンスを1つのサーバー内で立ち上げ

Redmineが大量乱立

 Redmineは便利なので、社内ではプロジェクトごとにサーバーを立ち上げています。いつのまにか、30以上のredmineサーバーが乱立しています。もちろん各Redmineごとに物理サーバーを立ち上げているわけではなく、ほとんどが社内にある物理サーバーマシン上の仮想サーバーを作成しています。それでも1サーバーにこれだけの仮想サーバーを立ち上げると不安定になるので、終了したプロジェクトのRedmineサーバーは電源を落としたりしています。
 こんなにRedmineを乱立させなくても、Redmine内でプロジェクトを複数作れば、と思われるかもしれませんが、Redmineユーザーの権限が細かく設定できなかったり、プロジェクトをグループ化したりできないので、結局プロジェクト毎にRedmineを立ち上げてきました。
 さらに、Redmineは常にバージョンアップしていますが、稼働しているRedmineに対してのバージョンアップもリスクが伴います。Redmine/ruby/rails/gem等のバージョン依存も激しいのも、バージョンアップを避けている理由(言い訳)です。

複数のRedmineを1つのサーバーに収容しよう

 今まで1つのサーバーに複数のRedmineを収容してこなかったのは、公式のドキュメントでそのようなインストール方法が説明されていないというのも理由です。複数のRedmineを同居させる事例も意外と少ないです。
 ですが、さすがにもうそろそろRedmineもrubyも安定しているだろうと覚悟し、今後は複数のRedmineインスタンスを1サーバーで新規運用することにします。

まずはRedmineをインストール

 Redmineを公式ドキュメントに沿ってインストールします。公式ドキュメントもバージョン等古い記述も含まれていますが、インストール環境のOSはCentOS7、Redmineバージョンは4.0、Apache+Passenger環境、MariaDB5.5(MySQL互換)とします。

 http://redmine.jp/install/

BitNamiのパッケージでの一括インストールも試しましたが、ApacheがCentOS標準と異なる起動方法だったので、今回は採用せずに手動でインストールを行いました。

ここまでで新規にRedmineがPassangerとともにインストールされた直後ということで進めます。以下の操作の前提はroot権限でログインし、Redmineのインストール場所は /var/lib/redmine とします。

2つめのRedmineをコピー

 まずは念の為Apacheを停止します。

# systemctl stop httpd.service

 インストールされた現在のRedmineを、テンプレートとして保存しておきます。

# mv /var/lib/redmine /var/lib/redmine.template

テンプレートから1番めのRedmineと2番めのRedmineをコピーします。

# cp -p -r /var/lib/redmine.template /var/lib/redmine1
# cp -p -r /var/lib/redmine.template /var/lib/redmine2

2番めのRedmineのユーザーとデータベースを作成します。

# mysql -u root -p 
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 180
Server version: 5.5.64-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> CREATE DATABASE redmine2 CHARACTER SET utf8;
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> CREATE USER 'redmine2'@'localhost' IDENTIFIED BY 'password';
Query OK, 0 rows affected (0.01 sec)

MariaDB [(none)]> GRANT ALL PRIVILEGES ON redmine2.* TO 'redmine2'@'localhost';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> quit;
Bye

2番めのRedmineデータベースの設定にあわせて、/var/lib/redmine2/config/database.yml ファイルを修正します。

database.yml
production:
    adapter: mysql2
    database: redmine2
    host: localhost
    username: redmine2
    password: password
    encoding: utf8

2番めのRedmineの新しいセッション保護用の秘密鍵を生成します。

# cd /var/lib/redmine2
# bundle exec rake generate_secret_token

 2番めのRedmineのデータベースのマイグレーション(?=データ初期化?)を行います。下記の3行め最終行は、プラグインがインストールされてていれば必要のようです。(私はプラグインを追加していないので実施しませんでした)

# cd /var/lib/redmine2
# bundle exec rake db:migrate RAILS_ENV=production
# bundle exec rake redmine:plugins:migrate RAILS_ENV=production

 実行中メッセージが流れますが、最後にエラーメッセージが出ていなければ完了です。
 エラーが出た場合は、追加したデータベースにアクセスできるか確認しましょう。

Redmine1/Redmine2のテスト

 これで2つのRedmineが独立してインストールされたはずです。テストするには(しなくてもいいですが)、各Redmineディレクトリに移動し以下のようにRedmineを実行します。

# cd /var/lib/redmine1
# bundle exec rails server webrick -e production

手元のPCブラウザで、「http://IPアドレス:3000」とすることで、Redmineの動作を確認できます。アクセスするとRedmine側のサーバー画面上にアクセス状況のログが流れます。終了するには、Redmine側で「CTRL+C」を押して停止します。

 同様に、2番めのRedmineの動作を確認します。

# cd /var/lib/redmine2
# bundle exec rails server webrick -e production 

コピーしている同じRedmineですので、Redmine1もRedmine2も実際にはどちらか判別できません。ログインしたらウェルカムメッセージを書き換えれば、判別しやすくなります。こちらもRedmine側で「CTRL+C」を押して停止します。

 テストをして2つのRedmineを切り替えられましたが、同じポートを使っているので、同時に起動することはできません。同時に起動するには、ポートを変えて起動する方法もありますが、Apacheのバーチャルホスト機能と、サブディレクトリを変えてアクセスする2つの方法を試してみます。

 下記のケース1とケース2は、どちらかを選択してください。

ケース1:バーチャルホスト機能で複数のredmineを設定

 ここまでで、独立したRedmine1/Redmine2が、別々にインストールされて実行できるようになりました。ここで、Apacheのバーチャルホスト機能で、

のアクセスとなるよう設定します。もちろん、DNSサーバーの設定で、redmine1.hogehoge.com/redmine2.hogehoge.comとも同じサーバーを指すようにAレコードまたはCNAMEの設定が必要です。

 DNSの設定と反映を確認したら、Apacheの設定ファイルを変更します。httpd.confの末尾に以下のように変更追記します。

/etc/httpd/conf/httpd.conf
・
・
##ここから追加変更

# サーバーデフォルトのドキュメントルート設定
<VirtualHost *:80>
 ServerName 127.0.0.1
 DocumentRoot /var/www/html
</VirtualHost>

# Redmine1(redmine1.hogehoge.com)の設定

<Directory "/var/lib/redmine1/public">
  Require all granted
</Directory>

<VirtualHost *:80>
 ServerName redmine1.hogehoge.com
 DocumentRoot "/var/lib/redmine1/public"
 PassengerAppRoot /var/lib/redmine1
 RailsBaseURI /
</VirtualHost>

# Redmine2(redmine2.hogehoge.com)の設定

<Directory "/var/lib/redmine2/public">
  Require all granted
</Directory>

<VirtualHost *:80>
 ServerName redmine2.hogehoge.com
 DocumentRoot "/var/lib/redmine2/public"
 PassengerAppRoot /var/lib/redmine2
 RailsBaseURI /
</VirtualHost>

 既にPassenngerが設定済みであるという前提ですので、追加するのは各Redmineごとにディレクトリのアクセス許可とバーチャルホスト設定になります。

 設定変更後にApacheを起動します。

# systemctl start httpd.service

エラーが無くApacheが起動したら、

 がそれぞれ redmine1/redmine2が起動して操作できるのを確認してください。

各Redmineをアクセスした後は、しばらく以下のようにPassengerプロセスにも表示されるはずです。

# ps ax | grep Passenger
19815 ?        Sl     0:03 Passenger AppPreloader: /var/lib/redmine1
19865 ?        Sl     0:01 Passenger AppPreloader: /var/lib/redmine1 (forking...)
19920 pts/0    S+     0:00 grep --color=auto Passenger
22015 ?        Ssl    0:00 Passenger watchdog
22018 ?        Sl     0:33 Passenger core
27829 ?        Sl     0:04 Passenger AppPreloader: /var/lib/redmine2
27877 ?        Sl     0:01 Passenger AppPreloader: /var/lib/redmine2 (forking...)
#

Passengerから、Redmine1/Redmine2のそれぞれを起動しているのが確認できます。しばらくアクセスが無いと該当のPassengerプロセスも消滅します。

 この手順で、1つのサーバーに別々のホスト名をつけた複数のRedmineをいくつも立ち上げることができます。

ケース2:サブディレクトリで複数のredmineを設定

 次はサブディレクトリでの複数のRedmineの設定です。

のアクセスとなるよう設定します。ホスト名の代わりにIPアドレスでも大丈夫です。

 Apacheの設定ファイルを変更します。httpd.confの末尾に以下のように変更追記します。

/etc/httpd/conf/httpd.conf
・
・
##ここから追加変更

# Redmine1(/redmine1)の設定

<Directory "/var/lib/redmine1/public">
  Require all granted
</Directory>
Alias /redmine1 /var/lib/redmine1/public
<Location /redmine1>
  PassengerBaseURI /redmine1
  PassengerAppRoot /var/lib/redmine1
</Location>

# Redmine2(/redmine2)の設定

<Directory "/var/lib/redmine2/public">
  Require all granted
</Directory>
Alias /redmine2 /var/lib/redmine2/public
<Location /redmine2>
  PassengerBaseURI /redmine2
  PassengerAppRoot /var/lib/redmine2
</Location>

 設定変更後にApacheを起動します。

# systemctl start httpd.service

エラーが無くApacheが起動したら、

 がそれぞれ redmine1/redmine2が起動して操作できるのを確認してください。

各Redmineをアクセスした後は、しばらく以下のようにPassengerプロセスにも表示されるはずです。

# ps ax | grep Passenger
30318 ?        Ssl    0:00 Passenger watchdog
30323 ?        Sl     0:00 Passenger core
30349 ?        Sl     0:03 Passenger AppPreloader: /var/lib/redmine1
30396 ?        Sl     0:00 Passenger AppPreloader: /var/lib/redmine1 (forking...)
30429 ?        Sl     0:03 Passenger AppPreloader: /var/lib/redmine2
30477 ?        Sl     0:00 Passenger AppPreloader: /var/lib/redmine2 (forking...)
30517 pts/0    R+     0:00 grep --color=auto Passenger
# 

Passengerから、Redmine1/Redmine2のそれぞれを起動しているのが確認できます。しばらくアクセスが無いと該当のPassengerプロセスも消滅します。

 この手順で、1つのサーバーに別々のサブディレクトリ名で複数のRedmineをいくつも立ち上げることができます。

まとめ

 思ったよりすんなりと設定できました。ホスト名でもサブディレクトリ名でも問題なく複数のRedmineがアクセスできます。応用すれば https でも設定できるでしょう。
しばらく運用して問題は出ていませんが、これで完全に正しいかどうかはわかりませんので、自己責任でお願いします。
 将来のRedminemのバージョンアップのことは考えないことにしましょう(笑)

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

忘れがちなrubyの基礎知識を復習

はじめに

改めてrubyの基本的な記法を復習するための記事になります。

・あるオブジェクトを文字列に変換するto_sメソッド

# 文字列→文字列
'1'.to_s   # => "1"

# 数値→文字列
1.to_s     # => "1"

# nil→空白の文字列
nil.to_s   # => ""

# 真偽値true→文字列の"true"
true.to_s   # => "true"

# 真偽値のfalse→文字列の"false"
false.to_s   # => "false"

メソッドの呼び出し方

# 通常の書き方
オブジェクト.メソッド(引数1, 引数2, 引数3)
# カッコを省略しても良い
オブジェクト.メソッド 引数1, 引数2, 引数3
# 引数がない場合
オブジェクト.メソッド

変数名の作り方

# 変数名はスネークケースが望ましい
first_name = user.first_name

# キャメルケースは慣習的に使用しない
firsfName = user.first_name

# 数字から始まる変数はエラーになり使用できない
2_discount_price = 200

文字列について

シングルクオート('')を使用しても、ダブルクオートを使用しても("")文字列を表現することができる。
使い分けとしては、基本的にはシングルクオートを使い、式展開する場合はダブルクオートを使用する

# 文字列
'これは文字列'
"これは文字列"

# 式展開する場合
i = '文字列'
"これは#{i}"  # => これは文字列

論理演算子||と&&

# &&はANDの論理演算
# 条件1も条件2も真であれば真、それ以外は偽となる
条件1 && 条件2

t1 = true
t2 = true
f1 = false
t1 && t2      # => true
t1 && f1      # => false

||はORの論理演算

## 条件1も条件2のいずれかが真であれば真、両方偽であれば偽となる
条件1 || 条件2

t1 = true
t2 = true
f1 = false
f2 = false
t1 || t2      # => true
t1 || f1      # => true
f1 || f2      # => false

?で終わるメソッド

?で終わるメソッドは慣習的に真偽値を返すメソッドになります。

# 空文字列であればtrue、文字が入っていればfalseを返すempty?メソッド
''.empty?           # => true
'あいうえお'.empty?   # => false
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ネストされたフォームにより関連付けられたモデルにデータを同時保存する方法(Rails 6.0.0)

結論 親モデルにaccepts_nested_attributes_forを追加する

実証環境

・Cloud9 Ubuntu Server
・Rails 6.0.0
・Ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]

前提条件

次のような一対多のリレーションを持つParentモデルとKidモデルがあるとします。
※1:混乱を避けるため、「Parentって父親?母親?」とかは考えないものとします。
※2:モデル名に不規則変化の名詞を用いるとややこしいので、childではなくkidを用いています。
ペアレントモデルとキッドモデル

models/parent.rb
class Parent < ApplicationRecord
  has_many :kids, dependent: :destroy
end
models/kid.rb
class Kid < ApplicationRecord
  belongs_to :parent
end

ネストしたフォームの実装

親モデルのデータ保存時に子モデルのデータも同時に保存するため、accepts_nested_attributes_for
をParentモデルに追加します。

models/parent.rb
class Parent < ApplicationRecord
  has_many :kids, dependent: :destroy
  accepts_nested_attributes_for :kids
end

これによって関連付けたデータを1つのフォームで登録できるネストしたフォームを使用できるようになります。

次に、親モデルのParentsコントローラーにて、フォームのページから送られてくるparamsを受け取る空のインスタンスを作ります。

その際、関連付けられた子モデルの空のインスタンスも作成します。
また、子モデルのpramsを受け取るために、ストロングパラメーターに
kids_attributes: [:name, :age, :toy]
を渡しています。

controllers/parents_controller.rb
class ParentsController < ApplicationController

#(中略)

  def new
    @parent = Parent.new
    @parent.kids.build #子モデルの空のインスタンスを作成
  end

  def create
    @parent = Parent.new(parent_params)
    if @parent.save
      redirect_to root_url
    else
      render :new
    end
  end

#(中略)

  private

    def parent_params
      #子モデルのパラメーターを受け取れるようにする
      params.require(:parent).permit(
        :name, :age, kids_attributes: [:name, :age, :toy] 
      )
    end

end
new.html.erb
<div class="container">
  <div class="col-sm-10 col-sm-offset-1">
    <h1 class="text-center">親登録</h1>
    <%= form_with(model: @parent, local: true) do |f| %>
      <div class="field form-group">
        <%= f.label :name %>
        <%= f.text_field :name, class: "form-control" %>
      </div>
      <div class="field form-group">
        <%= f.label :age %>
        <%= f.number_field :age, class: "form-control" %>
      </div>

      <!-- 子モデルのデータを受け取るためのネストされたフォーム -->

      <%= f.fields_for :kids do |kf| %>
      <h1 class="text-center">子登録</h1>
        <div class="field form-group">
          <%= kf.label :name %>
          <%= kf.text_field :name, class: "form-control" %>
        </div>
        <div class="field form-group">
          <%= kf.label :age %>
          <%= kf.number_field :age, class: "form-control" %>
        </div>
        <div class="field form-group">
          <%= kf.label :toy %>
          <%= kf.text_field :toy, class: "form-control" %>
        </div>
      <% end %>

      <div class="field form-group">
        <%= f.submit "上記内容で登録する", class: "btn btn-primary btn-lg btn-block" %>
      </div>
    <% end %>
  </div>
</div>

Bootstrapのクラスが入っており見にくいですが、上記のf.fields_forが子モデルのデータを受け取るフォームになります。
ネストされたフォーム

データ更新(update)時に新たな関連付けられたデータを保存できるようにする

子モデル用の入力フォームですが、空のインスタンスを複数個作成することで、view自体のフォームは増やさずに入力欄を増やすことができます。
例えば、Parentsコントローラーを次のように変更することで、新規登録時には1組の子モデル入力フォーム、更新時には2組の子モデル入力フォームを表示させることができます。

controllers/parents_controller.rb
class ParentsController < ApplicationController

#(中略)

  def new
    @parent = Parent.new
    @parent.kids.build #子モデルの空のインスタンスを作成
  end

  def create
    @parent = Parent.new(parent_params)
    if @parent.save
      redirect_to root_url
    else
      render :new
    end
  end

#(中略)

  def edit
    @parent = Parent.find(params[:id])
    @parent.kids.build #子モデルの空のインスタンスを作成
  end

  def update
    @parent = Parent.find(params[:id])
    if @parent.update(parent_params)
      redirect_to root_url
    else
      render :edit
    end
  end

  def destroy
    @parent = Parent.find(params[:id])
    @parent.destroy
    redirect_to root_url
  end

  private

    def parent_params
      params.require(:parent).permit(
        :name, :age, kids_attributes: [:name, :age, :toy]
      )
    end

end

editアクションでも子モデルの空のインスタンスを作成することで、更新(update)時に「登録されている子モデルのデータ」+1個の入力フォームが作成されます。

これにより、JSなどで動的に追加するよりも簡便に入力フォームを増やすことができます。(個数が限定されてしまうのがネックですが...)

追加されるフォームをさらに増やしたい場合は、生成する空のインスタンスの数を
@parent.kids.build
から
n.times { @parent.kids.build }
とすることで、n個の入力フォームを生成できます。

入力されなかった場合の空データを保存されないようにする

しかし、このままでは追加されたフォームに入力されなかった場合に空のデータが保存されてしまいます。
それを防ぐためにはParentモデルに追加したaccepts_nested_attributes_forの第2引数に次のようなProcを渡します。

models/parent.rb
class Parent < ApplicationRecord
  has_many :kids, dependent: :destroy
  accepts_nested_attributes_for :kids, reject_if: lambda {|attributes| attributes['name'].blank?}
end

上記の場合、子モデル入力フォームのnameが空の場合は他の属性(ここでは、age、toy)が入力されていても全て保存されません。

nameまたはageが入力されていない場合に登録させたくない場合は次のように変更します。

models/parent.rb
class Parent < ApplicationRecord
  has_many :kids, dependent: :destroy
  accepts_nested_attributes_for :kids, reject_if: lambda {|attributes| attributes['name'].blank? || attributes['age'].blank?}
end

上記に加え、子モデルへのバリデーションも変更すれば、保存される値を自由に制御できます。

この他、関連付けた子モデルのデータのみを削除したい場合などもあると思いますが、詳しくはRailsガイドの「Action View フォームヘルパー」がとても参考になります。

あとがき

現在Ruby on Rails学習中の初学者・タツロンです。
自作アプリ作成中に数日間に渡って詰まった機能に関して投稿させていただきました。
間違っている点やアドバイス等ございましたらコメント頂けば幸いです。

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

【Rails】fields_forが表示されない

今回は、「fields_for」で「file_field」を使用しようとしたところ、ビューに反映されずに苦戦したので、備忘録として解決した方法を記載します。
同じ悩みを抱えた方の一助になると幸いです。

※この記事ではfields_for とaccepts_nested_attributes_for を使ったフォーム作成手順を解説するものではありません。

今回登場するモデル

・(親)postモデル
・(子)imageモデル

postモデルとimageモデルaccepts_nested_attributes_forでアソシエーションしております。

想定

ツイッターやFBのようなSNSを作成。
「form_for」を用いて投稿フォームを作成するところです。

文章 →postモデル
写真 →imageモデル
に保存したく、以下のようにビューを作成しました。

間違えたコード

(わかりやすいように関係箇所のみ抜粋してます)

haml
.form__contents
  = form_for @post, id: "new_post" do |f|
    .title
      = f.text_field :title
    .text
      = f.text_area :text
    .image
      = f.fields_for :images do |i|
        = i.file_field :image
    = f.submit "投稿!"

よし、コーディング完了!!いざビューへ!!
…あれ、、「= f.fields_for :images do |i| 」以下が反映されてないぞ…
しかもエラーも出てないから何が悪いのかわからない…調べた通りやったのに…

上手く行ったコード

haml
.form__contents
  = form_for @post, id: "new_post" do |f|
    .title
      = f.text_field :title
    .text
      = f.text_area :text
    .image
      = f.fields_for :images, @post.images.build do |i|
        = i.file_field :image
    = f.submit "投稿!"

まとめ

私はてっきり「fields_for」では保存したいモデルを書けば「file_field」で記載したカラムに保存してもらえるとばかり思っていたのですが、

「fields_for」の第二引数に子モデルのインスタンスも渡してあげないとダメみたいでした。

なるほど…たしかに「form_for」でもインスタンス渡してあげてるんだから当たり前か。
(そもそも images.build インスタンス作れるって初めて知りました!)

どんどはれ。

参考させていただいたサイト

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

【環境構築 Mac】Ruby on Rails (+Webpackerでエラーの対処)

初めに

Ruby on Railsの環境構築を行いましたので、記録します。

【構築環境】
・Rails6
・Ruby 2.6.3

【マシンスペック】
・macOS Catalina
・バージョン 10.15.3
・iMac(retina 4K, 21.5-inch,2019)
・プロセッサ 3 GHz 6コアIntel Core i5
・メモリ 8GB

【使用エディター】
VScode
(https://azure.microsoft.com/ja-jp/products/visual-studio-code/)

構築手順

Command Line Toolsのインストール

こちらでは、AppleIdが必要になります。
Id・パスワードを忘れている場合は事前に準備してください。

①Appleのdeveloperアカウントページにログイン
https://developer.apple.com/account/#/welcome

②See more downloadsからダウンロードリストページへ
https://developer.apple.com/download/more/

→OSに対応したCommand Line Toolsをダウンロードしてください。

Homebrewのインストール

①Homebrewの公式サイトへ行き、記載されているコマンドを「ターミナル」に貼り付けてください。
(Homebrewの公式サイト)https://brew.sh/index_ja

※私の場合は以下のコマンドでした。

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

②Homebrewのインストールの確認
インストールが無事されたか不安なので、確認をします。

brew -v

※私の場合は以下のコマンドでした。

Homebrew 2.2.17
Homebrew/homebrew-core (git revision 572fc; last commit 2020-05-24)

rbenvのインストール

①rubyのバージョン管理ができるようインストールします。

brew install rbenv ruby-build

②インストールが完了したら、以下のコマンドで確認してみてください。

rbenv -v

※私の場合は以下のコマンドでした。

rbenv 1.1.2

Rubyのインストール

ここからは、Rubyをインストールしましょう。
※Rubyについては、使用者によりは、もうインストールされているかもしれません。

①インストールされているか確認します。

ruby -v

※私の場合は以下のコマンドでした。

ruby 2.6.3p62 (2019-04-16 revision 67580) [universal.x86_64-darwin19]

もうインストールしてたいましたが、もしインストールされていない様でしたら、以下でインストールしてください。

②インストールされていない場合
以下のコマンドで、インストール可能なRubyのバージョンを確認します。

rbenv install --list

確認できたら、以下を実行、
数字は「rbenv install --list」で実行されたバージョンを指定します

rbenv install ●●●●
rbenv global ●●●●
rbenv rehash
ruby -v

バージョンがインストールされているか確認のため「ruby -v」を行いました。

Bundlerのインストール

①以下のコマンドを実行して、インストールしてください。

gem install bundler

②確認します。

bundle -v

my SQLのインストール

①my SQLをインストールして起動します。

brew install mysql

②my SQLを確認してください

mysql.server start

Railsのインストール

①ディレクトリを制作しましょう
●は、任意のファイル名で記入してください。

mkdir ~/●●●●●●●

②制作したフォルダーに移動

cd ~/workspace

③Gemfileを作成する

bundle init

④Gemfileの中を編集・コメント解除
「mkdir ~/●●●●●●●」で制作したフォルダには「Gemfile」があります。
エディターソフトで、それを起動してください。

ファイルの中には# gem "rails"がメモ表記になっているので、コメント解除をしてください。

⑤Railsのインストール

bundle install --path=vendor/bundle

⑥Railsがインストールか確認

bundle exec rails -v

※私の場合は以下のコマンドでした。

Rails 6.0.3.1

Railsでテストファイルを作成

①制作したいファイル先を指定

cd desktop
※私の場合はデスクトップ上に制作しました
また、こちらの制作時はRailsのインストール先のパスが異なります。
私は、新しくvscodeで新しくターミナルを制作していますのでご注意ください。

②Railsで新規ファイルを制作
●は任意のファイル名です。

rails new ●●●●●

しかし

私はここでエラーが発生!!
原因は「Webpackerでエラー」でした。
以下の作業を行います。

Webpackerのインストール

①yarnがインストール

brew install yarn

②下記のコマンドを実行してください。

rails webpacker:install

でも「yarn」がインストールされていない!
と言われているので下記のコマンドを実行します。

Railsの起動

①ブラウザを立ち上げるコマンドを実行する
以下のコマンドを実行してください

rails s

②ローカルサーバを起動

http://localhost:3000

→無事に起動しました。
よかった!

参考記事

Ruby初学者のRuby On Rails 環境構築【Mac】
Homebrewのインストール
Rails6 Webpackerでエラーが出た

参考記事様には、とても助かりました。
ありがとうございます。

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

メソッドに引数を渡し演算の結果を返り値として受け取る

引数がよく分からない

「Mr.Yuki」と出力したいのですが…

1 def rename(name)
2  name = "Mr.#{name}"
3 end
4
5 name = "Yuki"
6 rename(name)
7 puts name
Yuki

この構文では、出力にMr.はつかない「Yuki」になります。

1 def rname(name)         # renameメソッドで受け取る変数name
2   name ="Mr.#{name}"    # renameメソッドで受け取る変数name
3 end

メソッドの変数には引数で渡した値のコピーが代入されている。

5 name = "Yuki"    #このnameは全て引数のname
6 rename(name)
7 puts name

要するに、引数のnameと変数nameは同じ名前だが別物である

順番を追って解説。

  • 5行目:引数nameに文字列 "Yuki"が代入される
  • 6行目:このnameを引数として、メソッドrenameを呼び出す  この時にnameのなかに入っている値がコピーされる
  • 1行目:コピーされた"Yuki"はメソッドrenameの変数nameに代入される。  よって引数nameとメソッドで使われる変数nameが同じ値となり、メソッドに値を渡すことができる
  • 2行目:ただし、変数nameの値を変えても、引数のnameは別物なので、引数nameには影響がない

ではどうすれば期待通りの結果が得られるのか?

詳しく解説。

1 def rename(name)
2   name = "Mr.#{name}"
3 end
  • 2行目:メソッドrenameでは引数から受け取ったnameにMr.をつけた文字列を返り値としてメソッドの呼び出し元に返す。
6 name = rename(name)
  • 修正前はrename(name)と、単にメソッドrenameを呼び出しただけだったが、今回はname = rename(name)とメソッドからの返り値をnameに代入している
1 def rename(name)
2  name = "Mr.#{name}"  # ③5行目の結果を受けて、"Mr.Yuki"が左辺の`name`に代入される
3 end
4
5 name = "Yuki"       # ①「=」が1つの式は右辺から読む。”Yuki"を変数nameに代入
6 name = rename(name)   # ②renameは1行目のメソッド。このメソッドの答えと、引数(name)(※5行目で定義)の値を左辺の変数nameに代入
7 puts name          # ④putsで返り値を出力される
Mr.Yuki

これでnameの値が、メソッドrenameによってMr.をつけた文字列になる。

さいごに

ここは本当にわかりづらい。
nameがたくさん出てくる。それが別物だと頭で理解できなかった。
処理に番号ふって、順番で示したらいくらか入ってきた。
ここは復習が必要そうです。

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

100日後に1人前になる新人エンジニア(4日目)

100日後に1人前になる新人エンジニア(4日目)

先日の記事はこちらから
100日後に1人前になる新人エンジニア(3日目)

どうもこんばんは。早くも週末が終わってしまいますね。
今日も今日とて更新をしていきます。
今まであまりRailsについて書いてこなかったので
今日はRailsのFormに関して書いていこうと思います。

Railsのフォーム

なんかいくつかの種類があるんだなあって感じで学んできたけど
いい機会なのでしっかりまとめてみようと思います。

form_for
form_tag
form_with

この3つですね。とりあえずTutorialでは言われた通り書いてみて
うまくいったなって感じでしたが、それではダメだと思ったので一つずつ見ていきます。

form_for

関連するモデルが用意されている場合はform_forでモデルを渡す。

<%= form_for @user do |form| # @userというインスタンス変数を渡している %>
  <%= form.text_field :email # 受け取ったモデルから作ったformを利用  %>
  <%= form.submit %>
<% end %>

この場合だと関連するモデルは@user
formにこのモデルが紐付けられてるってことですね。

form_tag

関連するモデルがない場合

<%= form_tag users_path do # user_pathというURIを渡している %>
  <%= text_field_tag :email %>
  <%= submit_tag %>
<% end %>

こんな感じですね。formに対してusers_pathと言う形でurlを渡しています。
これによってパラメタを送信しているってことなんですね。

form_with

うーん二つ使い分ける必要があるのね〜。
と言うことでできたのがこのフォームの形式。どちらも対応しています。
なのでRails5.1以降ではformは基本的にこれを使えば良いみたいです(そうだったのね...)

例えば関連するモデルがある場合(上記ではform_for)

<%= form_with model: @user do |form| %>
  <%= form.text_field :email %>
  <%= form.submit %>
<% end %>

関連するモデルがない場合は

<%= form_with url: users_path do |form| %>
  <%= form.text_field :email %>
  <%= form.submit %>
<% end %>

ハイハイなるほどねー。1つの形式で兼用できるわけです。
また、URL: @userがDBに存在するときは、updateアクションに、ないときは、createアクションに飛びます。つまりPOSTなのかPATCHなのかをフォームが判断して送ってくれるってこと。

これすごいよね。Javaやってた僕からするとびっくり!

モデルはかなずしもフィールドに対応しなくてもいい

<%= form_with model: @user, local: true do |form| %>
  <%= form.text_field :email %>
  <%= form.check_box :send_welcome_email %>
  <%= form.submit %>
<% end %>

上記でいうとこの:send_welcome_emailは@userモデルに対応していないが、
それでも問題はない。値はparams[:user][:send_welcome_email]で取り出せる

form_withのlocalについて

<%= form_with model: @user, local: true %>
<% end %>

local: trueってなんやねん。
という疑問をもったので調べました。

form_withではデフォルトの状態ではajaxでの通信がおこなわれる。
それをキャンセルするためのオプションが local: true
なんだって。ふーん。
いまいちわかり切れていないのでここは復習しておきます。

とりあえずformの基本的なところを書いていきました。
基本的にはform_withで行けばいいみたい。
あとはリファレンスを読んで知識を深めていきまーす。

以上

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

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

【開発ログ⑯】テーブル変更後のHeroku再デプロイ

前提について

はじめまして、
プログラミングスクールに通ういりふねと申します。この記事は、スクールの課題である個人アプリの開発の記録を書くことで、自身のアウトプットに利用しています。もし、読んでいただけた方がいましたら、フィードバックをしていただけたら嬉しいです。

開発するのは「有給休暇管理ツール」です。仕様は過去記事をどうぞ。

アプリはデプロイまで行いますが、サービスとして提供するものではありません。あくまでも自学習の一環ですので、ご理解下さい。では本題へどうぞ。

今回の実施内容

前回までで有給休暇管理ツールのindex画面にあるリンクボタンには全てリンク先が設定できました。その後記事にはしていませんが、デプロイまで完了し、無事にスクールの発表会が終了しました。今回はデプロイ後にテーブルのカラムを追加し、再デプロイまでの流れを書きます。

  • ローカルの編集
  • 本番環境でのマイグレーション
  • ビューの確認

開発環境

前提として開発環境を書くことを最近覚えました。

  • Rails 5.2.4.2
  • Ruby 2.5.1
  • データベース postgreSQL
  • デプロイ Heroku

ローカルでの編集

今回はHolidayテーブルに登録日を表す「registration_date」カラムを追加します。これまで有休の付与や消化のデータを取り出すためにデフォルトの「created_at」を使用していましたが、これを止めます。
理由は、先々の消化予定も入力できるようにしたいためです。このサイトで有給管理をする担当者を想定したときに従業員が有給を取る当日に合わせてデータ入力するのはやっぱり手間なので。

まずは、マイグレーションファイルをロールバックします。

$ rails db:rollback

マイグレーションファイルを編集します。

models/*****_create_holidays.rb
class CreateHolidays < ActiveRecord::Migration[5.2]
  def change
    create_table :holidays do |t|
      t.date :registration_date, null: false
〜中略〜
  end
end

再度マイグレーションを行います。

$ rails db:migrate

この他、モデルファイルに記述していた「created_at」を使用した日付の検索メソッドや有休登録画面に登録日のフォームを設置するなど必要な変更を加えていきます。複数ファイルの修正になるので、今回は割愛します。盲点だったのがコントローラーのストロングパラメーターへの追記忘れでした。created_atからの置き換えばかり意識していたので、すっかり忘れていました。何度か有休データが保存できずに焦りましたが、binding.pryを使用して原因を特定しました。

Herokuへのマイグレーション

変更したテーブルやビューを本番環境に反映させるためにHerokuから再デプロイをします。初めはHerokuからマニュアルデプロイでいいかなと思って実行しました。
image.png

しかしながら、エラーが!!(余談ですがこのエラー画面めっちゃ怖い。)
picture_pc_f8886f63bd354c264487153ad2c5c567.png

恐らく、テーブルに登録日カラムが反映されていないので、先程修正したビューファイルや日付検索メソッドたちがエラーとなっているのでしょう。
そこで、次はローカル環境と同じようにロールバックとマイグレーションを実行してみました。

$ heroku run rails db:rollback

結果の画面は以下のとおりです。少し見えにくいですが、「DROP TABLE "Holidays"」の記述があるので、どうやらロールバックは成功したようです。
スクリーンショット 2020-05-24 9.40.46.png

続けて、同じ要領でマイグレーションも実行してみます。

$ heroku run rails db:migrate

こちらも結果は写真のとおりです。同じく見えにくいですが、「create_table(:holidays)」という記述と登録日カラムの「registration_date」が追加されていることが確認できました。
スクリーンショット 2020-05-24 9.41.11.png

ビューの確認

本番環境でビューを確認します。新しいフォームの「登録日」が追加されていることが確認できます。フォームを追加したせいでビューが乱れています(泣)。今後ビューも手直しを入れる予定なので、その際に再度整えていきたいと思います。
スクリーンショット 2020-05-24 20.01.58.png

次に登録後の消化履歴の画面です。こちらも問題なく表示されています。
image.png

今日の積み上げ

難航するかと思っていたテーブルのカラム追加ですが、思いの外、スムーズに終わりました。ただ、ロールバックを行うと本番環境であれ、レコードをは全てなくなったので、これが実際に提供されているサービスだと思うとゾッとします。
やはり、機能の洗い出しやデータベース設計は、めちゃくちゃ大切だということがわかりました。

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

Rails6 開発環境設定 [Mac]

はじめに

Macを使用しRails6の開発環境構築時に行った手順の備考録です。

手順

1.Homebrewのインストール

ソフトウェアのインストールやアンインストールを管理してくれるシステム
https://brew.sh/index_ja
スクリーンショット 2020-05-24 15.52.20.png
Install Homebrew下部のコマンドをコピーしターミナルで実行

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

passwordを求められるので、Mac起動時のpasswordを入力

続いて、Homebrewのパスを通す為、下記コマンド入力し実行

$ echo ‘export PATH=/usr/local/bin:$PATH’ >> .bash_profile source .bash_profile

最後に、確認の為下記コマンド実行

$ brew ­-v

Homebrew ○.○.○
のようにバージョン表示がされれば完了

2.rbenvのインストール

Rubyのバージョン管理を切り替えるツール
Homebrewを使用しインストール

#初期設定
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile

#初期設定を反映
$ source ~/.bash_profile

#rbenvのインストール
$ brew install rbenv ruby-build

#Rubyのバージョン一覧表示
$ rbenv install -l
2.5.8
2.6.6
2.7.1
...

#指定したRubyのバージョンをインストール
$ rbenv install 2.7.1


#新しいRubyやgemをインストールしたときに実行、使用可能な状態にする
$ rbenv rehash

使用するRubyのバージョン設定

$ rbenv global 2.7.1

3.Bundlerのインストール

gemの依存関係とバージョンを管理するためのツール

$ gem install bundler

4.Railsのインストールする

$ gem install rails

5.yarnのインストール

webpackerのインストールの為に必要

brew install yarn

6.webpackerのインストール

Rails6からwebpackerが標準仕様になった為、yarnのインストールが必要

$ rails webpacker:install

7.動作確認

# Railsプロジェクトを作成
$ rails new sample

# Railsプロジェクトに移動
$ cd sample

# Railsプロジェクトを起動
$ rails server

http://localhost:3000/
Railsのページが表示できていたら完了

まとめ

ここでは各項目の詳細な解説はしきれておりません。
各項目の詳細な情報を発信している方々はたくさんいましたので、あくまで流れを記載しているのみです。
深堀りしたい場合はキーワードでググっていただければと思います。

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

Rails6 開発環境構築 [Mac]

はじめに

Macを使用しRails6の開発環境構築時に行った手順の備考録です。

手順

1.Homebrewのインストール

ソフトウェアのインストールやアンインストールを管理してくれるシステム
https://brew.sh/index_ja
スクリーンショット 2020-05-24 15.52.20.png
Install Homebrew下部のコマンドをコピーしターミナルで実行

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

passwordを求められるので、Mac起動時のpasswordを入力

続いて、Homebrewのパスを通す為、下記コマンド入力し実行

$ echo ‘export PATH=/usr/local/bin:$PATH’ >> .bash_profile source .bash_profile

最後に、確認の為下記コマンド実行

$ brew ­-v

Homebrew ○.○.○
のようにバージョン表示がされれば完了

2.rbenvのインストール

Rubyのバージョン管理を切り替えるツール
Homebrewを使用しインストール

#初期設定
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile

#初期設定を反映
$ source ~/.bash_profile

#rbenvのインストール
$ brew install rbenv ruby-build

#Rubyのバージョン一覧表示
$ rbenv install -l
2.5.8
2.6.6
2.7.1
...

#指定したRubyのバージョンをインストール
$ rbenv install 2.7.1


#新しいRubyやgemをインストールしたときに実行、使用可能な状態にする
$ rbenv rehash

使用するRubyのバージョン設定

$ rbenv global 2.7.1

3.Bundlerのインストール

gemの依存関係とバージョンを管理するためのツール

$ gem install bundler

4.Railsのインストールする

$ gem install rails

5.yarnのインストール

webpackerのインストールの為に必要

brew install yarn

6.webpackerのインストール

Rails6からwebpackerが標準仕様になった為、yarnのインストールが必要

$ rails webpacker:install

7.動作確認

# Railsプロジェクトを作成
$ rails new sample

# Railsプロジェクトに移動
$ cd sample

# Railsプロジェクトを起動
$ rails server

http://localhost:3000/
Railsのページが表示できていたら完了

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

【RSpec】ArgumentError: wrong number of argumentsエラーが出たら、変数の命名を気にした方がいいかもしれないのですね

はじめに

Controller specsに関する記事です。
共通化を行うために変数定義を行った際、命名を適当に行ったら沼ったので備忘録として残しておくことにします!

環境

ruby 2.6.5
rails 5.2.4.2
rspec 3.7
capybara 2.15
factory_bot_rails 4.11

エラー内容

エラー修正前のコード

spec/controllers/posts_controller_spec.rb
require 'rails_helper'

RSpec.describe PostsController, type: :controller do

  context "ログインを必要としないアクション" do
  .
  .
  .
  end

  context "ログインを必要とするアクション" do

    let(:user) { FactoryBot.create(:user) }
    let(:login_user) { login(user) }
    let(:post) { FactoryBot.create(:post) }
    let(:post_params) { FactoryBot.attributes_for(:post) }

    describe "createアクション" do

      context "ログイン済みユーザーの場合" do
        it "投稿を作成する" do
          login user
          expect {
            post :create, params: { post: post_params }
          }.to change(user.posts, :count).by(1)
        end
      end

      context "ログインしていないユーザーの場合" do
      .
      .
      .
      end

    end
  end
end

 前提
  ➡︎テスト用データ作成のためにFactoryBotを使用してます。(postは関連付け済み)
  ➡︎ログイン用にrails_helper.rbファイルに、login(user)メソッドを定義してます。

エラー内容

Failures:
  1) PostsController ログインを必要とするアクション createアクション ログイン済みユーザーの場合 投稿を作成する
    Failure/Error: post :create, { post: post_params }

    ArgumentError:
      wrong number of arguments (given 2, expected 0)
   # ./spec/controllers/posts_controller_spec.rb:85:in `block (5 levels) in <main>'

呼び出し側(give)の引数の数が2、メソッド側(expected)の引数の数が0となっています。

つまり「引数が2つ呼び出されているのに、それに当たるメソッド側の引数が存在しない」ということで怒られています。

エラー地点

post :create, params: { post: post_params }

何故この記述がエラーになるかというと、私が勝手にパラメータのキーとして渡しているつもりになっていた上記の「post:」部分が、実はキーとしてではなく投稿の共通化をするために定義したpost変数だと見なされていたことが原因でした。

2つのgivenは「post:」と「post_params」のことを指していたんですね…。

なので、「post:」部分をキーとして認識してもらえるように共通化の方のpost変数の命名を変えてあげます。

解決策

コード修正後

spec/controllers/posts_controller_spec.rb
require 'rails_helper'

RSpec.describe PostsController, type: :controller do

  context "ログインを必要とするアクション" do

    let(:user) { FactoryBot.create(:user) }
    let(:login_user) { login(user) }
    - let(:post) { FactoryBot.create(:post) } #削除
    + let(:new_post) { FactoryBot.create(:post) } #変数名変更
    let(:post_params) { FactoryBot.attributes_for(:post) }

    describe "createアクション" do
      context "ログイン済みユーザーの場合" do
        it "投稿を作成する" do
          login user
          expect {
            post :create, params: { post: post_params }
          }.to change(user.posts, :count).by(1)
        end
      end
    end
  end
end

post変数をnew_post変数へ書き換え。

spec実行

$ bin/rspec spec/controllers

1 examples, 0 failures

通りました!

今回のエラーで、変数の命名には気をつけようと改めて感じさせられました…笑

参考

 https://qiita.com/yikegaya/items/98f0c12f5c25ee4731a1

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

AtCoderでRuby学習10【第一回アルゴリズム実技検定 DoubleCamelCase Sort】

はじめに

Ruby学習の一環として「アルゴリズム実技検定」に挑戦します。
そのための学習の中で学んだことをアウトプットしていきます。
今回は「第一回アルゴリズム実技検定」の六問目(DoubleCamelCase Sort)より。
第一回アルゴリズム実技検定 過去問

今回は、参考になった解答をもとに学ぶことが出来た内容をまとめていきたいと思います。

問題

文字列 S が与えられる。
これは、1 つ以上の単語を (間に空白などを挟まずに) 連結したものである。
ここで、各単語は 2 文字以上であり、最初の文字と最後の文字のみが英大文字、それ以外の文字は全て英小文字である。

制約
・S は長さ 2 以上 100,000 以下の文字列である。
・S の各文字は英大文字または英小文字である。
・S は問題文で述べたような単語の連結である。

入力は以下の形で与えられる。

S

入力例
FisHDoGCaTAAAaAAbCAC
出力例
=> AAAaAAbCACCaTDoGFisH

解答

今回参考にさせて頂く解答はこちらです。

puts gets.scan(/[A-Z][a-z]*[A-Z]/).sort_by(&:upcase).join

受け取った文字列に対して、単語ごとに要素としてまとめて配列化。
sort_byメソッドを使って並び替えた後、joinメソッドを使って配列の要素全てを連結して出力という流れ。

それぞれのメソッドについてや、正規表現での表現について以下にまとめていきます。

scanメソッド

オブジェクトに対し、()内に指定したパターンを繰り返しマッチし、マッチした部分文字列を配列として返します。

p "test".scan(/../)
#=> ["te", "st"]
p "test".scan("t")
#=> ["t"]
p "testet".scan(/te./)
#=> ["tes", "tet"]

大文字で始まり、大文字で終わる単語を取り扱う今回のようなケースでは最適なメソッドですね。

正規表現部分

今回取り扱う単語を正規表現で表現すると以下のようになります。

/[A-Z][a-z]*[A-Z]/

/ /
//で囲むことで正規表現オブジェクトを生成することが出来ます。
つまり、「//で囲まれたものが正規表現だよ」という宣言になります。

[ ]
角括弧[ ]で挟まれた部分を文字クラスと言います。
1個以上の文字を列挙したもので、いずれかの1文字にマッチします(上記では0から9のうち1文字)。

[A-Z]
1文字の大文字英字を表しています。

[a-z]
1文字の小文字英字を表しています。

*
直前の表現を0回以上繰り返すという意味のメタ文字になります。
今回の場合は小文字英字が0回以上繰り返されるという意味になり、
3文字以上の英単語が示される際、大文字の間に挟まれるのは必ず小文字、という意味になります。

これで、問題の指定に沿った単語にマッチ出来るようになりました。

sort_byメソッド

配列の中身を比較して並び替え、並び替えた状態の配列を新たに作ってくれます。
()内にて、正しく比較をするためにupcaseメソッドを各要素に当て、全て大文字にしてから比較しています。
※そのままだとabcという順番よりも、大文字ABC...小文字abc...という順番で並び替えてしまうため。

p ["AA", "AC", "AaA"].sort_by(&:upcase)
#=>["AA", "AaA", "AC"]

joinメソッド

配列の要素を括弧()内に指定した区切り文字を挟んで連結した文字列を返します。
()を記述しなかった場合は、区切り文字なしで連結されます。

p ["AA", "AaA", "AC"].join(",")
#=>AA,AaA,AC
p ["AA", "AaA", "AC"].join
#=>AAAaAAC

最後に

以上、「第一回アルゴリズム実技検定」の六問目(DoubleCamelCase Sort)で学んだメソッドについてまとめました。
正規表現や様々なメソッドを使って、今回参考にさせて頂いた解答のように簡潔で分かりやすい解答が出来るようにしていきたいものです。

もし間違いなどございましたら、ご指摘いただけると嬉しいです。

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

hashとeach文

理解不足の部分を潰していく強化週間!
ということで、1週間では足りなそうです。

hashの理解不足(涙

hashに値(value)を代入するところまでは分かっていましたが
問題はその後。

分析していきましょう。

ハッシュとeach文

スクリーンショット 2020-05-24 16.18.40.png

  • 1〜5行目でhashにvalueを代入しています。  ※[:name] の部分はkey、= の右辺はvalue
  • 6行目のeach文でハッシュの要素を出力する。ココは詳しく解説を残します。

each文

●hash.each do |key, value|

 ・each do の記述により、ハッシュの要素の数だけ処理が繰り返される。
  今回の場合は、name,height,weight,BMIの4回。
 ・4回の処理が繰り返し実行された後、ブロックから抜け出し処理が終了する。

●each文のメリット

 変数の初期化や終了判定の処理がない分 eachメソッドを使用した方がより簡潔に記述できる。

 また、オブジェクトの範囲以上に処理が実行されないことが保証されている。繰り返される範囲が決まっているので、エラーの心配が少ない。

出力結果

ターミナルにこれが出力されたら成功です。
スクリーンショット 2020-05-24 16.37.29.png

それぞれのvalueが出力され、4回繰り返されて処理が終わっています。

さいごに

理解力が不足しているので、こんな内容も調べてから腹落ちするまで1時間以上かかる訳です。
アウトプットすることで理解が深まる。ありがたいことです。

せっかく理解したものは、忘れないように!

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

【Ruby on Rails】ログアウト後にCouldn't find User with ...になってしまうエラー

環境

macOS 10.15.4
Ruby 2.5
Rails 5.2

エラー内容

スクリーンショット 2020-05-24 14.04.16.png
ログアウト後にログアウト状態にしてトップページに移動するための処理を実装し、いざログアウトを実行してみたら写真のようなエラーがでてしまいました...

コードの記述ミスはないheadのjavascriptの記述に不備もない...だとしたら何がエラーの原因なんだろう...と調べてみると

sign_outのHttpメソッドがDELETEになっているとGETではできないという記事を見つけました。

HttpメソッドをDELETEからGETに変更

config/initializers/devise.rbに移動します。
そしてconfig.sign_out_viaの値をDELETE→GETに編集します。

config.sign_out_via = :get

この編集後に再度実行したら見事にエラーが直りました^_^

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

Ruby on Rails Elastic beanstalkへのデプロイ(IAM権限変更編)

概要

Ruby on Rails で作ったアプリケーションをデプロイ環境の構築をElasticBeanstalk(以下EB)を使用して、最短で行います。
IAM権限変更編・環境構築編・EBデプロイ編で分けます。
あくまで、パッとデプロイすることに重点を置くので、厳しい管理が必要な方の場合はご了承ください。

目次

IAM権限変更編
環境構築編
EBデプロイ編

IAM権限変更編

ユーザーの作成 → 必要な権限の付与

root権限で実行するのはセキュリティ上よろしくないので、適当なuserを作成して以下の権限を振っていきましょう。
・AWSElasticBeanstalkFullAccess
・AmazonRDSDataFullAccess
・AWSCloudFormationFullAccess
・AWSCloud9Administrator(cloud9使用の方)
EBはEC2、S3へのアクセス権限は含まれていますが、RDSへの権限は含まれませんので、追加で権限を振ります。また、cloudformationはEBのデプロイ環境の構築後の管理・運用時に(インフラのver管理とか、全体構成を見るのにデザイナーで見るとか)使うことがありますので、予め割り振っておくことといいかもです。
cloud9を使用してデプロイされる方はAWSCloud9Administratorもふっておきましょう

1.jpg

また後程、AWSのCLI(command line interface)をinstallしてコマンド上でデプロイしていきますので、その際のアクセスキー、シークレットアクセスキーの取得もしておきましょう。
2.jpg

EBの権限範囲についてはこちら

AWS CLI install方法

AWSの公式ガイドに従います。
ターミナルで以下をコピペするだけです。

pip install --user virtualenv
virtualenv ~/cli-ve
source ~/cli-ve/bin/activate
pip install --upgrade awscli
aws --version
deactivate
brew install awsebcli
#eb コマンドが使えることを確認
eb --version

EBのコマンドライン作成・管理

シークレットキーの入力

$aws configure
AWS Access Key ID [****************225N]: #IAMで取得したAccess Keyをコピペ
AWS Secret Access Key [****************ERNe]: #IAMで取得したSecret Access Keyをコピペ
Default region name [ap-northeast-1]: #そのままenterでOK
Default output format [json]: #そのままenterでOK

これでEBのデプロイまでの準備が整いました。
お疲れ様です。次回EBのデプロイをやっていきます。

EBデプロイ編

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

Ruby on Rails Elastic beanstalkへのデプロイ(環境構築編)

概要

Ruby on Rails で作ったアプリケーションをデプロイ環境の構築をElasticBeanstalk(以下EB)を使用して、最短で行います。
IAM権限変更編・環境構築編・EBデプロイ編で分けます。
あくまで、パッとデプロイすることに重点を置くので、厳しい管理が必要な方の場合はご了承ください。

目次

IAM権限変更編
環境構築編
EBデプロイ編

環境構築編

開発環境について

Ruby・・・2.6.3
Rails・・・5.0.7.2
Bundler・・・2.1.4以上
OS・・・amazon Linux(cloud9)
Railsは、5.2以降はSECRET_KEYのver管理のために少し面倒だったこと、6.0以上はまだまだ新しく(自分が追いつけていない点もあるのですが)わざわざverを上げるメリットがなかったため、ver5.0.7.2を使用しています。

基本、Linuxなので、Macでも同様の操作ができるかと思います。
ただ、cloud9の無料枠ではrbenv、Rubyのver変更等で容量が必要になり、10GBほど拡張しました。
デプロイできたらすぐたたんでOKですが、実際1か月でも500前後ってところでしょうか。
拡張方法はこちら

環境構築

  1. rbenvのinstall
git clone https://github.com/sstephenson/rbenv.git ~/.rbenv

2.buildをpluginとして入れる

mkdir -p ~/.rbenv/plugins

3.ruby-build を~/.rbenvに インストール(clone)する

cd ~/.rbenv/plugins
git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

4.PATH に追加 → .bash_profileにrbenv initを追加 → pathに追加した情報の有効化

echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
exec $SHELL -l

5.rbenvの確認 → インストールできるリストを確認

rbenv -v
rbenv install --list

6.指定のverを選択(今回は2.6.5)

rbenv install 2.6.5

7.installしたversionに環境全体globalに設定(他のアプリがある場合はlocalにしてください)

rbenv global 2.6.5

8.設定したrbenvを再読み込み

rbenv rehash

9.bundlerのverを指定してinstall

gem install bundler -v 2.1.4

10.railsのver指定でrails new

rails _5.0.7.2_ new myapp

11.gemの追記(開発に必要なものここで入れて事前にデプロイの確認を行うと安心できる)
pg, sqlite 1.3.6以上(pgは、herokuにも対応できるように。sqliteはcloud9の場合1.3.6以上を明記する。dotenv-railsは環境変数を使うので今回入れます、。)

gem 'sqlite3','~> 1.3.6'
gem 'pg'
gem 'dotenv-rails'

12.bundle install

myapp
bundle install --path vendor/bundle

13.gem fileに追記, pg, sqlite 1.3.6以上(pgは、herokuにも対応できるように。sqliteはcloud9の場合)

Gemfile
gem 'sqlite3','~> 1.3.6'
gem 'pg'
gem "dotenv-rails"

14.コア4つで高速install化設定しつつinstall(bundle configに入るため、-j4は今後入力不要)

myapp
bundle install -j4

15.アプリの動作確認

myapp
rails g scaffold message subject body:text
rails db:create
rails db:migrate
rails s

ここでrails のlocalserver への接続確認をしておくこと。
お疲れ様でした。

次はIAMでEBの権限を持ったuserを作成していきます。
Root権限でEBを操作するのはよろしくないですし、Rootのアクセスキーを作成するのも、推奨できないので。

IAM権限変更編

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

Ruby on Rails Elastic beanstalkへのデプロイ(EBデプロイ編)

概要

Ruby on Rails で作ったアプリケーションをデプロイ環境の構築をElasticBeanstalk(以下EB)を使用して、最短で行います。
IAM権限変更編・環境構築編・EBデプロイ編で分けます。
あくまで、パッとデプロイすることに重点を置くので、厳しい管理が必要な方の場合はご了承ください。

目次

IAM権限変更編
環境構築編
EBデプロイ編

EBへデプロイ

1.まずは初期設定を行います。
eb init (再設定の場合は eb init -i)

myapp
Select a default region
1) us-east-1 : US East (N. Virginia)
2) us-west-1 : US West (N. California)
3) us-west-2 : US West (Oregon)
4) eu-west-1 : EU (Ireland)
5) eu-central-1 : EU (Frankfurt)
6) ap-south-1 : Asia Pacific (Mumbai)
7) ap-southeast-1 : Asia Pacific (Singapore)
8) ap-southeast-2 : Asia Pacific (Sydney)
9) ap-northeast-1 : Asia Pacific (Tokyo)
10) ap-northeast-2 : Asia Pacific (Seoul)
・・・
22) af-south-1 : Africa (Cape Town)
(default is 3): 9 #Tokyoを選択
Enter Application Name
(default is "myapp"): 
Application myapp has been created.

It appears you are using Ruby. Is this correct?
(Y/n): 
Select a platform branch.
1) Ruby 2.7 running on 64bit Amazon Linux 2
2) Ruby 2.6 running on 64bit Amazon Linux 2
3) Ruby 2.5 running on 64bit Amazon Linux 2
4) Puma with Ruby 2.6 running on 64bit Amazon Linux
5) Puma with Ruby 2.5 running on 64bit Amazon Linux
6) Puma with Ruby 2.4 running on 64bit Amazon Linux
7) Passenger with Ruby 2.6 running on 64bit Amazon Linux
8) Passenger with Ruby 2.5 running on 64bit Amazon Linux
9) Passenger with Ruby 2.4 running on 64bit Amazon Linux
・・・
17) Passenger with Ruby 2.0 running on 64bit Amazon Linux (Deprecated)
18) Passenger with Ruby 1.9.3 running on 64bit Amazon Linux (Deprecated)
(default is 1): 4 
#cloud9なので、Amazon Linuxですが大切なのは、PumaとRuby 2.6(今回のversion)を選ぶこと

Do you wish to continue with CodeCommit? (y/N) (default is n): <EnterOK>
Do you want to set up SSH for your instances?
(Y/n): <EnterOK>

Select a keypair.
1) cloudformation
2) [ Create new KeyPair ]
(default is 1): <これ用にキーペアを作るか、事前にあるkeyを使うかは自由です。>

これで初期設定はOKです。
デプロイに必要なEC2まわりの作成をしていきましょう。(ここkも良しなにやってくれると助かるのですが。)

2.必要なVPC,subnet,securitygroupの作成
2-1.VPC作成
AWSのコンソールメニューからVPC を選択。
Create VPC をクリック。
以下の通り入力・選択する
Name tag: myapp-vpc (任意の名前)
IPv4 CIDR block: 10.0.0.0/16 (任意のネットワークを指定)
Create をクリック。

2-2.サブネット(Subnet)の作成
左メニューから サブSubnetを選択。
1つめのSubnetを作る。 Subnetの作成 ボタンをクリック。
以下の通り入力。
名前タグ: myapp-subnet-1a (任意のSubnet名)
VPC: myapp-vpc を選択.
アベイラビリティーゾーン: ap-northeast-1a (VPCを作成しているリージョンから一つ選ぶ)
IPv4 CIDRブロック: 10.0.0.0/24 (AZごとにVPCのCIDRの範囲で指定)
2つめのSubnetを作る。ふたたび サブネットの作成 ボタンをクリック。
以下の通り入力。
名前タグ: myapp-subnet-1c (任意のSubnet名)
VPC: myapp-vpc を選択.
アベイラビリティーゾーン: ap-northeast-1c (VPCを作成しているリージョンから一つ選ぶ)
IPv4 CIDRブロック: 10.0.1.0/24 (AZごとにVPCのCIDRの範囲で指定)

2-3.インターネットゲートウェイ(IGW)の作成
左メニューから を選択。
IGWの作成 ボタンをクリック。
Nameタグ: myapp-gateway
作成 ボタンをクリック。
リストからゲートウェイ myapp-gateway を選択し、アクションから VPCにアタッチ を選択。
VPC: myapp-vpc を選択
アタッチ をクリック。
左メニューから ルートテーブル をクリック。
VPC IDを参考に、 myapp-vpc に紐づいているルートテーブルを選択。
ページ下部のタブから Routes を選択し、 Edit routes をクリック。
Add route をクリックし、以下を入力
Destination: 0.0.0.0/0
Targetから Internet Gateway を選択し、続けて myapp-gateway を選択。
Save routes をクリックして保存。

2-4.セキュリティグループの作成(2つのリージョン用に2つ、RDS用に1つ作成します。)
左メニューから セキュリティグループ を選択
Create security group をクリックして以下のように入力.
Security group name: myapp-security-group
Description: (なんでもいいです)
VPC: myapp-vpc を選択。
Create をクリックしてセキュリティグループを作成する。
リストから今作ったセキュリティグループを選択し、画面下のタブから Inbound Rules をクリック。
Edit rules をクリック。
ルールの追加 をクリックして以下のように入力。
タイプ: HTTP
説明: HTTP
Save rules をクリックしてルールを保存する。これを再度繰り返し、もう一つ作成。

RDS用のセキュリティグループは今作ったセキュリティグループの二つからのアクセスを許可するようにします。
Inbound Rulesにセキュリティグループからのインバウンド(アクセス)を許可します。先ほどのセキュリティグループ二つを選択して追加しましょう。
3.jpg

以上でVPC,subnet,securitygroupの作成は終わり。

4.EBへデプロイ
あと少しです。デプロイしていきましょう。
ターミナルに戻って、以下のコマンドでデプロイ時の設定(RDSの作成、ALBの設定も含め)して構築します。

eb create <EBの環境名> --instance_type <EC2のスペック> --database.engine <DBの種類> --database.username <DBusername> --elb-type application --vpc
#例)eb create rails-app --instance_type t2.medium --database.engine mysql --database.username admin --elb-type application --vpc
Enter an RDS DB master password: 
Retype password to confirm: 

Enter the VPC ID: <作成したVPCのID>
Do you want to associate a public IP address? (Y/n): <Enter>
Enter a comma-separated list of Amazon EC2 subnets: <作成した2つのSubnetのID>
Enter a comma-separated list of Amazon ELB subnets: <作成した2つのSubnetのID>
Do you want the load balancer to be public? (Select no for internal) (Y/n): 
Enter a comma-separated list of Amazon VPC security groups:<作成した2つのセキュリティグループのID>

これでデプロイ環境の構築がEBのコンソール画面で始まります。
追加で、作成されたRDSの設定を追加します。(設定するパラメータはRDSのコンソール→各RDS画面で確認できます。)

eb setenv RDS_DB_NAME=◎◎ RDS_USERNAME=◎◎ RDS_PASSWORD=◎◎ RDS_HOSTNAME=◎◎ RDS_PORT=◎◎
例)eb setenv RDS_DB_NAME=myapp RDS_USERNAME=admin RDS_PASSWORD=123456 RDS_HOSTNAME=database-1.cfwrsdfe64.ap-northeast-1.rds.amazonaws.com RDS_PORT=3306

デプロイしてみましょう。

eb deploy

ここで、EBのコンソールでURLを確認してみましょう。

4.jpg

An unhandled lowlevel error occurred. The application logs may have details.
という表示がでました。これはRubyで本番環境時のシークレットキーを作成、設定していないためおきます。
ということで、ここにRubyの本番環境設定をしていきましょう。

5.rubyの環境変数およびシークレットキーの出力EBへの設定

#シークレットキーの出力
rails credential:edit
<シークレットキー>
#EBへ設定を反映
eb setenv SECRET_KEY_BASE=<シークレットキー>

本番環境時のCSSprecompileが必要なので・・

RAILS_ENV=production bundle exec rake assets:precompile
myapp/config/environments/production.rb
config.assets.compile = true

6.再度デプロイ

eb deploy

お疲れ様です。これでデプロイ完了です。

まとめ

今回AWS elastic beanstalkを使ってRubyのアプリケーションのデプロイをしました。
簡単にALB、Autoscallingなどのリソースも含めて冗長的な構成をすぐ作れる事、elastic beanstalkの環境ですべてのリソースの管理できるのもは非常にいいサービスに感じました。
一方で、RDSがデフォルトで作成されなかったり、環境の削除の際はS3が残る点(バケットポリシーの関係で)は不便に感じました。

その他

いくつか、デプロイ後に触ること、エラー時の対応について追記します。
1.初期の設定では毎度DB作成・マイグレーションされる
Elastic Beanstalk>環境>myapp-env>設定
RAILS_SKIP_ASSET_COMPILATION(false → true)
RAILS_SKIP_MIGRATIONS(false → true)

2.エラーについて
エラーがはかれる場合は以下のコマンドで現状のエラー内容がわかるので、対応しましょう。
eb logs

その他ebコマンドについてはこちら
が参考になりました。

参考記事

以下の記事を参考にさせていただきました。
RailsアプリケーションをElastic Beanstalkにデプロイするまで
https://qiita.com/hiroeorz@github/items/c9dcdb9c648d7e8eae7f#rails%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E4%BD%9C%E6%88%90%E3%81%A8%E8%A8%AD%E5%AE%9A%E7%AD%89

Railsのバージョンを指定してinstallする方法
https://qiita.com/tanakayo/items/7b85261924eca1a5a3d6

production環境でsecret_tokenをセットする(rails)
https://qiita.com/takusemba/items/2ad25d3d0a007757c194

Rails5をproduction(本番環境)で起動する時に嵌ったこと
https://qiita.com/qqhann/items/7cd01f4b5cff4a31e053

aws EB CLI 公式ref
https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/eb3-cmd-commands.html

Elastic Beanstalkで使うコマンドまとめ
https://qiita.com/yoshito410kam/items/712e96be87477aafdc89

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

Day18~22 中間試験~基礎カリキュラム本試験

本試験で学んだことについて

本試験は5/22に突破。

学んだことは詳細は後日まとめる。

CSS上のwidth 100%と100vw、またheight 100%と100vhについて、詳しくまとめておきたい。

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

Ruby on rails を初心者向けに解説⑦ ~フラッシュの実装~

はじめに

今回は以前の記事の続きになります。

よろしければ、以前の記事も御覧ください。

今回はフラッシュについてまとめていきます。

Ruby on rails を初心者向けに解説①

Ruby on rails を初心者向けに解説② ~リンクの作成~

Ruby on rails を初心者向けに解説③ ~データベースの作成~

Ruby on rails を初心者向けに解説④ ~命名規則とform_Tagの使い方について~

Ruby on rails を初心者向けに解説⑤ ~データベースの編集と削除~

Ruby on rails を初心者向けに解説⑥ ~バリデーションの作成~

フラッシュとは

具体例を探しに、Twitterにで試してみました。

image.png

この入力されたユーザー名が~の部分がフラッシュです。

フラッシュとはページ上に一度だけ表示されるものであり、ページを更新したり別のページに移動したりするとフラッシュは表示されなくなります。

image.png

このフラッシュを実装してみましょう。

フラッシュの実装

railsでフラッシュを表示するためには、特殊な変数flashが用意されています。

アクションで変数flash[:notice]に文字列を代入すると、viewファイルで使用することができます。flashは一度使用された後は自動的に削除されることになっています。

また、フラッシュは色々な場所で共通して使用するので、application.html.erbファイル内で使用すると便利です。

application.html.erbファイルに書かれたものは、全てのviewファイルに共通して表示されるようになります。

views >> layoutsフォルダの配下にあるapplication.html.erbファイルに以下のように記入してフラッシュが表示できるようにしましょう。

application.html.erb
<% if flash[:notice]%>
  <div class="flash">
    <%= flash[:notice]%>
  </div>
<% end %>

これで、フラッシュが存在するなら表示されるようになりました。

どうせなんで、cssも設定しておきましょう。

application.css
.flash {
    background-color: brown;
    color: white;
}

postsコントローラーを次のように書き直して、flash[:notice]にエラーメッセージを代入してみましょう。

posts_controller.rb
def create
  post = Post.new(content: params[:content])
  @content = params[:content]
  if post.save
    flash[:notice] = "投稿に成功しました"
    redirect_to("/posts/all")
  else
    flash[:notice] = post.errors.full_messages[0]
    render("posts/new")
  end
end

post.saveの部分で失敗した場合に、post.errors.full_messagesにエラーメッセージがリストとして格納されるため、その1つ目の値をflash[:notice]に格納しています。投稿に成功した場合は、その旨をflash[:notice]に格納します。

これでフラッシュを実装することができました。

実際に試してみましょう。

以下のnew.html.erbファイルを開いてみましょう。また、バリデーションは以下のようになっています。

new.html.erb
<%= form_tag("/posts/create") do  %>  
  <textarea name="content" cols="30" rows="10"><%= @content%></textarea>
  <input type="submit" value="送信">
<% end %>
post.rb
class Post < ApplicationRecord
    validates :content, {presence: true}
    validates :content, {length: {maximum: 20}}
end

image.png

試しに、値を何も入れずに送信を押してみましょう。バリデーションに弾かれ、エラーメッセージがflash[:notice]に格納されます。

image.png

次は、20文字以上入力して送信を押してみましょう。次のエラーメッセージが表示されます。

image.png

今度は、投稿に成功した場合を試してみます。次のようになります。

image.png

上手くいきましたね。

終わりに

今回の記事はここまでになります。

お付き合い頂きありがとうございました。

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

Ruby on rails を初心者向けに解説⑥ ~バリデーションの作成~

はじめに

今回は以前の記事の続きになります。

よろしければ、以前の記事も御覧ください。

今回はバリデーションについて学んでいきましょう。

Ruby on rails を初心者向けに解説①

Ruby on rails を初心者向けに解説② ~リンクの作成~

Ruby on rails を初心者向けに解説③ ~データベースの作成~

Ruby on rails を初心者向けに解説④ ~命名規則とform_Tagの使い方について~

Ruby on rails を初心者向けに解説⑤ ~データベースの編集と削除~

新しいコントローラーの作成

新しいコントローラーを作成していきましょう。

今回は、投稿を管理するpostsコントローラーを作成します。ターミナルで以下のコードを実行してください。

rails g controller posts all

all.html.erbファイルで、全ての投稿を表示するようにしましょう。

そのために、新しい投稿を作成するファイルを作成します。new.html.erbファイルをpostsファイルの中に作成しましょう。

image.png

このnew.html.erbファイルで、新しい投稿を作成していきます。

新しいモデルの作成

では、投稿を管理するデータベースを作成しましょう。今回は、まだデータベースを全く作成していないので、モデルから作成していきます。

モデルとは、データベースの情報を操作する仕組みであり、データベースとのやり取りを行うクラスとも言うことができるものでしたね。

モデルは通常、小文字から始まる単数形で命名します。なぜなら、モデルとはtableに対して一つしか存在しないからです。

 rails g model post content: string

このようにモデルを作成すると、同時にデータベースの設計図であるmigrationファイルが作成されるのでしたね。

以下のコードでマイグレーションファイルを実行しましょう。

rails db:migrate

データベースコンソールから、作成したtableを確認してみましょう。

rails dbconsole
.table

ar_internal_metadata schema_migrations

posts users

postsテーブルが作成されていますね。以下のコードで中身を見てみましょう。

.schema posts

CREATE TABLE IF NOT EXISTS "posts" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "content" varchar, "string" varchar, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL);

投稿を作成

new.html.erbファイルに、投稿を作成するコードを追加しましょう。

new.html.erb
<%= form_tag("/posts/create") do  %>  
  <textarea name="content" cols="30" rows="10"></textarea>
  <input type="submit" value="送信">
<% end %>

image.png

/posts/createというURLにpostリクエストを送っています。params[:content]に、textarea内部のデータが格納されて、送られます。

以下のようにルーティングしましょう。

routes.rb
post "posts/create" => "posts#create"

postsコントローラーのcreateアクションにルーティングされています。textareaのデータをpostsテーブルに格納するために、postsコントローラーを以下のようにコーディングします。

posts_controller.rb
def create
  post = Post.new(content: params[:content])
  post.save
  redirect_to("/posts/new")
end

これで、postsテーブルにデータを保存することができるようになりました。

以下のようにtextareaに記入して送信ボタンを押しましょう。

image.png

データベースを確認してみましょう。ターミナルで以下のコードを打ってください。

rails dbconsole
.header on
select * from posts;

id|content|string|created_at|updated_at
1|pocomaru||2020-05-23 10:37:51.509719|2020-05-23 10:37:51.509719

このように、投稿をデータベースに格納することができました。

バリデーションの設定

バリデーションとは、データベースにデータを保存する際にかける制約のことです。

例えば、何かのサイトにログインする際にメールアドレスやパスワードが空っぽでもログイン可能だとやばいですよね。

そんなことを防ぐために存在します。

バリデーションは、モデルに設定します。

実際に設定してみましょう。

空っぽの投稿を防ぐ

空っぽの投稿を防ぐバリデーションを考えます。

投稿を保存するのはpostsテーブルなので、このバリデーションはpostモデルのPostクラス内部に記入します。

postモデルはデフォルトでは以下のようになっています。

post.rb
class Post < ApplicationRecord
end

バリデーションは、以下の書式で書きます

validates :カラム名, {検証内容}

空っぽの投稿を防ぐバリデーションは以下のようになります。

post.rb
class Post < ApplicationRecord
end

バリデーションは、以下の書式で書きます

validates :カラム名, {検証内容}

空っぽの投稿を防ぐバリデーションは以下のようになります。

post.rb
class Post < ApplicationRecord
    validates :content, {presence: true}
end

これで、空っぽの投稿を防ぐことができました。

バリデーションに引っかかった場合、saveすることができなくなります。また、saveに成功スっればTrueが戻り値として帰ってきて、saveに失敗すればFalseが戻り値として帰ってきます。

postsコントローラーを以下のように書き換えましょう。

posts_controller.rb
def create
  post = Post.new(content: params[:content])
  if post.save
    redirect_to("/posts/all")
  else
    redirect_to("/posts/new")
  end

このようにコードを書き換えることで、saveが成功した場合には/posts/allにリダイレクトし、saveが失敗した場合には/posts/newにリダイレクトします。

これで、空っぽの投稿を排除するバリデーションを作成することができました。

次は、一定以上の文字数を削除するバリデーションを作成してみましょう。

一定以上の文字数を防ぐ

今回は20文字以上の投稿を防ぐバリデーションを設定してみましょう。

以下のようになります。

post.rb
class Post < ApplicationRecord
    validates :content, {presence: true}
    validates :content, {length: {maximum: 20}}
end

このvalidates :content, {length: {maximum: 20}}の部分により、20文字以上の投稿を制限することができるようになりました。

しかし、このようにバリデーションを設定するだけだと、問題があります。20文字以上の投稿をしたときに、textareaが空っぽになってしまうのです。

理由はpostsコントローラーにあります。バリデーションに引っかかり、redirect_to("/posts/new")が呼ばれたとき、ルーティングによりpostsコントローラーのnewアクションが実行されます。そうすると、インスタンス変数をnew.html.erbファイルに送ることができないため、頑張って書いたtextareaが空っぽになってしまうのです。

これを防ぐために、renderというメソッドを使います。

renderとはレンダリングすることができるメソッドであり、レンダリングとはブラウザにviewファイルを読み込ませて描画させることです。

renderメソッドをviewファイル内で使うと、複数のviewファイルの共通の部分を描画する部分テンプレートを使うことができます。

今回はコントローラー内部で使うことにより、アクションを介することなくレンダリングを行うことで、作成したインスタンス変数をviewファイルに渡すことができます。

postsコントローラーを次のように書き換えましょう。

def create
  post = Post.new(content: params[:content])
  @content = params[:content]
  if post.save
    redirect_to("/posts/all")
  else
    render("posts/new")
  end
end

@contentに、投稿の内容を格納した後、redirect_to の代わりにrenderを使ってnew.html.erbファイルを描画しています。

このようにすることで、インスタンス変数であ@contentをnew.html.erbに渡すことができます。

new.html.erbファイル内でこのインスタンス変数を表示するために、以下のように書き換えましょう。

new.html.erb
<%= form_tag("/posts/create") do  %>  
  <textarea name="content" cols="30" rows="10"><%= @content%></textarea>
  <input type="submit" value="送信">
<% end %>

textareaの初期値に@contentを渡しています。これで、バリデーションに引っかかったときに、その値を表示することができます。

実際に試してみましょう。

image.png

以下のように20文字以上入力して、送信を押してみましょう。

image.png

特に何も変わりません。

image.png

終わりに

今回はここまでになります。

お付き合い頂きありがとうございました。

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

RSpec で メソッドをモックしたいときに mock 用の allow メソッドと singleton メソッドを使うか迷ったときは allow メソッドを使うべき

概要

rspecではテストをしやすくするために、メソッドをモックしたいときがよくあると思います。

下記の例では set_complex_config メソッドにadmin?メソッドが影響を受けるのですが、

set_complex_config メソッドはすでにそれ自体のテストコードがあり、そのレスポンスのみ欲しいという状況です。

# コード例は適当です
class User
  def admin?
    res = set_complex_config
    case res
    when 'hoge'
      'hoge'
    when 'fuga'
      'fuga'
    end
  end

  def set_complex_config
    # 複雑な処理
  end
end

このような場合のモックの仕方として私は2通りのやり方が思いつくので、どちらが良いかを考えてみました。

mockの仕方

① singleton メソッドを定義してmockする

下記のように User クラスの set_complex_config メソッドを singleton メソッドで上書きする方法です。

let(:hoge_let) { 'hoge' }
it do
  user = create(:user)
  hoge_var = 'hoge'
  user.define_singleton_method(:set_complex_config) { hoge_var }
  user.set_complex_config => 動く

  user.define_singleton_method(:set_complex_config) { hoge_let }
  user.set_complex_config => wrong number of arguments (given 0, expected 2..3)
end

一見かっこいいですが、この場合、example内やbeforeブロック内で、define_singleton_method メソッドのブロックはlet変数を読むことができません。

② allow メソッドでmockする

allow メソッドでは問題なく動きます。

let(:hoge_let) { 'hoge' }
it do
  user = create(:user)
  allow(user).to receive(:attributes).and_return(hoge_let)
  user.set_complex_config => 動く
end

結論

素直にallow().to receive().and_return()を使った方が良さそうです。

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

Rails でセッションを特定のコントローラだけ無効にしたいとき

概要

クッキーを使ったセッションを特定のコントローラだけ無効にしたいときがあります。

例えば、管理画面Aでは active_record_store でセッション管理をしており、
管理画面Bでは devise token auth でセッション管理をしているときなどです。

この場合、管理画面Aでのみセッション管理が働いて欲しいのに、管理画面Bでも active_record_store によって
sessions テーブルにセッションデータの書き込みが発生してしまいます。

対策

セッションを無効にしたいコントローラーで下記の処理を記載すればOKです。

request.session_options[:skip] = true

参考
https://stackoverflow.com/questions/33318060/how-do-i-prevent-rails-from-creating-a-session

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

Rails の routing で namespace, module, scope, as の違い

概要

routing を書くときに紛らわしいメソッドをまとめました。

ルーティングの各名称

resources :users


名前付きルーティング      パス                     ディレクトリ
      ↓                ↓                         ↓

   Prefix Verb   URI Pattern               Controller#Action
    users GET    /users(.:format)          users#index
          POST   /users(.:format)          users#create
 new_user GET    /users/new(.:format)      users#new
edit_user GET    /users/:id/edit(.:format) users#edit
     user GET    /users/:id(.:format)      users#show
          PATCH  /users/:id(.:format)      users#update
          PUT    /users/:id(.:format)      users#update
          DELETE /users/:id(.:format)      users#destroy

それぞれのメソッドの対応表

名前付きルーティング パス ディレクトリ
namespace
module × ×
scope × ×
as × ×

きれいな routes ファイルを目指しましょう!

参考:
https://devblast.com/b/rails-5-routes-scope-vs-namespace

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

RSpec で hash の確認をするときは素直に include matcher を使おう

概要

rspec で hash を確認したいときに、eq matcher ではなく、include matcher を素直に使おうという記事です。

コード

{ hoge: 'fuga' }という hash があるときに、これを eq で確認しようとすると、

it do
  expect(subject).to eq { hoge: 'fuga' }
end

のようには書けません、{}がブロックと解釈されるからです。
なので eq を使うためには

it do
  expected_hash = { hoge: 'fuga' }
  expect(subject).to eq expected_hash
end

のように、hash を変数に入れなければなりません。

当たり前で記事にするまでもないかもしれませんが、

これでは面倒なのでinclude を使いましょう。

it do
  expect(subject).to include(hoge: 'fuga')
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Scaffoldでslimのカスタマイズをしてみた

これはなに

概要

railsのscaffoldをカスタマイズする時に、slimでの出力に苦戦したので、それを実現するまでの奮闘記

こんな人向け

・railsのテンプレートエンジンをslimにしている人
 またはrailsのテンプレートエンジンをslimにしたいと思っている人
・scaffoldのカスタマイズをしているが、viewのカスタマイズを諦めている人
 またはscaffoldのカスタマイズをしたい人

環境

Rails 6.0.2.2
ruby 2.6.5

実装までの事前準備

その1 テンプレートエンジンをslimにする

こちらの記事を参考にして、slim-railsというgemを追加します。
https://qiita.com/ftyabu/items/42eb62901b6b56a7dc72

その2 scaffoldのテンプレートをカスタマイズできるようにする

こちらの記事を参考にして、テンプレートの作成と、その参照先を変更します。
https://qiita.com/akito1986/items/d9f379191fd6b98de955

実現までの手順

その1 ディレクトリ名をerbからslimに変更

上記の「その2」で以下のようなファイルが作成されていると思います。
(設定によって違いがあるかも)

$ tree lib/templates
lib/templates
├── erb
│   ├── controller
│   │   ├── templates
│   │   │   └── view.html.erb
│   │   └── view.html.erb
│   ├── mailer
│   │   ├── templates
│   │   │   ├── view.html.erb
│   │   │   └── view.text.erb
│   │   ├── view.html.erb
│   │   └── view.text.erb
│   └── scaffold
│       ├── _form.html.erb
│       ├── edit.html.erb
│       ├── index.html.erb
│       ├── new.html.erb
│       ├── show.html.erb
│       └── templates
│           ├── _form.html.erb
│           ├── edit.html.erb
│           ├── index.html.erb
│           ├── new.html.erb
│           └── show.html.erb
└── rails
    ├── assets
    │   ├── javascript.js
    │   ├── stylesheet.css
    │   └── templates
    │       ├── javascript.js
    │       └── stylesheet.css
    ├── controller
    │   ├── controller.rb
    │   └── templates
    │       └── controller.rb
    ├── helper
    │   ├── helper.rb
    │   └── templates
    │       └── helper.rb
    └── scaffold_controller
        ├── api_controller.rb
        ├── controller.rb
        └── templates
            ├── api_controller.rb
            └── controller.rb

16 directories, 28 files

この「erb」ディレクトリを「slim」に変更しましょう。

その2 ファイルをerb.tt仕様からslim.tt仕様に書き換える

さて、ここからが本番です。
参考になる記事を探したものの、なかなか見つかりませんでした。
まずは対象ファイルの中身をみてみましょう

lib/templates/erb/scaffold/index.html.erb.tt

<p id="notice"><%%= notice %></p>

<h1><%= plural_table_name.titleize %></h1>

<table>
  <thead>
    <tr>
<% attributes.reject(&:password_digest?).each do |attribute| -%>
      <th><%= attribute.human_name %></th>
<% end -%>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
      <tr>
<% attributes.reject(&:password_digest?).each do |attribute| -%>
        <td><%%= <%= singular_table_name %>.<%= attribute.column_name %> %></td>
<% end -%>
        <td><%%= link_to 'Show', <%= model_resource_name %> %></td>
        <td><%%= link_to 'Edit', edit_<%= singular_route_name %>_path(<%= singular_table_name %>) %></td>
        <td><%%= link_to 'Destroy', <%= model_resource_name %>, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <%% end %>
  </tbody>
</table>

<br>

<%%= link_to 'New <%= singular_table_name.titleize %>', new_<%= singular_route_name %>_path %>

erbを普段から使う人にとっては馴染みのあるんでしょうか、<%%=の記号は良くわかりませんでした。

https://qiita.com/ykhirao/items/7ff9ce515a82a6dd24ea
こちらの記事に<%%=のことが紹介されていました。erbを一度展開しても、erbファイルが壊れないようにするためなんですね。

slimでそれを実現するにはどうしたらいいんだろう。。

その3 (失敗)とりあえずgemにぶち込んでみればなんとかなる説の立証

ここでふと思い出しました。erb2slimの存在を。

「erbは正しく書かれているし、直してくれるだろう」と信じ、試してみましたが。。

lib/templates/erb/scaffold/index.html.slim

p#notice
  - %= notice
h1
  = plural_table_name.titleize
table
  thead
    tr
      - attributes.reject(&:password_digest?).each do |attribute|
        th
          = attribute.human_name
      th[colspan="3"]
  tbody
    |  <ruby code="% @
    = plural_table_name
    | .each do |
    = singular_table_name
    | | "> 
    tr
      - attributes.reject(&:password_digest?).each do |attribute|
        td
          - %= <%= singular_table_name
          | .
          = attribute.column_name
          |  %>
      td
        - %= link_to 'Show', <%= model_resource_name
        |  %>
      td
        - %= link_to 'Edit', edit_<%= singular_route_name
        | _path(
        = singular_table_name
        | ) %>
      td
        - %= link_to 'Destroy', <%= model_resource_name
        | , method: :delete, data: { confirm: 'Are you sure?' } %>
    - % end
br
- %= link_to 'New <%= singular_table_name.titleize
| ', new_
= singular_route_name
| _path %> 

崩壊のにおいしかしない。。。笑
案の定scaffoldを実行するとsyntaxエラーの連発でした。
やはり自力で修正する方が確実そう

その4 slim-railsからヒントを得る

とはいえ、何かしたのとっかかりが欲しいなと思って、いろいろと調べていると、ふと
「そもそもslim-railsはscaffoldのテンプレートをいじってるはず」
と我ながら筋の良い勘が働いたので、確認してみました。すると、、、
https://github.com/slim-template/slim-rails
ありました。

slim-rails/lib/generators/slim/scaffold/templates/index.html.slim

h1 Listing <%= plural_table_name %>

table
  thead
    tr
<% attributes.each do |attribute| -%>
      th <%= attribute.human_name %>
<% end -%>
      th
      th
      th

  tbody
    - @<%= plural_table_name %>.each do |<%= singular_table_name %>|
      tr
<% attributes.each do |attribute| -%>
        td = <%= singular_table_name %>.<%= attribute.name %>
<% end -%>
        td = link_to 'Show', <%= singular_table_name %>
        td = link_to 'Edit', edit_<%= singular_table_name %>_path(<%= singular_table_name %>)
        td = link_to 'Destroy', <%= singular_table_name %>, data: { confirm: 'Are you sure?' }, method: :delete

br

= link_to 'New <%= human_name %>', new_<%= singular_table_name %>_path

つまりこれを参考にして、自分好みにテンプレートを変更すればいいんですね。
見つけてしまえばこちらのもの。文言を変えたり、構造を変えたり、こまめに実験しながら、素敵なカスタマイズ生活をお送りください。

結論

困ったらソースコード
早期に気づけてたら一瞬で解決していた

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