Gem gretelを使ってパンくずを設定する方法
こんにちは。塩濱です。
今回はgretelというGemを使ってパンくずを設定する方法についてまとめていきたいと思います。
パンくずとはこんな感じで自分が今どのページにいるかわかるというものです。(間違ってたら修正します)
前提
今回使用するgreteというGemをインストールし、使えるるようになっていること。
使用方法
$ rails generate gretel:install
rails g
コマンドを使用してgretel:install
するとbreadcrumb.rb
というファイルが作成されます。
このファイルにパンくずの設定を書いていきます。
# config/breadcrumb.rb # 記法 crumb crumsの名前を指定 do link '表示させたい文字', その文字のリンク先 parent 親の指定 end
基本的な記法はこのようになります。
crumb :admin_tags do link 'タグ', admin_tags_path parent :admin_dashboard end crumb :edit_admin_tag do |tag| link 'タグ編集', edit_admin_tag_path(tag) parent :admin_tags end crumb :new_admin_article do link '記事作成', new_admin_article_path parent :admin_articles end
idが必要になるURLにはブロックでローカル変数を渡すことでidが渡されます。
viewの設定
ここまでできたらあとは、viewで記述するだけです。
<% breadcrumb :admin_users %>
先程
breadcrumb.rb
で設定したcrumb
の名前をつけることによってパンくずが設定されます。
また、crumb :edit_admin_tag
のようにローカル変数を渡しているものはview側でも変数を渡さなければいけません。
<% breadcrumb :edit_admin_tag, @tag %>
変数を渡すことで、エラーが出ずにパンくずが設定できているかと思います。
まとめ
パンくずはWEBサイト、WEBアプリケーションなどでよく使われるものだと思うので、しっかり理解していきたいと思いました。
RSpec 〜ログイン処理をmoduleにまとめる
こんにちは。塩濵です。
RSpecを使ってテストを書いている時、ログインの処理を書くことがよくあります。
毎回書くのは大変なので今回はログイン処理のテストをmoduleにまとめることで、毎回書かずにわかりやすいコードにするということについてまとめていきます。
前提
前提として、RSpec、capybara、factory_bot_railsのGemが追加してあり、 これらのGemが正しく使えること。
RSpecの基本形
RSpecについて詳しくはここではまとめませんが、基本的な記法だけ、まとめておきます。
describe [ 仕様を記述する対象(テスト対象) ], type: [ Specの種類 ] do context [ ある状態・状態 ] do before do [事前準備] end it [ 仕様の内容(期待の概要) ] do [期待する動作] end end end
RSpecの基本的な形は上記の様になります。
itに達成するまでにdescribeやcontextを何個もネストすることもでき、内部のcontext、describe、itを並べて複数記述することもできます。
ネストや複数記述したSystem Spec
のコードの基本形も書いておきます。
describe '〜機能', type: :system do describe '登録' do context '〇〇の場合' do before do # (context内を確認するのに必要な)事前準備 end it '△△する' do # 期待する動作 end end context 'XXの場合' do before do # (context内を確認するのに必要な)事前準備 end it '○○する' do # 期待する動作 end end end discribe '削除' do # 略 end end
たくさん用語が出てきますが、大きく分けて2つのタイプに分ける事ができます。
●テストケースを整理・分類する => describe, context
●テストコードを実行する => before, it
このようにdescribe
, context
は整理、分類するために使われ、before
, it
はテストコードを実行するために記述されます。
UserFactoryの作成
ログイン処理をmoduleにまとめる前にUserFactoryを作成することによってテスト実行時に、ログインさせるユーザーを作成します。
ここではログインページに遷移し、Email
とPassword
を入力して、ログインボタンを押すと、ログインが完了するといった処理の流れにしていきたいと思います。
FactoryBot.define do factory :user do sequence(:email) { |n| "example#{n}@example.com" } password { 'password' } password_confirmation { 'password' } end end
UserFactoryの作成が完了しました。
sequence
は同一ではない適当な値が代入されます。
この場合、example1@example.com
、example2@example.com
、example3@example.com
というふうになります。
ログイン処理のmoduleを作成
supportディレクトリ
を作成し、supportディレクトリ
内にlogin_module.rb
ファイルを作成します。
login_module.rb
ファイルにログインの処理を書いていきます。
module LoginModule def login(user) visit new_user_session_path fill_in 'Email', with: user.email fill_in 'Password', with: user.password click_button 'ログイン' expect(current_path).to eq root_path end end
moduleが設定できたらこのmoduleを読み込む設定をrails_helper.rb
に記載します。
# rails_helper.rb RSpec.configure do |config| config.include LoginModule end
こうすることでSystem Spec
でログインをまとめたmoduleを使えることができます。
まとめ
今回はログインの処理をmoduleにまとめることによってログインの処理を毎回書かずにコード量を減らせるというメリットがあることについてまとめてみました。
RSpecでテストを書くことにはまだまだ理解が追いついていないので、キャッチアップとアウトプットを繰り返して、身に付けれるように努力していきたいと思いました。
ransackで「いつ~いつ」を検索するためのカスタマイズ方法
こんにちはしおはまです。
今回はransack
というGemを使って「いつ~いつ」という条件で検索できるようにするためのカスタマイズ方法についてまとめていきたいと思います。
基本的な検索方法については別の記事で紹介しておりますのでそちらを参照してください。
前提条件
今回実装するための前提条件として、ToDoアプリを作ったとして、そのToDoアプリのリストの作成日時を「いつ~いつ」という条件で検索できるようにしたいという構成になってます。
List
モデルのcreated_at
を検索対象としています。
もちろん今回使用するransack
というGemは導入している前提です。
それでは実装方法についてまとめていきます。
簡単なやり方
一番簡単な実装方法はlistcontroller
にて
@q = List.ransack(params[:q]) @lists = @q.result.includes(%i[user]).order(created_at: :asc)
として検索できるようにします。
viewにて
<%= f.label :created_at_gteq %> <%= f.text_field :created_at_gteq %> <%= f.label :created_at_lteq %> <%= f.text_field :created_at_lteq %>
とすることによって「いつ~いつ」という条件の検索ができるようになります。
しかし、この実装方法では正しく絞り込みができません。
例えば、1月1日から1月5日までのリストを検索したい場合、「xx(年)/1/1」~「xx(年)/1/5」と検索フォームに入力します。
created_at_gteq
とcreated_at_lteq
の場合、「1月1日00時〜1月5日00時」までのリストしか表示することができません。
これでは困ります。実質前日のリストしか検索できないようになってますね。
ransackのカスタマイズ
ransackは非常に便利なので、カスタマイズすることによって検索条件を変更することができます。
どうやってカスタマイズしたらいいのか。
predecates
をカスタマイズすることで検索条件を変更することができます。
predicate
を直訳すると述語。
検索するとき、「attribute(属性) + predicate(述語)」で検索しますよね。
<%= f.search_field :name_cont %>
このようなコードの場合、name(属性)+cont(述語)というふうにすることで、name属性に~を含んでいるものを検索対象としています。
このcont
という部分がpredicate
。つまり述語になります。
上記のURLはransackの公式Github内のWikiにここをカスタマイズするよ~的なことが書いてあるURLです。
このまま全部コピペして、みたいなことはしなくてよくて、カスタマイズしたい部分だけコードを書けばいいです。
config/initializers/ransack.rbを作成して、カスタマイズしていきます。
Ransack.configure do |config| config.add_predicate 'lteq_end_of_day', arel_predicate: 'lteq', formatter: proc { |v| v.end_of_day } end
この辺りはransackの公式Githubを見たほうがわかりやすいですが、1つずつ見ていきます。
config.add_predicate
→ 述語の名称。ここでカスタマイズするpredicateの名前を設定します。
arel_predicate
→入力された値を適切にフォーマットする。ここでカスタマイズするpredicateを記載します。今回はcreated_at_lteq
のpredicateであるlteq
をカスタマイズしたいので引数にlteq
を取ります。
formatter: proc
→値を検証します。無効な値は、検索に使用されません。 ここで受け取った値をどうフォーマットするかを変更できます。
デフォルトでは{ |v| "#{v}-diddly" }
となっています。
今回はend_of_dayで受け取るように設定しています。
viewの設定
ここまで設定できたらviewの設定をしていきます。
<%= f.date_field :created_at_gteq, include_blank: true, class: 'form-control', , placeholder: '年/月/日' %> <%= f.date_field :created_at_lteq_end_of_day, include_blank: true, class: 'form-control', , placeholder: '年/月/日' %>
今回、lteq_end_of_dayというpredicateを設定したので「いつ~いつ」という検索条件の「いつまで」の部分にcreated_at_lteq_end_of_day
としています。
どのようになってるか見てみましょう。
こんなふうになっており、「いつ~いつ」という検索ができるようになっていますね。
まとめ
yarnでインストールしたAdminLTE3を使った管理画面の作り方
こんにちはしおはまです。
今回はAdminLTE3を使った管理画面の作り方をまとめていきたいと思います。
そもそもAdminLTE3ってなんですか?って思いますね。
簡単にAdminLTEの説明
AdminLTE3
とはBootstrap3をベースにした、管理画面等のテンプレートテーマです。
上記のような画面や、
こんな管理者用のログイン画面だって簡単に実装できてしまいます。
スマートフォン等にも対応しており、かっこいい管理画面作りたいけどデザインに自信がない・・・といった方でも、かっこいいUIが作成できてしまいます。(ちなみに僕はフロント部分が苦手なので大変助けられました...)
前提条件
ます前提条件としてyarn
がインストールされていることを確認してください。
yarn
がインストールされていない場合は、先にyarn
をインストールしてからこちらを参考してください。
ここではyarn
のインストールは割愛させていただきます。
AdminLTEのインストール
それではさっそくAdminLTE
をインストールしていきます。
$ yarn add admin-lte
色々インストールされて最後に✨ Done in
という文字が出たら正常にインストールされています。
インストールが完了したら以下の3つのファイルが作成されます。
- node_modules
- package.json
{ "dependencies": { "admin-lte": "^3.1.0-rc" } }
- yarn.lock
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. # yarn lockfile v1 "@fortawesome/fontawesome-free@^5.15.1": version "5.15.2" resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.2.tgz#218cd7276ab4f9ab57cc3d2efa2697e6a579f25d" integrity sha512-7l/AX41m609L/EXI9EKH3Vs3v0iA8tKlIOGtw+kgcoanI7p+e4I4GYLqW3UXWiTnjSFymKSmTTPKYrivzbxxqA== "@lgaitan/pace-progress@^1.0.7": version "1.0.7" resolved "https://registry.yarnpkg.com/@lgaitan/pace-progress/-/pace-progress-1.0.7.tgz#c96fbbd9fd4cf528feed34ea0c8f9d8b3e98f0dd" integrity sha1-yW+72f1M9Sj+7TTqDI+diz6Y8N0= "@sweetalert2/theme-bootstrap-4@^4.0.1": version "4.0.3" resolved "https://registry.yarnpkg.com/@sweetalert2/theme-bootstrap-4/-/theme-bootstrap-4-4.0.3.tgz#7a9e7a99f5ecfb353e4ba9a16de918736162370c" integrity sha512-jP8cpQy4cGjlGPkEK8KF/owF00BRz5vvEdi5VrpTsiMjdkte85a1EZ/azPsX9HQrMAZ2qAmIsleV8UDcl8R2YQ== "@ttskch/select2-bootstrap4-theme@^1.4.0": version "1.5.2" resolved "https://registry.yarnpkg.com/@ttskch/select2-bootstrap4-theme/-/select2-bootstrap4-theme-1.5.2.tgz#3b4519b349f3e7831c28752a1e9617312a192656" integrity sha512-gAj8qNy/VYwQDBkACm0USM66kxFai8flX83ayRXPNhzZckEgSqIBB9sM74SCM3ssgeX+ZVy4BifTnLis+KpIyg==
このうちnode_modules
は頻繁に活用するのでちゃんとインストールされていることを確認してください。
使い方
AdminLTEの使い方はシンプルで先程インストールしたnode_modules
から使いたいhtmlファイル
を選び、erbファイル
に変換して使います。
例えば、初めに画像で使った管理者用のログイン画面を使いたい場合、
node_modules/admin-lte/pages/example/login.html
のファイルを使えば、簡単に使うことができます。
jsファイルとcssファイルを分ける
先程使用したlogin.html
はあくまでもhtmlファイル
なので中身を見るとわかると思うのですが、cssの読み込みやjsの読み込みのコードまで書いてあります。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>AdminLTE 3 | Log in</title> <!-- Google Font: Source Sans Pro --> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback"> <!-- Font Awesome --> <link rel="stylesheet" href="../../plugins/fontawesome-free/css/all.min.css"> <!-- icheck bootstrap --> <link rel="stylesheet" href="../../plugins/icheck-bootstrap/icheck-bootstrap.min.css"> <!-- Theme style --> <link rel="stylesheet" href="../../dist/css/adminlte.min.css"> </head> <body class="hold-transition login-page"> <div class="login-box"> <div class="login-logo"> <a href="../../index2.html"><b>Admin</b>LTE</a> </div> <!-- /.login-logo --> <div class="card"> <div class="card-body login-card-body"> <p class="login-box-msg">Sign in to start your session</p> <form action="../../index3.html" method="post"> <div class="input-group mb-3"> <input type="email" class="form-control" placeholder="Email"> <div class="input-group-append"> <div class="input-group-text"> <span class="fas fa-envelope"></span> </div> </div> </div> <div class="input-group mb-3"> <input type="password" class="form-control" placeholder="Password"> <div class="input-group-append"> <div class="input-group-text"> <span class="fas fa-lock"></span> </div> </div> </div> <div class="row"> <div class="col-8"> <div class="icheck-primary"> <input type="checkbox" id="remember"> <label for="remember"> Remember Me </label> </div> </div> <!-- /.col --> <div class="col-4"> <button type="submit" class="btn btn-primary btn-block">Sign In</button> </div> <!-- /.col --> </div> </form> <div class="social-auth-links text-center mb-3"> <p>- OR -</p> <a href="#" class="btn btn-block btn-primary"> <i class="fab fa-facebook mr-2"></i> Sign in using Facebook </a> <a href="#" class="btn btn-block btn-danger"> <i class="fab fa-google-plus mr-2"></i> Sign in using Google+ </a> </div> <!-- /.social-auth-links --> <p class="mb-1"> <a href="forgot-password.html">I forgot my password</a> </p> <p class="mb-0"> <a href="register.html" class="text-center">Register a new membership</a> </p> </div> <!-- /.login-card-body --> </div> </div> <!-- /.login-box --> <!-- jQuery --> <script src="../../plugins/jquery/jquery.min.js"></script> <!-- Bootstrap 4 --> <script src="../../plugins/bootstrap/js/bootstrap.bundle.min.js"></script> <!-- AdminLTE App --> <script src="../../dist/js/adminlte.min.js"></script> </body> </html>
これをRailsではアセットパイプラインの仕組みを使って、jsファイルとcssファイルを分けることができます。
ここではわかりやすくadmin.js
とadmin.scss
ファイルを作成し、個別ファイルでjsとcssを分けていきます。
#admin.scss @import 'bootstrap/dist/css/bootstrap.min.css'; @import 'admin-lte/dist/css/adminlte.min.css'; @import 'admin-lte/plugins/fontawesome-free/css/all.min.css';
#admin.js //= require rails-ujs //= require jquery/dist/jquery.min //= require bootstrap/dist/js/bootstrap.min //= require admin-lte/dist/js/adminlte.min
※application.js、application.cssでのrequire_tree .について
Railsではデフォルトでapplication.js
とapplication.css
に
# application.js //= require_tree .
# application.css
*= require_tree .
というコードがあります。
これは何を意味しているかというと、require_tree
には指定したディレクトリ以下のすべてのJSファイルを読み込むといった特徴があります。
先程作成したadmin.js
とadmin.css
は application.js
とapplication.css
と同じ階層に作成しています。
→つまりrequire_tree
を記述していることによって管理画面しか使用しないファイルまでapplication.css(js)
を読み込んでしまいます。
個別でcss、jsファイルを読み込むにはrequire_tree
は削除します。
jsファイルとcssファイルを別に読み込むことができたら元のhtmlファイルをerbで使う部分以外を削除します。(今回は元のファイルからかなりカスタマイズしています)
<div class="hold-transition login-page"> <div class="login-box"> <div class="login-logo"> <%= link_to 'ログイン', '#' %> </div> <div class="card"> <div class="card-body login-card-body"> <%= form_with local: true do |f| %> <div class="form-group"> <%= f.label :email, (t 'user_sessions.new.email') %> <%= f.email_field :email, class: 'form-control', id: 'email' %> </div> <div class="form-group"> <%= f.label :password, (t 'user_sessions.new.password') %> <%= f.password_field :password, class: 'form-control', id: 'password' %> </div> <div class="row"> <!-- /.col --> <div class="col-4 form-group"> <%= f.submit t('user_sessions.new.title') , class: 'btn btn-primary' %> </div> <!-- /.col --> </div> <% end %> </div> </div> </div> </div>
このようにすると
無事にログインが作れたかと思います。
まとめ
今回はバックエンドの実装ではなく、フロント部分の実装をしました。
フロント部分は苦手なのでしっかりアウトプットすることで知識の定着を測っていきたいです。
バックエンドの実装も今後まとめていければと思っています。
最後まで拝読していただき、ありがとうございました。
sorceryでパスワードリセット機能を実装する
こんにちは。しおはまです。
今回はsorceryというGemを使ってパスワードをリセットする機能を実装する過程をまとめてみたいと思います。
sorceryとは
そもそもsorceryってどういうGemなのか説明します。
Sorceryは、ユーザ認証機能を簡単に実装できるライブラリ
で、MITライセンスのオープンソースソフトウェアとして公開されています。
↑がsorcery
のgithubです。
ユーザの認証の基本的な機能であるパスワード認証を始め、
- User Activation
- Reset Password
- Remember Me
- Session Timeout
- Brute Force Protection
- Basic HTTP Authentication
- Activity Logging
といった機能が揃っており、必要に応じて機能を選んで使うことができます。
ログイン機能やパスワード認証の実装についても今後ブログでまとめたいですが、今回はパスワードをリセットする方法にフォーカスを当ててまとめていきたいと思います。
なお、ログイン機能については今回は実装できている前提で説明をしますのでご了承ください。
sorceryのインストール
さっそくパスワードをリセットする方法について見ていきます。
まずは、Gemfile
にsorcery
を記述してbundle install
しましょう。
# Gemfile gem 'sorcery'
パスワードのリセットを実装するにはsorcery
のReset Password
というmoduleを使用します。
こちらのgithubに一連の流れは書いてあるので、より正しい情報が知りたいという方は参照してみてください。
moduleのインストールとマイグレーションファイルの作成
まず初めの手段として下記のコマンドでmoduleのインストールとマイグレーションファイルの作成をします。
$ rails g sorcery:install reset_password --only-submodules
コマンドを叩くと、自動的にマイグレーションファイルが作成されます。
class SorceryResetPassword < ActiveRecord::Migration def change add_column :users, :reset_password_token, :string, default: nil add_column :users, :reset_password_token_expires_at, :datetime, default: nil add_column :users, :reset_password_email_sent_at, :datetime, default: nil add_index :users, :reset_password_token end end
マイグレーションファイルが作成されたことを確認して、マイグレーションを実行します。
$ rails db:migrate
config/initializers/sorcery.rb
(sorceryの設定ファイル)を見ると自動的にpassword_reset
のサブモジュールを使用することが書かれています。
# Gemfile Rails.application.config.sorcery.submodules = [:reset_password] #################################### Rails.application.config.sorcery.configure do |config| config.user_config do |user| user.reset_password_mailer = UserMailer end end
PasswordResetsコントローラーの追加
ここまで設定できたらrails g
コマンドでPasswordResets
コントローラーを作成します。
アクションはパスワードを変更するcreate、編集ファイルのedit、作成するためのupdateを指定します。
rails g controller PasswordResets create edit update
PasswordResets
コントローラーが作成できたらReset passwordのgithubにしたがってコードを記述します。(多少カスタマイズしているところもありますが、おおまかなところは変わり無いです)
class PasswordResetsController < ApplicationController skip_before_action :require_login def create @user = User.find_by(email: params[:email]) @user&.deliver_reset_password_instructions! if @user flash[:success] = 'パスワードリセット手順を送信しました' redirect_to root_path end def edit @token = params[:id] @user = User.load_from_reset_password_token(params[:id]) return not_authenticated if @user.blank? end def update @token = params[:id] @user = User.load_from_reset_password_token(params[:id]) return not_authenticated if @user.blank? @user.password_confirmation = params[:user][:password_confirmation] if @user.change_password(params[:user][:password]) flash[:success] = 'パスワードを変更しました' redirect_to login_path else flash.now[:danger] = 'パスワードを変更できませんでした' render :edit end end end
細かいメソッドの説明は割愛しますが、create
アクションはパスワードをリセットするためのメールアドレスを送信し、どのユーザーのメールアドレスかを判定します。
edit
アクションでは実際にパスワードをリセットするための判定がされています。(詳しくはgithubのWikiでload_from_reset_password_token
の動きなどを確認するといいと思います)。
update
アクションではパスワードをリセットする動きを制御しています。
if @user.change_password
の部分でパスワードの条件分岐をしており、正しくパスワードが入力されたらtrue
になり、正常にパスワードがリセットされるということになります。
ルーティングの設定
コントローラーまで設定できたら次にルーティングの設定をしていきます。
ルーティングの設定は簡単ですね。
# route.rb resources :password_resets, only: [:create, :edit, :update]
これでルーティングが正しく設定されますね。
送信メールの設定
ルーティングの設定ができたら送信するためのメールを設定していきます。
# reset_password_email.text.erb Hello, <%= @user.email %> =============================================== You have requested to reset your password. To choose a new password, just follow this link: <%= @url %> Have a great day!
ここは自分が送信メールで設定できる部分なので自由にコードを書いてもいいのですが、<%= @user.email %>
でパスワードをリセットするために送信したメールアドレス、<%= @url %>
にパスワードをリセットするためのURLが記載されますので、ご注意ください。
# app/mailers/user_mailer.rb def reset_password_email(user) @user = User.find user.id @url = edit_password_reset_url(@user.reset_password_token) mail(:to => user.email, :subject => "Your password has been reset") end
user_mailer.rb
はApplicationMailer
を継承しており、メールに関する設定を変更できます。
特にmail(to: user.email, subject: 'パスワードリセット')
で、メールの送信元、メールの題名を設定することができます。
フォームの作成
ここまで設定できたらあとはフォームを作成するだけです。
どのようにフォームを作成するかは個人個人で違うと思いますが、githubを参考に# app/views/password_resets/new.html.erb
や# app/views/password_resets/create.html.erb
にコードを書いていくと簡単に作成することができます。
まとめ
ここまで読んでいただきありがとうございます。
長くなってしまいましたが、パスワードリセット機能はログイン機能を実装したら必然的にリセット機能も必要になってくるのでしっかり理解しておきたいところですね。
にしてもsorceryは使いたい機能を使う時にサブモジュールをインストールして自分で実装できるのがいいですね。
ransackで検索機能を実装する
こんにちは、しおはまです。
今回はransackという検索機能を実装できるgemの使い方をまとめてみます。
ransackとは
冒頭で説明した通り、ransackは検索機能を簡単に実装することができるRailsのGemです。
検索機能を実装することで掲示板やToDoアプリ、その他WEBアプリにおいて検索機能が実装されているとなにかと便利です。
それでは使い方をみていきます。
ransackのインストール
まずはGemを使うためにGemfileにransackを追加していきます。
gem 'ransack
Gemfileに追加したらbundle install
して準備完了です。
ransackの使い方
まず、コントローラーからみていきましょう。
例として、ユーザーの名前を検索できる機能を実装することを想定し、 users_controller
ではこのような形式になってるとしましょう。
# users_controller def index @users = User.all end
インスタンス変数@users
にUserオブジェクトの全ての値が入っています。
この値を検索できるように下記のように書き換えます。
# users_controller def index @q = User.ransack(params[:q]) @users = @q.result(distinct: true) end
いきなりransackとか(params[:q])とかresultとか出てきて戸惑うかもしれませんが、このメソッドの概要を説明します。
用語 | 説明 |
---|---|
params[:q] | ビューファイルから送られてくるパラメーター。 |
ransackメソッド | 送られてきたパラメーターを元にテーブルからデータを検索するメソッド。(whereメソッドのransack版というイメージ。) |
resultメソッド | ransackメソッドで取得したデータをActiveRecord_Relationのオブジェクトに変換するメソッド。 |
なんとなくイメージは掴めたでしょうか。
@q
の部分は自分で好きな変数名をつけても動きますが、慣習的に@q
を使用します。
次に検索をフォームを作っていきます。
# 検索フォーム.erb(例) <%= search_form_for @q, url: users_path do |f| %> <%= f.label :name, "Keyword" %> <%= f.search_field :name_cont %> <%= f.submit "検索" %> <% end %>
検索フォームを実装するには<%= %>
で囲んでsearch_form_for
メソッドを使います。
search_form_for
メソッドはransackで用意されているメソッドです。
これがどのようにして検索フォームとしてできているのか。
→_cont
の部分です。
_cont
はransackで用意されているメソッドで、検索したワードが含まれているレコードを取得するためのメソッドです。
つまり、検索結果に属性(カラム)が含まれていれば表示するというものになります。
ransackには検索のためのメソッドが沢山ようされています。
検索に使えるメソッド
_cont
のような便利なメソッドの他にたくさんの便利メソッドが用意されているので少し紹介します。
メソッド名 | 説明 |
---|---|
_eq | 完全に一致するとき |
_not_eq | 完全に一致しないとき |
_matches | 一部が一致するとき |
_does_not_match | 一部が一致しないとき |
_matches_any | いずれかに一致するとき |
_matches_all | 全てに一致するとき |
_does_not_match_any | いずれにも一致しないとき |
_does_not_match_all | 全てに一致しないとき |
_lt | 〜未満のとき |
_lteq | 〜以下のとき |
_gt | 〜より大きいとき |
_gteq | 〜以上のとき |
_present | nullでも空でもないとき |
_blank | nullまたは空のとき |
_null | nullのとき |
_not_null | nllではないとき |
_in | 配列内の値と一致するとき |
_not_in | 配列内のどの値とも一致しないとき |
_lt_any | いずれかの値より少ないとき |
_lteq_any | いずれかの値以下のとき |
_gt_any | いずれかの値より大きいとき |
_gteq_any | いずれかの値以上のとき |
_lt_all | 全ての値よりも少ないとき |
_lteq_all | 全ての値以下のとき |
_gt_all | 全ての値より大きいとき |
_gteq_all | 全ての値以上のとき |
_not_eq_all | 指定した値ではないとき |
_start | 前方一致のとき |
_not_start | 前方不一致のとき |
_start_any | 〜のいずれかで始まるとき |
_start_all | 〜の全てから始まるとき |
_not_start_any | 〜のいずれかで始まらないとき |
_not_start_all | 〜の全てから始まらないとき |
_end | 後方一致のとき |
_not_end | 後方不一致のとき |
_end_any | 〜のいずれかで終わるとき |
_end_all | 〜の全てで終わるとき |
_not_end_any | 〜いずれかで終わらないとき |
_not_end_all | 〜の全てで終わらないとき |
_cont | 〜の部分が一致するとき |
_cont_any | 〜のいずれかが含まれているとき |
_cont_all | 〜の全てが含まれているとき |
_not_cont | 〜に部分が一致しないとき |
_not_cont_any | 〜のいずれかが含まないとき |
_not_cont_all | 〜の全てが含まれないとき |
_i_cont | 大文字と小文字を区別しない値が含まれるとき |
_i_cont_any | 大文字と小文字を区別しないいずれかの値が含まれるとき |
_i_cont_all | 大文字と小文字を区別しない全ての値が含まれるとき |
not_i_cont | 大文字と小文字を区別しない値が含まれないとき |
_not_i_cont_any | 大文字と小文字を区別しないいずれかの値が含まれないとき |
_not_i_cont_all | 大文字と小文字を区別しない全ての値が含まれないとき |
_true | 真偽値のレコードを取得するとき |
_false | 真偽値と反対のレコードを取得するとき |
長くなってしまいましたがこのようなメソッドが用意されているので、時と場合によって使い分けるようにしましょう。
まとめ
- コントローラーとビューを変更して、検索機能を実装する。
- viewファイルではsearch_form_forメソッドを使用する
検索機能は汎用性が高く、よく使われると思うので、いろいろなメソッドを使いこなせるようにしていきたいです。
kaminariの使い方 まとめ
こんにちは。しおはまです。
今回はページネーションを実装するのに便利なGem(kaminari)の基本的な使い方をまとめてみます。
ページネーションとは
検索結果が多くなり、1ページに収めようとするとUI的に見にくい場合なんかにページネーションは使用されていますね。
または、掲示板アプリなどでたくさん記事を投稿すると、古い記事がどんどん下のページにいってしまい、見にくくなりますよね。
そんな時、ページネーションを実装し、ページを分けることで見やすくなります。
そこで、RailsのGemで簡単にページネーションが実装できるkaminariというGemの使い方を学んだので、自分なりにアウトプットしていこうと思います。
kaminariのインストール
まず初めにGemfile
にkaminariを追加し、bundle install
します。
gem 'kaminari'
インストールが完了したらkaminariを使うことができます。簡単ですね。
記述の仕方
使い方はシンプルで、controllerでページネーションさせたいデータにpage
メソッドを追加して、viewファイルにて、paginate
メソッドを用いてページネーションを追加するだけです。
文脈だとわかりにくいのでここでは例として、ToDoアプリを作ったとして、そのToDoリストをページネーションさせたいとします。
ToDoアプリのモデルはTaskとし、ToDo一覧ページでタスクが10件以上あるとページネーションさせるとします。(あくまでも例です。アプリにてCRUD処理が実装できている前提です。)
# tasks_controller.rb class TaskController < ApplicationController def index @tasks = Task.all end end
Taskコントローラーのindexアクションではこのようなコードになっていると思います。
ここで、kaminariをインストールした時に追加されるpageメソッドを使います。
pageメソッドについては後述します。
# tasks_controller.rb class TaskController < ApplicationController def index @tasks = Task.all.page(params[:page]) -----------この部分 end end
page(params[:page]) を追加し、viewファイルにてページネーションの指定をすることでページネーションが完成します。
#viewファイル <%= paginate @tasks %>
このようにviewファイルにてページネーションを表示させたい部分にpaginate
メソッドを使用し、引数に先程page
メソッドを設定したインスタンスを渡すことでページネーションが実装されます。
ちなみにデフォルトでは、ページネーションが1ページに表示するレコード数はデフォルトで25件です。
※pageメソッドについて
kaminariを導入すると、モデルクラスにpageメソッドが定義されます。このメソッドは、ページネーションにおけるページ数を指定します。ビューのリクエストの際paramsの中にpageというキーが追加されて、その値がビューで指定したページ番号となります。よって、pageの引数はparams[:page]となります。
kaminariのデフォルト設定の変更
今の状態でもページネーションは実装できていますが、このままでは1ページに表示するレコード数がで25件なので、1ページに表示するレコードを10件に変更したいです。
やり方は様々ありますが、ここではrails g
コマンドでconfig/initializers
に設定ファイルを作成させましょう。
$ rails g kaminari:config
これで簡単にconfig/initializersファイルにkaminari_config.rb
が作成されます。
作成された kaminari_config.rb
を見るとこのようなコードが書かれていると思います。
Kaminari.configure do |config| # config.default_per_page = 25 # config.max_per_page = nil # config.window = 4 # config.outer_window = 0 # config.left = 0 # config.right = 0 # config.page_method_name = :page # config.param_name = :page end
ここでkaminariのデフォルトの設定を変更できます。
色々ありますが、1つずつ見ていきましょう。
config.default_per_page
→1ページ辺りの項目数を変更できます。
config.max_per_page
→1ページ辺りの最大数を変更できます。
config.window
→現在のページから、左右何ページ分のリンクを表示させるかを変更できます。
config.outer_window
→最初(First)と最後(Last)のページから、左右何ページ分のリンクを表示させるかを変更できます。
config.left
→最初(First)のページから、何ページ分のリンクを表示させるかを変更できます。
config.right
→最終(Last)ページから、何ページ分のリンクを表示させるかを変更できます。
config.page_method_name
→モデルに追加されるページ番号を指定するスコープの名前を変更できます。
config.param_name = :page
→ページ番号を渡すために使用するパラメータ名を変更できます。
kaminari_config.rb
ではこのような色々なデフォルトの設定を変更することができます。
今回は1ページに表示するレコードを10件に変更したいので、
config.default_per_page = 10
というふうに変更することで1ページに表示するレコードを10件に変更することができます。
まとめ
ここまでページネーションを簡単に実装することができるGemkaminari
について、使い方を自分なりにまとめてみました。
ページネーションは何度も実装するものでは無いかもしれませんが、忘れてしまわないようにブログにまとめることで、整理することができました。
ここまで読んでいただき、ありがとうございました。