はてなブログでMarkdownで目次が作りたい!
ということで、Qiitaとかみてると目次ってかっこいいなと、思うわけですよ。なので、今回は目次について調べて、実際に使ってみようと思います!
はてなブログを参考に
まず、目次を挿入したい行に[:contents]
と記入をする。
[:contents]
その下に見出しをつけてやればできるらしい。
できてる。
#の数で入る場所が変わるぜ
面白い。
参考
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でも場合分けするので覚えなければ!
参考
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_with
はform_tag
とform_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_tag
とform_for
で書き方が異なることが分かります。form_for
では、FormBuilderオブジェクトのヘルパーメソッドを使っています。FormBuilderオブジェクトとは、上の例だとform_forというヘルパーメソッドの引数である@userの情報を持っている「f」です。フォームを作るときに便利なヘルパーメソッドを使うことができます。form_forによって作られるオブジェクトということなのかな?text_fieldやsubmitなど便利なヘルパーメソッドを使えます。
form_withとは
form_tag
とform_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は、呼び出し元の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
作成日時を表示しよう!
掲示板の作成日時を制作します。 何も設定を変えずにcreated_atの時間を見ると、UTC(世界標準時)で出てきてしまいます。そのため、いくつか変更や設定をすることがあるので観ていきます。
タイムゾーンの変更
最初にタイムゾーンを日本時間に設定します。
class Application < Rails::Application config.time_zone = 'Asia/Tokyo' # タイムゾーンを日本時間に設定 end
UTCから変更することができましたが、まだまだ進めます。
読みやすいフォーマットへ
日本人の読みやすいフォーマットに変更していきます。
Railsを使っているため、便利に使えるlメソッド
を使っていきます。
使い方は、
<%= l board.created_at %>
のように、l
を使いたいところの前に置くだけですが、これだけではなんの変化もありません。次に何をするのか。
ロケールの設定
まずは、日本人が読みやすい書式にするため、アプリケーションのロケールを:ja
に変更します。
ロケールとは、あるネイティブ言語環境の明示的なモデルおよび定義のことです。ロケールの概念は、http://opengroup.org からアクセスできる POSIX 規格に明示的に定義されて含まれています。
class Application < Rails::Application config.i18n.default_locale = :ja # ロケールを日本に設定 end
次に、config/locales/ja.yml
というファイルを作り、
ja: time: formats: default: "%Y/%m/%d %H:%M:%S"
とすることで、日本人向けの書式で日時が表示されます。 さらに、表示するものを短くすることも可能です。
ja: time: formats: default: "%Y/%m/%d %H:%M:%S" short: "%m/%d %H:%M"
と、して、
<%= l board.created_at, format: :short %>
としてあげると、月日時分だけの短いものを表示させることも可能です。
参考
present?メソッドとは
present?メソッドとは
present?とは、真偽判定をしてくれるメソッドの1つで、オブジェクトに値が入っていれば真、入っていなければ偽を返してくれます。
その他のメソッドとの違い。
メソッド | メソッドの意味 |
---|---|
nil? | 変数の値がnilまたは値なしで真 |
empty? | 変数の値が空白("")の場合、真 |
blank? | nil?,empty?が真の時、真 |
present? | blank?が偽の時、真 |
present?の使い方
Rubyでは、nil?とempty?しか標準で使えないが、blank?とpresent?はRailsに搭載されているためRailsでの環境下ではそのまま使用することができる。 * 使い方例
num1 = 10 num2 = "" num3 = true num4 = false num1.present? # => true num2.present? # => false num3.present? # => true num4.present? # => false
他にも配列やハッシュの判定も行える。
arr = Array["dog", "cat", "rabit", "", "cow", ""] for var in arr do # varにarrの要素を順に入れるfor文 p var.present? end
結果は、
true true true false true false
となる。また、これはif文の中でも使うことができる。
arr = Array["dog", "cat", "rabit", "", "cow", ""] for var in arr do if var.present? puts var else puts "値は空です" end end
結果は
dog cat rabit 値は空です cow 値は空です
となります。
参考
Post.all.includes(:user).order(created_at: :desc)
includesメソッドとは?
このメソッドはモデル同士の関連付けを事前に取得してN+1問題を解決してくれるメソッド。指定された関連付けが最小限のクエリ回数で読み込まれるようになる。
N+1問題って?
ループ処理の中で、その都度SQLを発行してしまい、大量のSQLが発行されてしまい、パフォーマンスが低下してしまう問題。買い物をするときに商品を1つずつお会計しているようなもの。非常に効率が悪い。 例えば、投稿者(user)と投稿(post)が関連付けられているとします。postは複数あって、userに従属しているので、 userモデル
class User < ApplicationRecord has_many :posts end
postモデル
class Post < ApplicationRecord belongs_to :user end
とそれぞれのモデルに記述します。 次に、各投稿者が投稿したものを出力するプログラムを作成します。
User.all.each do |u| post_names = u.posts.pluck(:name).join(",") # pluckはテーブルから欲しいcolumnだけを情報として取ってくる。 p "#{u.name}が投稿したのは#{post_names}です。" end
として、これを実行すると、1回目のSQLでUserのデータを全て取り出したあと、Userのレコード1つ1つをu
に代入して、postsテーブルにアクセスしてデータを取り出すため、Userのデータの数分の処理を行うことになります。usersテーブル1回に対して、postsテーブルへのアクセスがN回。これがN+1問題です。
これを解決するためにincludesメソッドを使います。
includesメソッドの使い方
includesメソッドの定義ですが、
モデル名.includes(:関連名)
と書きます。ここでいうと、モデル名がUser、関連名がpostsになります。 ここの関連名はhas_many :postsと書いた:postsになります。
User.all.includes(:posts)
とすると、全ユーザーが持っている投稿を全て、N回もSQLを発行することなく出すことができる。
それでは、タイトルのPost.all.includes(:user).order(created_at: :desc)
を考えていきます。
Post.allなので、Postテーブルから全データを持ってきて、その際に付属しているuserも持ってきています。さらに、orderメソッドで並び替えをしています。その基準が作成日時を降順で、というふうになるということです。
参考
https://note.com/kentarotawara/n/nf8b27ba0e5d3 https://pikawaka.com/rails/includes https://qiita.com/massaaaaan/items/4eb770f20e636f7a1361