M1macでrbenvを使ってrubyのインストール

% rbenv install 2.6.3

などrubyのバージョンをインストールしたいときにBUILD FAILEDが出てしまってインストールできないことがある。 そんなときはこれ!

% RUBY_CFLAGS=-DUSE_FFI_CLOSURE_ALLOC rbenv install 2.6.3 

なんかわからないけどインストールできる。神

errorメッセージを個別で出したい

色々と調べながらやってるうちに知らない間にerrorメッセージを出せるようになってしまったが、やったことに自分の頭がついていっていないので、落ち着いてまとめてみる。

エラーメッセージ用のテンプレートの作成

まずはじめに全てのエラーメッセージを配列で取得します。が、エラーメッセージ用の部分テンプレートを作成するのが先です。いろいろなところで使うので、viewに書き込むと直すのが手間になってしまいます。views/shared/_error_messages.html.erbとしておきましょう。

<% if model.errors.any? %>
  <div class="alert alert-warning">
    <ul>
      <% model.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
    </ul>
  </div>
<% end %>

さて、上のように書くことで、エラーメッセージを配列で取得でき、複数のエラーメッセージがある可能性がある(自分で作っていれば)ので、eachを使って、全て取得します。一行ずつ丁寧にみていきます。

1行目 <% if model.errors.any? %>

<% if model.errors.any? %>

errors.any?はエラーがあるかどうかの真偽を出してくれるメソッドです。じゃあ、modelは?というと、呼び出す先で指定しているものになります。呼び出し先をviews/users/new.html.erbとでもしましょう。

<%= form_with model: @user, local: true do |f| %>
  <%= render 'shared/error_messages', model: f.object %>
...

<%= render 'shared/error_messages', model: f.object %>の部分で呼び出しをしていて、model: f.objectmodelの部分が、<% if model.errors.any? %>のmodelと対応しています。では、f.objectってなんだろう?ということで調べていきます。

model: f.objectとは

fはフォームビルダー変数といい、

<%= form_with model: @user, local: true do |f| %>

form_withで生成された|f|の部分です。このフォームビルダー変数には様々なメソッドがあり、text_field(一行のテキスト投稿フォーム)やselect(選択肢を作成)など様々ある。f.objectには、入力したデータが入っています。つまり、model: @userの情報をもっていることになるので、userコントローラーのnewアクションとつながっていることになる。かなり遠いところまで行くけど、そういうことみたい。

4行目 <% model.errors.full_messages.each do |message| %>

まず、はじめのmodelには、呼び出し先の

<%= form_with model: @user, local: true do |f| %>

の@userが代入されます。そして、errorsメソッドで@userの持っているエラーを表示してくれ、full_messagesでエラーの文章のみを配列で表示してくれます。そして、each do |message|でエラーの配列を一つ一つ処理してくれる、というようになっているようです。

これでエラーメッセージが個別で出る動きが分かった。難しい。

参考

https://yama2-0506.hatenablog.com/entry/2020/12/11/083007 https://qiita.com/ryuuuuuuuuuu/items/1a1e53d062bff774d88a

Railsでデータベースのリセットをしよう!

データベースを空にするために、

rails db:reset

rails db:migrate:reset

の2種類存在する。この2つについて考えていきます。

rails db:resetとは

rails db:resetは2種類のコマンドを実行するのと同じ働きがあります。

上の2種類のコマンドを実行するのと同等なので、一度データベースを削除して、スキーマからテーブルを再度作成し、シードデータを用いてデータベースの初期化を実行します。

rails db:migrate:resetとは

rails db:migrate:resetでは、DBの削除、DBの作成、rails db:migrateが行われます。なので、seeds.rbの読み込みがないため、ダミーデータのようなものは作成されません。

どちらを使うか

seeds.rbの読み込みまでしたい場合は、rails db:reset 読み込みまではしたくない場合は、rails db:migrate:resetということになる。

参考

https://k-koh.hatenablog.com/entry/2020/09/25/232829 https://railsguides.jp/active_record_migrations.html https://note.com/kentarotawara/n/n976705aa4cb8 https://railsdoc.com/rake#rake_db_migrate

はてなブログでMarkdownで目次が作りたい!

ということで、Qiitaとかみてると目次ってかっこいいなと、思うわけですよ。なので、今回は目次について調べて、実際に使ってみようと思います!

はてなブログを参考に

まず、目次を挿入したい行に[:contents]と記入をする。

[:contents]

その下に見出しをつけてやればできるらしい。

できてる。

#の数で入る場所が変わるぜ

面白い。

参考

staff.hatenablog.com

buildメソッドって?

インスタンスを生成するメソッド。モデルの関連付けでも用いられる。 newメソッドと同じ使い方をするが、モデルの関連付けの際には、暗黙のルールとしてbuildメソッドを使う。

buildの記述方法

全部で3パターン。モデルの同士の関連付けで変わってくる。 1. アソシエーションが1対1 2. アソシエーションが1対多 3. アソシエーションが多対多

1対1の場合

ユーザーが予定を1つ持っている場合として、

class User < ActiveRecord::Base
  has_one :plan
end
class Plan < ActiveRecord::Base
  belongs_to :user
end

このような1対1関係では、build_関連付けのメソッド名となります。

@user = User.new
@plan = @user.build_plan

1対多の場合

ユーザーが予定を複数持っている場合として、

class User < ActiveRecord::Base
  has_many :plans
end
class Plan < ActiveRecord::Base
  belongs_to :user
end

このような1対多関係では、関連付けのメソッド名.buildとなります。

@user = User.new
@plan = @user.plans.build

多対多の場合

多対多の場合中間テーブルを作るため、以下のようにモデルを作成します。

class User < ApplicationRecord
  has_many :group_users
  has_many :groups, through: :group_users
end
class Group < ApplicationRecord
  has_many :group_users
  has_many :users, through: :group_users
end
class GroupUser < ApplicationRecord
  belongs_to :group
  belongs_to :user
end

このような多対多関係では、1対多と同様に関連付けのメソッド名.buildとなります。

@user = User.new
@group = @user.groups.build

buildでも場合分けするので覚えなければ!

参考

techtechmedia.com

form_withって難しい(n回目)

form_withっていろいろな情報があって、何が何やらさっぱりなので、少しまとめて行きたいと思います。たくさん参考にしながらやっていきます。

form_tagとform_for

まず、form_withは第一引数にmodel:かurl:を使います。この使い分けは、

<%= form_with url: "パス" do |form| %>
  フォーム内容
<% end %>
<%= form_with model: モデルクラスのインスタンス do |form| %>
  フォーム内容
<% end %>

なぜ、この2つに分けられているのかというと、もともとform_withform_tagform_forが使われていました。form_tagは保存する必要がない時、form_forは保存する必要があるときに使います。

<%= form_tag('/main', method: :post) do %> 
  <input type="text" name="nickname"> 
  <input type="submit"> 
<% end %>
<%= form_for(@user) do |f| %>
  <%= f.text_field :name %>
  <%= f.submit %>
<% end %>

form_tagform_forで書き方が異なることが分かります。form_forでは、FormBuilderオブジェクトのヘルパーメソッドを使っています。FormBuilderオブジェクトとは、上の例だとform_forというヘルパーメソッドの引数である@userの情報を持っている「f」です。フォームを作るときに便利なヘルパーメソッドを使うことができます。form_forによって作られるオブジェクトということなのかな?text_fieldやsubmitなど便利なヘルパーメソッドを使えます。

form_withとは

form_tagform_forくっつけたらもっと簡単なのになー。モデルでもパスでもどっちも使えたらなー。ということで、form_withが誕生したらしいです。 使い方をもう一度

<%= form_with model: @user do |form| %>
  フォーム内容
<% end %>
<%= form_with url: root_path do |form| %>
  フォーム内容
<% end %>

form_withでmodelオプションを使う場合は、引数にモデルクラスのインスタンスを指定します。モデルクラスのインスタンスとは、保存したいテーブルのクラスのインスタンスのことをいうそうです。よく分かりません。 進めます。usersテーブルに新たにレコードを作成したいので、コントローラーに

def new
  @user = User.new
end

と記述します。この@userがform_withの引数に指定されるのです。@userが新規に作成された場合(@userになんの情報も入っていない)には、createアクションへ、@userにすでに情報が入っている場合にはeditアクションへ自動的にform_withが振り分けてくれます。

参考

https://pikawaka.com/rails/form_with https://qiita.com/kenkentarou/items/f6b2f033d8b14056ec81

部分テンプレートをrenderするときのcollectionってなに?

部分テンプレートをレンダリングするときに、ローカル変数を渡す時があるけれど、何種類も渡し方があるので、その中に出てくるcollectionについて考えていきます。

前提として、postコントローラー、postモデルが存在し、

def index
  @posts = Post.all
end
<%= post.title %>
<%= post.body %>

とします。

collectionの使い方

まず、collectionをつかわずに、eachを使って繰り返しレンダリングさせると、

<% @posts.each do |post| %>
  <%= render 'post', post: post %>
<% end %>

と表現できます。しかしこれでは毎回レンダリングをするため、負荷がかかってしまいます。 collectionを使うと、

<%= render partial: 'post', collection: @posts %>

と書くことで、内部で要素1つずつを取り出して処理をしてくれるため、何度もレンダリングをしません。負荷がかからないし、早い。また、部分テンプレートに渡る変数名は、partialで指定した値(post)になるので注意が必要。

collectionの省略記法

<%= render @posts %>

とかなり省略して書くことができるが、これが成立するためにはいくつかの決まりがある。

  1. 部分テンプレートが呼び出し元のテンプレートと同じディレクトリ内にある
  2. 部分テンプレートのファイル名がオプションで指定した変数の単数形である
  3. 部分テンプレート内で使用する変数名が、オプションで指定した変数の単数形である

今回でいうと、1は、呼び出し元のindex.html.erbと部分テンプレートの_post.html.erb同じディレクトリ内にあることが必要。2は、オプションで指定した変数名が@postsなので、部分テンプレートは単数形の_post.html.erbであることが必要。3は、オプションで@postsを渡しているので、部分テンプレート内で使用する変数名は、postであることが必要。 上記3つが守られていればかなり短いコードが書ける。

参考 https://b1840943.hatenablog.jp/entry/2018/05/24/221420 https://himakuro.com/rails-render-collection