ランダムなレコードを1件取得する
親モデルに紐付いた子モデルのテーブルのダミーを作る際、 親モデルの取得方法にハマってしまったので忘備録。
10.times do title = Faker::Restaurant.name #gem fakerを使ってます body = Faker::Restaurant.description user = User.offset(rand(User.count)).first # これ Board.create!( title: title, body: body, user: user ) end
BoardはUserに紐付いてるのでUserを取ってこないとBoradが作れない。 Userからランダムに1つ取ってきたい。
はじめ、
User.find(User.ids.sample)
や
User.find(User.pluck(:id).sample)
としていたが、Userテーブルから全てのidを取得してしまっていてSQLのパフォーマンスが悪い。
User.offset(rand(User.count)).first
とすることでランダムなレコードを1つだけ取得できるのでコスパ良し。
挙動が同じでもSQLのパフォーマンスも考える必要があると感じた。
Gem 'draper'を使ってDecoratorを導入
Decoratorとは
ソフトウェアデザインパターンの1つで、既存のオブジェクトに新しい機能や振る舞いを動的に追加するもの
ModelやHelperでもよさそうだが
・Modelに何でもかんでも詰め込むのはよくない(FatModel対策)
・ModelにはDBにアクセスするような処理のみを記載することで肥大化を防ぐ
・HelperはModelから独立し直接関係していない描画ロジックを実装するのに用いる
・Decoratorは特定のモデルにがっつり関連した描画ロジックを実装するのに用いる
Decoratorというデザインパターンを導入することで、ビューファイルにロジックを記述しないといったことができ、ビューをすっきりさせる
Gem 'draper'をインストール
gem 'draper'
でbundle install
さらに
$ rails g draper:install
でインストール完了。
Decoratorの作成
$ rails g decorator モデル名
とすることで指定したモデルに対応したDecoratorを作成 中にメソッドを記述してViewで呼び出せる
class モデル名Decorator < Draper::Decorator delegate_all def メソッド名 end
オブジェクト.decorate.メソッド名
まとめ
役割分担させることでDRYを意識し、可読性やメンテナンス性を上げる。
i18nの導入
i18nを使って日本語に対応します
デフォルト言語を日本語に設定
module RunteqNormal class Application < Rails::Application config.i18n.default_locale = :ja #デフォルトのlocaleを日本語にする config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s] #複数のロケールファイルを読み込むためにpathを設定 end
Gem 'i18n-rails'をインストール
gem 'i18n-rails'
でbundle install
config/locales下にymlファイルを作成
今回はviewを扱うview/ja.yml、modelを扱うactiverecord/ja.ymlを作成
ja.ymlに日本語を設定
#インデントで階層を変える ja: users: new: title: ユーザー登録 #viewファイルで<%= t '.title' %>とすることで「ユーザー登録」を取り出せる user_sessions: new: title: ログイン helpers: submit: create: 登録
ja: activerecord: models: user: ユーザー attributes: user: name: 名前 #viewファイルで<%= t('activerecord.attributes.user.name') %>とすることで「名前」を取り出せる email: メールアドレス password: パスワード password_confirmation: パスワード確認
form_with内の記述
form_withでmodelを指定しているときはrailsが「これはユーザー登録に関するフォームだな」と認識してくれる
<%= form_with model: @user, local: true do |f| %> <%= f.label :email %> #「メールアドレス」を取り出す <%= f.text_field :email, class: 'form-control' %> #「登録」を取り出す <%= f.submit class: 'btn btn-primary' %> <% end %>
modelの指定がない場合は
<%= form_with url: login_path, local: true do |f| %> <%= f.label :email, User.human_attribute_name(:email) %> <%= f.text_field :email, class: 'form-control' %> <%= f.submit class: 'btn btn-primary' %> <% end %>
のように書く必要がある
form_with
form_with
情報を送信するためのヘルパーメソッド
<%= form_with url: root_path do |f| %> <%= f.text_field :name %> <%= f.submit %> <% end %>
のようにするとボタンをクリックしたときrootに設定したurlに遷移する。
<%= form_with model: @user do |f| %> #model: 保存したいテーブルのクラスのインスタンス <%= f.text_field :name %> <%= f.submit %> <% end %>
だと入力した情報をデータベースに保存する。
また、form_withはデフォルトでAjax通信になるが
<%= form_with model: @user, local: true do |f| %>
とすることでAjax通信を無効にできる。
rails g コマンドで自動生成されるファイルを設定する
rails g コマンドではファイルを自動生成してくれるが、不要なファイルがある場合は設定で生成しないようにできる。
class Application < Rails::Application config.generators do |g| #ここに設定を記述 #例 g.assets false end end
のように設定できる。
データベース関連のコマンド
データベースの編集について調べたのでいくつか書いておきます。
データベースの中身を空にする
rails db:migrate:reset
ロールバック(最新のマイグレーションファイルをdown状態にする)
rails db:rollback
2つ以上前のマイグレーションファイルをロールバックする
rails db:rollbadk STEP=2
数字を変えれば任意の数ロールバックできる
追記
以下のschemaを直接編集するのはよろしくなさそう。
ちゃんと新しくマイグレーションファイルを作成して変更を行う。
ファイルを直接編集
schema.rbを直接編集し、
rails db:schema:load
を実行するとその通りのテーブルを作成する データベースは空になるので注意
redirect_toの引数のインスタンス変数は何を表してるか
redirect_to @○○ はどういう意味?
このコードは一体どこにredirectしているのか?
redirect_to @post
調べてみると色んなものが省略されてこのように表記されているらしい。
redirect_to "/posts/#{@post.id}"
が省略されて
redirect_to post_url(@post.id)
さらに省略されて最終的に
redirect_to @post
になる。 ルーティングでいうと
get "/posts/:id" => "posts#show"
に繋がっている。