20201206のRailsに関する記事は26件です。

メッセージが投稿されたときに、一時的に「成功しました」的な表示をさせたい

はじめに

 メッセージが投稿されたときに、ちゃんと投稿できたか、ユーザーに知らせた方が、使い勝手がよい思い、調べた。

コントローラー側の記述

controllers
def create
  @post = Post.new(post_params)
  if @post.save
    flash[:success] = '送信されました'
    redirect_to root_path
  else
    render :new
  end
end

ビュー側の記述

views
<%= flash[:success] %>

最後に

 成功したときだけじゃなく、失敗したときにもメッセージを表示できるようにしよう!

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

sessionについて【アウトプット】

sessionについて自分用のアウトプットとして書いていく。
まずsessionとは何か
*変数session:サイト内でページを移動しても情報を維持し続けることができる。また、sessionで代入された値は、ブラウザに保存される。ブラウザとはGoogoleChromeとかである。

どんな感じに書くのか。
session[:キー名] = 値

【users.controller.rb】
def login
@users = User.find_by(...)
if @user
session[:user_id] = @user.id

もし、@userがあるならsessionに@user.idを代入する。
これで@user.idの情報が保持され続ける。

これがあればその人専用のサイトを見れたり、ログインできるのではないかなと個人的には考えている。

ログイン状態を解除したいときはログアウトができるようなリンクを作りsessionにnilを代入させてあげる。

こんな感じかな
session[キー名] = nil

【users.controller.rb】
session[:user_id] = nil
end

今日は久々に投稿したけどノートにはまとめてあるからアウトプットはできているはず
時間あるときに今日見たく書いていきたい。

では以上

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

rails APIモード devise

手順だけ

ターミナル
rails new devise_token_auth --api -d mysql
Gemfile
# トークンベースの認証を行うためのgem
gem 'devise'
gem 'devise_token_auth'
ターミナル
$ bundle install
$ rake db:create
$ rails g devise:install 
$ rails g devise_token_auth:install User auth
$ rails g controller api/auth/registrations
api/auth/registrations_conroller.rb
module Api
  module Auth
    class RegistrationsController < DeviseTokenAuth::RegistrationsController
      private
      def sign_up_params
        params.permit(:first_name, :last_name, :email, :password, :password_confirmation)
      end
      def account_update_params
        params.permit(:first_name, :last_name, :email)
      end
    end
  end
end
config.eb
Rails.application.routes.draw do
  namespace :api do
    mount_devise_token_auth_for 'User', at: 'auth', controllers: {
        registrations: 'api/auth/registrations'
    }
  end
end

リクエストごとに token を新しくしない、変更頻度の設定を決める

config/inizialize/devise_token_auth.rb
  ...
  config.change_headers_on_each_request = false
  config.token_lifespan = 1.month
  config.headers_names = {:'access-token' => 'access-token',
                          :'client' => 'client',
                          :'expiry' => 'expiry',![スクリーンショット 2020-12-06 23.13.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239663/9812bd33-0c32-b768-4e99-e2544876a1a7.png)

                          :'uid' => 'uid',
                          :'token-type' => 'token-type' }
 ...
model/user.rb
class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  include DeviseTokenAuth::Concerns::User
end

:trackableがあるとSessionのcreateがうまく行かないので一応削除。

postmanで確認してみる

新規登録

スクリーンショット 2020-12-06 22.51.13.png

ログイン

HeaderにContent-Typeapplication/jsonとして登録
そして確認
スクリーンショット 2020-12-06 23.12.19.png

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

Javascriptエラー問題集

事前準備

ターミナル上で下記コマンドを実行してcloneする。

git clone https://github.com/Shu-Hos/ajax_app_error.git
cd chat-app_error
bundle install
yarn install
rails db:create
rails db:migrate

問題1

新規投稿をしてもイベントが発火しません。
まずはこちらを解決しましょう!

問題2

新規投稿をしようとすると添付画像のエラーが表示されます。
次はこちらの問題を解決してください。

スクリーンショット 2020-12-06 19.42.49.png

ヒント

エラーの英文のしっかりと確認しましょう。
formText.value = "";に対してCannot set property value of nullと出ています。こちら翻訳するとnullのプロパティ値を設定できないという意味になります。こちらをヒントにプロパティ周りを確認してみると良さそうです。

問題3

問題2のエラーが解決した後に再度新規投稿しても非同期ではUndefinedが出てしまい、一度リロードしないと投稿内容が反映されません。
こちらを修正して非同期で投稿ができるようにしましょう

スクリーンショット 2020-12-06 19.50.04.png

ヒント

こちらエラーが出ずにUndefinedが出るということは、ajaxでレスポンスを受け取った後、新しい要素を作り出して表示するまでのプロセスのどこかに問題が潜んでいる可能性が高いです。

問題4

残りはcheck機能のエラー問題です。
投稿をクリックしても色が変化せずに添付画像のエラーが出てしまいます。
こちら原因が2箇所あります。

スクリーンショット 2020-12-06 21.40.50.png

ヒント

こちら404(Not found)エラーが発生していることから、Ajax送信時に問題が起きている可能性が高いです。
ajaxの送信内容やコントローラー周りを疑ってみましょう。
コントローラーでbinding.pryを使用してみるのも良いかも知れません。

問題5

スクリーンショット 2020-12-06 22.02.43.png

エラーはでなくなりましたが投稿を何回クリックしても色が白に戻りません。
こちらがクリックする度に色がグレーと白が交互に変わるように修正してください。

ヒント

コンソールにエラーが出ていない+グレーには色が変わるという部分から
レスポンスを受けとった後に問題が潜んでいる可能性が高そうです。
色はどのように変化させているのかロジックを深く考えてみましょう。

お疲れさまです!!
何かご不明点とかあれば、今後ぜひ教えてください!

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

【Ruby】コントローラーでメソッドによるコード省略

読んでなるほど!と思うのに、しばらくするとなんだっけ?ってなるシリーズその1

・edit
・show
この2つのアクションの記述をぎゅっとコンパクトに。

使用するのは、
before_action
onlyオプション

tweets_controller.rb
class TweetsController < ApplicationController

  def edit
    @tweet = Tweet.find(params[:id])
  end
#↑editの中身「@tweet = Tweet.find(params[:id])」と、
#↓showの中身が同一の記述になっている
  def show
    @tweet = Tweet.find(params[:id])
  end

  private
end

重複している部分を「set_tweet」として、privateメソッドに移し替える

tweets_controller.rb
  private

 def set_tweet
    @tweet = Tweet.find(params[:id])
 end

before_actionの記述方法

tweets_controller.rb
before_action :処理させたいメソッド名

before_action :set_tweet, only: [:edit, :show]

最後にまとめると

tweets_controller.rb
class TweetsController < ApplicationController
  before_action :set_tweet, only: [:edit, :show]

  def edit
  end

  def show
  end

  private

  def set_tweet
    @tweet = Tweet.find(params[:id])
  end
end

editとshowに入っていた
@tweet = Tweet.find(params[:id])
これをset_tweetとインスタンスで定義。
そして一番上で
:set_tweet, only: [:edit, :show]
としてeditとshowのみに使うようonlyオプションで指定

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

【Rails】プログラミング初心者が大学生の悩みを解決するアプリに付けた機能一覧

1. はじめに

少し前に大学生の悩みを聞く機会があったのですが、そこで多くの大学生が「課題が多すぎる」という悩みを抱えていることを知りました。〆切を守れないことから自己嫌悪に陥ってしまう学生を目の当たりにすることもありました。

特に最近はこんなご時世ですから、通常の授業がオンライン授業に切り替わり、教員は学生の出席状況を小まめにチェックしたり、学生にテストを課したりすることができない分、レポート課題などを出すという流れに変わってきています。その結果、ますます多くの課題に頭を抱える大学生が増えているというわけです。

スクリーンショット 2020-11-21 17.02.12.png

というわけで、「課題の多さに悩む大学生を何とかして助けたい」という思いが生まれ、その思いをもとにオリジナルアプリを作ることにしました。

そうは言っても、課題そのものを減らすことはできないので、できるだけ楽しく課題に取り組めるような仕組みを作るという方向性でアイデアを出していきました。

そして誕生したのが 『〆KiList』 です。

ezgif.com-video-to-gif.gif

Illustrated by Strories by Freepik

2. 「課題が多すぎる」という悩みを深掘る

1. はじめにで説明した通り、〆KiListを作成した目的は課題の多さに悩む大学生を助けるためでした。この目的を達成するためには、まず「課題が多すぎる」という悩みが表す意味をさらに深掘って考える必要がありました。

私は「課題が多すぎる」という悩みの根源は、以下の2点ではないかと考えました。

  • 課題に取り組むモチベーションがわかない

  • 課題のスケジュール管理が難しい

                        

よって、大学生の「課題が多すぎる」悩みを解決するためには、以下の2つの仕組みを作る必要があると考えました。

  • 課題に取り組むモチベーションが上がる仕組み

  • 課題のスケジュール管理をしやすくする仕組み

3. 機能一覧

〆KiListに付けた全ての機能は以下の18機能です。

       機能    Gem
   ログイン機能    devise
 ToDoリスト機能(CRUD)     ×
   カレンダー機能  FullCalendar 
   いいね機能(Ajax)     ×
   コメント機能(Ajax)     ×
   フォロー機能     ×
     宣言機能    
  わたしも機能(勝手に命名)     ×
  つぶやき機能(CRUD)     ×
    検索機能   ransack
  ページネーション機能   kaminari
グラフ機能(ドーナツチャート)    Chartkick
   レベル表示機能     ×
   ランキング機能     ×
   付箋機能(勝手に命名)     ×
  画像アップロード機能  CarrierWave 
   簡単ログイン機能     ×
    管理者機能       ×

この中でも、「課題が多すぎる」という悩みを解決するのに必要な2つの仕組みを実現するために付けた機能は、② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑫ ⑬ ⑭ ⑮の12機能です。

       機能    Gem
 ToDoリスト機能(CRUD)     ×
   カレンダー機能  FullCalendar 
   いいね機能(Ajax)     ×
   コメント機能(Ajax)     ×
   フォロー機能     ×
    宣言機能         ×
  わたしも機能(勝手に命名)     ×
  つぶやき機能(CRUD)     ×
グラフ機能(ドーナツチャート)    Chartkick
   レベル表示機能     ×
   ランキング機能     ×
   付箋機能(勝手に命名)     ×

これらの機能の概要と2つの仕組み実現のために工夫した点・思いについて、ここから1機能ずつ解説したいと思います!

4. 機能の解説

ToDoリスト機能

 概要 
ToDoリスト機能です。使い方は、とてもシンプルです。

①課題を登録
②課題がリスト化される
③完了ボタンを押すと完了済みに入る(完了済みから戻すのもできます!)

2.gif

ezgif.com-gif-maker (1).gif

工夫した点

①シンプル
まずはシンプルを心がけました。アプリ名にもなっているメイン部分ではありますが、色々機能があっても使いにくいと思ったのでここはシンプルに課題名と〆切日だけを表示させました。

②リマインド
「〆切をうっかり忘れていた」というようなことを防ぐために〆切1日前、〆切当日、〆切が過ぎている課題のリマインド機能を付けました。
また、〆切が過ぎている課題にはリストに赤い砂時計が表示されるようにしました。

スクリーンショット 2020-12-05 2.56.02.png

③実施日の登録
課題登録時に、〆切の何日前にするかという課題実施日も登録してもらうようにしました。これは、課題を「いつやるか」を考える習慣を付けることは、スケジュール管理が得意になる上で重要だと考えているためです。この仕組みを利用してその習慣を身に付けてもらえたらいいなという思いを込めて付けました。

カレンダー機能

 概要 
〆切を可視化できるカレンダーです。課題を登録すると、自動で〆切日のみ表示されるようになります。終わった課題は表示されません。それぞれの課題をクリックすると詳細画面に飛びます。

スクリーンショット 2020-11-21 23.45.37.png

工夫した点
①シンプル
リスト機能と同じくこちらもシンプルを心がけました。
〆切日のみに絞ってカレンダーに表示させることで、〆切日がひと目で分かるようにしました。

②〆切のカラー
通常は緑色のラベルで課題が表示されますが、〆切が過ぎている課題はでラベルが表示されます。パッと見て、「いますぐやるべき課題」が分かります。

いいね・コメント・フォロー

 概要 
SNSにはお馴染みの3機能です。

・いいね
ezgif.com-video-to-gif.gif

・コメント
ezgif.com-video-to-gif.gif

・フォロー
ezgif.com-video-to-gif.gif

工夫した点

これらの機能自体に特別な工夫があるわけではないですが、SNSやっている人なら誰もが一度は味わったことのある「いいねやコメントをもらう喜び」「誰かにフォローされる喜び」を〆KiListユーザーにも味わってもらい、課題に取り組む際のモチベーションにしてもらいたいなという思いを込めて実装しました。

宣言機能(オリジナル)

 概要  
課題を登録した際に、宣言ボタンが表示されます。
押すと、「いつ何の課題をするか」をみんなのつぶやき一覧に投稿できます。
ezgif.com-video-to-gif.gif

工夫した点
①手間いらず
無駄な行程を踏まずに済むように、文章を自分で入れなくても、ボタン1つですぐに宣言できるようにしました。

②やらざるを得ない環境の仕組み化
みんなの前で宣言して、やらざるを得ない状況を作る仕組みを仕掛けました。自分で管理するだけではついつい「明日でいっか」ってなってしまいますが、他の人に宣言しちゃうと何かやらなきゃいけない気がしてくると思います。その効果を利用しました。

わたしも機能(オリジナル)

 概要  
挙手のマークを押すと、他の人が宣言している課題を、自分の〆KiListにも登録できます。挙手のマークは、自分以外の他のユーザーの課題宣言の投稿にのみ表示されています。主に同じ大学、学部の人とかが使いやすい機能かと思います。
ezgif.com-video-to-gif.gif

工夫した点
①手間いらず
他の人の宣言を見て、「あ、この課題自分もやらなきゃいけなかった!」と思った時に、余計な行程を辿らず、すぐに課題が登録できるようにと思い、この機能を付けました。

②仲間意識・ライバル意識を活用
「友達がやるなら、自分も一緒に頑張ろう」という仲間意識「あいつに負けないように自分も頑張らないと」というライバル意識をモチベーションにする方は結構多いと思います。そういう人たちに、積極的に課題を登録してもらえるようにと思い、この仕組みを仕掛けました。

つぶやき機能

 概要  
つぶやきを投稿できる機能です。
スクリーンショット 2020-12-05 11.44.17.png

工夫した点
ToDoリスト×SNS
孤独な環境だと、どうしても課題が進められない人は多いと思います。そこで、つぶやき機能(SNS的な要素)を使って他の学生と積極的にコミュニケーションを取りながら、みんなで課題に取り組める仕組みを作りたいと思い、実装しました。

グラフ機能(ドーナツチャート)

 概要  
課題達成率(今まで登録した課題のうち、達成済みの課題数の割合)、〆切遵守率(達成した課題数のうち、〆切を守った課題数の割合)がドーナツチャートでグラフ化されます。

課題を完了すると、〆切達成率・〆切順守率が変わっていることが分かります。
ezgif.com-video-to-gif.gif

スクリーンショット 2020-12-05 11.54.29.png

工夫した点
①課題に取り組む姿勢を数値化・可視化
努力を数字やグラフで可視化させ、モチベーション維持に繋げてくれたらいいなと思い、実装しました。

②人に見られる環境の仕組み化
グラフはマイページに表示されています。そのページに飛んでくれば、自分の課題に取り組む姿勢が他の人の目に触れることになります。人に自分の努力値が見られている環境に置かれていることもまた頑張るモチベーションになるかなと思い、この機能を付けました。

レベル表示機能

 概要  
課題の完了数が増えていくにつれてレベルが上がっていきます。
「ビギナー」「中級者」などクラスも表示されます。
レベルが高ければ高いほど、課題をしっかりと完了させているという証明になります。
スクリーンショット 2020-12-05 12.28.21.png

工夫した点
①次のクラスを目指すワクワク感
ユーザーが「次はどんなクラスかな?」「私も〇〇クラス目指して頑張ろ!」と楽しめるようにして、頑張れるモチベーションにしてもらえたらなと思い、実装しました。
この辺のバリエーションはまだまだ増やす余地ありなので、さらに色々なクラスを用意して、ユーザーにワクワクしてもらえるような仕様にしていきたいと考えています。

②遊び心
真面目すぎるアプリは、少し使うとすぐに飽きてしまいます。なので、所々遊び心を加えて、ユーザーに楽しんでもらいながら長く使ってもらえるようにと思い、「何やコレ」と言うようなクラスを用意しました。例えば、Lv.1のクラスは「赤ちゃん」です。かわいいですね。育てたくなりますね
スクリーンショット 2020-12-05 12.36.12.png

ランキング機能

 概要  
レベルが上位3名になると、ランキングにユーザー名とレベルが載ります。
スクリーンショット 2020-12-06 16.20.25.png

工夫した点
ランキングに載ることへのモチベーション
ランキングに載ることもまた、一種のモチベーションになると思います。
「ランキングに名前を載せるために課題を頑張ろう!」と思ってもらえるようにこの機能を付けました。
ただし、今のところ見ての通りあまりにもデザインがシンプル過ぎて、名前が載っても「何だかな〜」と言う感じなので、もう少しモチベーション上がるような見栄えを目指したところです。

付箋機能

 概要  
登録した課題と〆切日が、付箋のような感じで表示されます。本日〆切、本日実施の課題もすぐに分かります。
ここから課題の詳細ページに飛ぶこともできます。
スクリーンショット 2020-12-06 16.43.53.png

工夫した点
アプリ使用中は〆切を意識
このアプリは、課題の〆切日を守るためのアプリなので、常に〆切を意識してもらう必要があります。通常であれば、〆KiListのページに行かないと〆切を見ることができないことになってしまいますが、この付箋機能をマイページとつぶやき一覧ページに載せることで、アプリを使っている最中は常に〆切を意識してもらえることになります。〆切のうっかり忘れの防止をさらに強化するために、この機能を実装しました。

番外編:〆KiListの色について

今回〆KiListを作成するにあたって、カラーを下記の通り選択しました。

  • メインカラー:ネイビーオレンジホワイト
  • サブカラー:グレーブルー(ボタンにカーソル置いた時)

基本的には、メインカラーを使うように気をつけました。
自分はデザイン的な知識は全くないので、色で統一感を出すことでそれなりにまとまりのある感じを出そうという発想になり、その結果使う色を3色に絞りました。

スクリーンショット 2020-12-06 17.59.26.png

ただし、全部がこの色だと面白味がないので、ボタンにカーソルをのせた時やちょっとしたデザインの部分に関しては、グレーやブルーなど、メインカラーに比較的馴染みが良いであろうカラーを使うようにしました。
(カレンダーは土曜日のイメージが青や水色、日曜日のイメージが赤やピンクなので例外です)

尚、一番のメインカラーはネイビーですが、これは青系の色の方が、「勉強」「課題」といった真面目な印象を与えやすいから選択しました。

そこにオレンジという暖色を加えたのは、〆KiListがSNS的な要素を持ち、「人との繋がり」「励まし合い」といった要素も含むからです。

ネイビー×オレンジという組み合わせが結構しっくりきたのでこれらの色をメインに使いました。

さいごに

長くなりましたが、以上です。

大学生の「課題が多すぎる」という悩みを解決するためには、

①課題に取り組むモチベーションが上がる仕組み 
②課題のスケジュール管理をしやすくする仕組み

この2つの仕組みが必要で、この仕組みを実現するために、今回解説した12機能を付けたというお話でした。
ここまで読んでいただいてありがとうございます。

予定

①この記事は、今のところ「思い」の部分が前面に出た記事になっておりますので、今後はそれぞれの機能についてどのように実装したかという技術的な部分も付け加えていけたらと思っています。

②今回は、機能という部分に着目しましたが、ポートフォリオ(このアプリ)の作成の全体的な解説記事は別で投稿します。それまでにAWSでのデプロイを頑張ります。

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

【Rails】プログラミング初心者が大学生の悩みを解決するアプリに付けた12機能

1. はじめに

少し前に大学生の悩みを聞く機会があったのですが、そこで多くの大学生が「課題が多すぎる」という悩みを抱えていることを知りました。〆切を守れないことから自己嫌悪に陥ってしまう学生を目の当たりにすることもありました。

特に最近はこんなご時世ですから、通常の授業がオンライン授業に切り替わり、教員は学生の出席状況を小まめにチェックしたり、学生にテストを課したりすることができない分、レポート課題などを出すという流れに変わってきています。その結果、ますます多くの課題に頭を抱える大学生が増えているというわけです。

スクリーンショット 2020-11-21 17.02.12.png

というわけで、「課題の多さに悩む大学生を何とかして助けたい」という思いが生まれ、その思いをもとにオリジナルアプリを作ることにしました。

そうは言っても、課題そのものを減らすことはできないので、できるだけ楽しく課題に取り組めるような仕組みを作るという方向性でアイデアを出していきました。

そして誕生したのが 『〆KiList』 です。

ezgif.com-video-to-gif.gif

Illustrated by Strories by Freepik

2. 「課題が多すぎる」という悩みを深掘る

1. はじめにで説明した通り、〆KiListを作成した目的は課題の多さに悩む大学生を助けるためでした。この目的を達成するためには、まず「課題が多すぎる」という悩みが表す意味をさらに深掘って考える必要がありました。

私は「課題が多すぎる」という悩みの根源は、以下の2点ではないかと考えました。

  • 課題に取り組むモチベーションがわかない

  • 課題のスケジュール管理が難しい

                        

よって、大学生の「課題が多すぎる」悩みを解決するためには、以下の2つの仕組みを作る必要があると考えました。

  • 課題に取り組むモチベーションが上がる仕組み

  • 課題のスケジュール管理をしやすくする仕組み

3. 機能一覧

〆KiListに付けた全ての機能は以下の18機能です。

       機能    Gem
   ログイン機能    devise
 ToDoリスト機能(CRUD)     ×
   カレンダー機能  FullCalendar 
   いいね機能(Ajax)     ×
   コメント機能(Ajax)     ×
   フォロー機能     ×
     宣言機能    
  わたしも機能(勝手に命名)     ×
  つぶやき機能(CRUD)     ×
    検索機能   ransack
  ページネーション機能   kaminari
グラフ機能(ドーナツチャート)    Chartkick
   レベル表示機能     ×
   ランキング機能     ×
   付箋機能(勝手に命名)     ×
  画像アップロード機能  CarrierWave 
   簡単ログイン機能     ×
    管理者機能       ×

この中でも、「課題が多すぎる」という悩みを解決するのに必要な2つの仕組みを実現するために付けた機能は、② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑫ ⑬ ⑭ ⑮の12機能です。

       機能    Gem
 ToDoリスト機能(CRUD)     ×
   カレンダー機能  FullCalendar 
   いいね機能(Ajax)     ×
   コメント機能(Ajax)     ×
   フォロー機能     ×
    宣言機能         ×
  わたしも機能(勝手に命名)     ×
  つぶやき機能(CRUD)     ×
グラフ機能(ドーナツチャート)    Chartkick
   レベル表示機能     ×
   ランキング機能     ×
   付箋機能(勝手に命名)     ×

これらの機能の概要と2つの仕組み実現のために工夫した点・思いについて、ここから1機能ずつ解説したいと思います!

4. 機能の解説

ToDoリスト機能

 概要 
ToDoリスト機能です。使い方は、とてもシンプルです。

①課題を登録
②課題がリスト化される
③完了ボタンを押すと完了済みに入る(完了済みから戻すのもできます!)

2.gif

ezgif.com-gif-maker (1).gif

工夫した点

①シンプル
まずはシンプルを心がけました。アプリ名にもなっているメイン部分ではありますが、色々機能があっても使いにくいと思ったのでここはシンプルに課題名と〆切日だけを表示させました。

②リマインド
「〆切をうっかり忘れていた」というようなことを防ぐために〆切1日前、〆切当日、〆切が過ぎている課題のリマインド機能を付けました。
また、〆切が過ぎている課題にはリストに赤い砂時計が表示されるようにしました。

スクリーンショット 2020-12-05 2.56.02.png

③実施日の登録
課題登録時に、〆切の何日前にするかという課題実施日も登録してもらうようにしました。これは、課題を「いつやるか」を考える習慣を付けることは、スケジュール管理が得意になる上で重要だと考えているためです。この仕組みを利用してその習慣を身に付けてもらえたらいいなという思いを込めて付けました。

カレンダー機能

 概要 
〆切を可視化できるカレンダーです。課題を登録すると、自動で〆切日のみ表示されるようになります。終わった課題は表示されません。それぞれの課題をクリックすると詳細画面に飛びます。

スクリーンショット 2020-11-21 23.45.37.png

工夫した点
①シンプル
リスト機能と同じくこちらもシンプルを心がけました。
〆切日のみに絞ってカレンダーに表示させることで、〆切日がひと目で分かるようにしました。

②〆切のカラー
通常は緑色のラベルで課題が表示されますが、〆切が過ぎている課題はでラベルが表示されます。パッと見て、「いますぐやるべき課題」が分かります。

いいね・コメント・フォロー

 概要 
SNSにはお馴染みの3機能です。

・いいね
ezgif.com-video-to-gif.gif

・コメント
ezgif.com-video-to-gif.gif

・フォロー
ezgif.com-video-to-gif.gif

工夫した点

これらの機能自体に特別な工夫があるわけではないですが、SNSやっている人なら誰もが一度は味わったことのある「いいねやコメントをもらう喜び」「誰かにフォローされる喜び」を〆KiListユーザーにも味わってもらい、課題に取り組む際のモチベーションにしてもらいたいなという思いを込めて実装しました。

宣言機能(オリジナル)

 概要  
課題を登録した際に、宣言ボタンが表示されます。
押すと、「いつ何の課題をするか」をみんなのつぶやき一覧に投稿できます。
ezgif.com-video-to-gif.gif

工夫した点
①手間いらず
無駄な行程を踏まずに済むように、文章を自分で入れなくても、ボタン1つですぐに宣言できるようにしました。

②やらざるを得ない環境の仕組み化
みんなの前で宣言して、やらざるを得ない状況を作る仕組みを仕掛けました。自分で管理するだけではついつい「明日でいっか」ってなってしまいますが、他の人に宣言しちゃうと何かやらなきゃいけない気がしてくると思います。その効果を利用しました。

わたしも機能(オリジナル)

 概要  
挙手のマークを押すと、他の人が宣言している課題を、自分の〆KiListにも登録できます。挙手のマークは、自分以外の他のユーザーの課題宣言の投稿にのみ表示されています。主に同じ大学、学部の人とかが使いやすい機能かと思います。
ezgif.com-video-to-gif.gif

工夫した点
①手間いらず
他の人の宣言を見て、「あ、この課題自分もやらなきゃいけなかった!」と思った時に、余計な行程を辿らず、すぐに課題が登録できるようにと思い、この機能を付けました。

②仲間意識・ライバル意識を活用
「友達がやるなら、自分も一緒に頑張ろう」という仲間意識「あいつに負けないように自分も頑張らないと」というライバル意識をモチベーションにする方は結構多いと思います。そういう人たちに、積極的に課題を登録してもらえるようにと思い、この仕組みを仕掛けました。

つぶやき機能

 概要  
つぶやきを投稿できる機能です。
スクリーンショット 2020-12-05 11.44.17.png

工夫した点
ToDoリスト×SNS
孤独な環境だと、どうしても課題が進められない人は多いと思います。そこで、つぶやき機能(SNS的な要素)を使って他の学生と積極的にコミュニケーションを取りながら、みんなで課題に取り組める仕組みを作りたいと思い、実装しました。

グラフ機能(ドーナツチャート)

 概要  
課題達成率(今まで登録した課題のうち、達成済みの課題数の割合)、〆切遵守率(達成した課題数のうち、〆切を守った課題数の割合)がドーナツチャートでグラフ化されます。

課題を完了すると、〆切達成率・〆切順守率が変わっていることが分かります。
ezgif.com-video-to-gif.gif

スクリーンショット 2020-12-05 11.54.29.png

工夫した点
①課題に取り組む姿勢を数値化・可視化
努力を数字やグラフで可視化させ、モチベーション維持に繋げてくれたらいいなと思い、実装しました。

②人に見られる環境の仕組み化
グラフはマイページに表示されています。そのページに飛んでくれば、自分の課題に取り組む姿勢が他の人の目に触れることになります。人に自分の努力値が見られている環境に置かれていることもまた頑張るモチベーションになるかなと思い、この機能を付けました。

レベル表示機能

 概要  
課題の完了数が増えていくにつれてレベルが上がっていきます。
「ビギナー」「中級者」などクラスも表示されます。
レベルが高ければ高いほど、課題をしっかりと完了させているという証明になります。
スクリーンショット 2020-12-05 12.28.21.png

工夫した点
①次のクラスを目指すワクワク感
ユーザーが「次はどんなクラスかな?」「私も〇〇クラス目指して頑張ろ!」と楽しめるようにして、頑張れるモチベーションにしてもらえたらなと思い、実装しました。
この辺のバリエーションはまだまだ増やす余地ありなので、さらに色々なクラスを用意して、ユーザーにワクワクしてもらえるような仕様にしていきたいと考えています。

②遊び心
真面目すぎるアプリは、少し使うとすぐに飽きてしまいます。なので、所々遊び心を加えて、ユーザーに楽しんでもらいながら長く使ってもらえるようにと思い、「何やコレ」と言うようなクラスを用意しました。例えば、Lv.1のクラスは「赤ちゃん」です。かわいいですね。育てたくなりますね
スクリーンショット 2020-12-05 12.36.12.png

ランキング機能

 概要  
レベルが上位3名になると、ランキングにユーザー名とレベルが載ります。
スクリーンショット 2020-12-06 16.20.25.png

工夫した点
ランキングに載ることへのモチベーション
ランキングに載ることもまた、一種のモチベーションになると思います。
「ランキングに名前を載せるために課題を頑張ろう!」と思ってもらえるようにこの機能を付けました。
ただし、今のところ見ての通りあまりにもデザインがシンプル過ぎて、名前が載っても「何だかな〜」と言う感じなので、もう少しモチベーション上がるような見栄えを目指したところです。

付箋機能

 概要  
登録した課題と〆切日が、付箋のような感じで表示されます。本日〆切、本日実施の課題もすぐに分かります。
ここから課題の詳細ページに飛ぶこともできます。
スクリーンショット 2020-12-06 16.43.53.png

工夫した点
アプリ使用中は〆切を意識
このアプリは、課題の〆切日を守るためのアプリなので、常に〆切を意識してもらう必要があります。通常であれば、〆KiListのページに行かないと〆切を見ることができないことになってしまいますが、この付箋機能をマイページとつぶやき一覧ページに載せることで、アプリを使っている最中は常に〆切を意識してもらえることになります。〆切のうっかり忘れの防止をさらに強化するために、この機能を実装しました。

番外編:〆KiListの色について

今回〆KiListを作成するにあたって、カラーを下記の通り選択しました。

  • メインカラー:ネイビーオレンジホワイト
  • サブカラー:グレーブルー(ボタンにカーソル置いた時)

基本的には、メインカラーを使うように気をつけました。
自分はデザイン的な知識は全くないので、色で統一感を出すことでそれなりにまとまりのある感じを出そうという発想になり、その結果使う色を3色に絞りました。

スクリーンショット 2020-12-06 17.59.26.png

ただし、全部がこの色だと面白味がないので、ボタンにカーソルをのせた時やちょっとしたデザインの部分に関しては、グレーやブルーなど、メインカラーに比較的馴染みが良いであろうカラーを使うようにしました。
(カレンダーは土曜日のイメージが青や水色、日曜日のイメージが赤やピンクなので例外です)

尚、一番のメインカラーはネイビーですが、これは青系の色の方が、「勉強」「課題」といった真面目な印象を与えやすいから選択しました。

そこにオレンジという暖色を加えたのは、〆KiListがSNS的な要素を持ち、「人との繋がり」「励まし合い」といった要素も含むからです。

ネイビー×オレンジという組み合わせが結構しっくりきたのでこれらの色をメインに使いました。

さいごに

長くなりましたが、以上です。

大学生の「課題が多すぎる」という悩みを解決するためには、

①課題に取り組むモチベーションが上がる仕組み 
②課題のスケジュール管理をしやすくする仕組み

この2つの仕組みが必要で、この仕組みを実現するために、今回解説した12機能を付けたというお話でした。
ここまで読んでいただいてありがとうございます。

予定

①この記事は、今のところ「思い」の部分が前面に出た記事になっておりますので、今後はそれぞれの機能についてどのように実装したかという技術的な部分も付け加えていけたらと思っています。

②今回は、機能という部分に着目しましたが、ポートフォリオ(このアプリ)の作成の全体的な解説記事は別で投稿します。それまでにAWSでのデプロイを頑張ります。

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

ローカル変数とインスタント変数の違い

現在、「Ruby on Rails 5 速習実践ガイド」を読みながら勉強をしているのですがローカル変数とインスタント変数についてあまり理解せずに進んでしまいました。

なので、きちんと理解するため記事にしてみました。

プログラミング初心者のため認識違いがあった場合などは是非ご指摘下さい。

ローカル変数とは

その場限りの一時的な変数です。メソッド内で定義したローカル変数はそのメソッドの中でしか使うことができず、他のメソッドからは使うことができません。

インスタント変数とは

オブジェクトの保持する変数です。オブジェクトのどのメソッドな内からも利用できます。

試したこと

今回、自分でMyClassを作ってみました。

class MyClass
  def method_1
    number = 100
  end

  def method_2
    number
  end
end

そしてこのクラス (MyClass) のオブジェクトを作って、method_1を呼び出してみます。

> object = MyClass.new
> object.method_1
=> 100

このメソッドにはnumberというローカル変数に100という数値のオブジェクトをいれています。
そのためメソッドを呼び出すと100という値が返ってきています。

それに続けて、method_2を呼び出してみます。

> object.method_2
Traceback (most recent call last):
...
NameError (undefined local variable or method `number' for #<MyClass:0x00007ffe439012580>)

「numberという名前のローカル変数やメソッドは知りません」というエラーが表示されてしまいました。

ここではmethod_1で定義したnumberというローカル変数がmethod_2でも生き残っていれば表示されるはずです。
エラーが返ってきてしまったということは、method_1で使ったnumberは使えないという状況になりました。

次にローカル変数ではなくインスタント変数を使ってみます。

class MyClass
  def method_1
    @number = 100
  end

  def method_2
    @number
  end
end

> object = MyClass.new
> object.method_1
=> 100
> object.method_2
=> 100

今度は、method_2でエラーが出ず、無事に100という値が返ってきました。
ここで同じインスタント変数を利用できていることがわかります。

まとめ

ローカル変数は1つのメソッドの中で一時的に使うデータを参照するために使います。
一方、インスタント変数は、特定のオブジェクトの内部で使いまわしたりできます。

参考本

・ 現場で使える Ruby on rails 5 速習実践ガイド

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

ローカル変数とインスタンス変数の違い

現在、「Ruby on Rails 5 速習実践ガイド」を読みながら勉強をしているのですがローカル変数とインスタンス変数についてあまり理解せずに進んでしまいました。

なので、きちんと理解するため記事にしてみました。

プログラミング初心者のため認識違いがあった場合などは是非ご指摘下さい。

ローカル変数とは

その場限りの一時的な変数です。メソッド内で定義したローカル変数はそのメソッドの中でしか使うことができず、他のメソッドからは使うことができません。

インスタンス変数とは

オブジェクトの保持する変数です。オブジェクトのどのメソッドな内からも利用できます。

試したこと

今回、自分でMyClassを作ってみました。

class MyClass
  def method_1
    number = 100
  end

  def method_2
    number
  end
end

そしてこのクラス (MyClass) のオブジェクトを作って、method_1を呼び出してみます。

> object = MyClass.new
> object.method_1
=> 100

このメソッドにはnumberというローカル変数に100という数値のオブジェクトをいれています。
そのためメソッドを呼び出すと100という値が返ってきています。

それに続けて、method_2を呼び出してみます。

> object.method_2
Traceback (most recent call last):
...
NameError (undefined local variable or method `number' for #<MyClass:0x00007ffe439012580>)

「numberという名前のローカル変数やメソッドは知りません」というエラーが表示されてしまいました。

ここではmethod_1で定義したnumberというローカル変数がmethod_2でも生き残っていれば表示されるはずです。
エラーが返ってきてしまったということは、method_1で使ったnumberは使えないという状況になりました。

次にローカル変数ではなくインスタンス変数を使ってみます。

class MyClass
  def method_1
    @number = 100
  end

  def method_2
    @number
  end
end

> object = MyClass.new
> object.method_1
=> 100
> object.method_2
=> 100

今度は、method_2でエラーが出ず、無事に100という値が返ってきました。
ここで同じインスタンス変数を利用できていることがわかります。

まとめ

ローカル変数は1つのメソッドの中で一時的に使うデータを参照するために使います。
一方、インスタンス数は、特定のオブジェクトの内部で使いまわしたりできます。

参考本

・ 現場で使える Ruby on rails 5 速習実践ガイド

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

ポートフォリオ作成記録 静的ページでの作成と自動テスト

generateで静的ページを作成

generateで静的ページ作成をしました。
また、コマンドの省略版の入力を知り、便利さを実感しました。
例:rails server = rails s、rails generate = rails g等

また、destroyですでにgenerate/migrate/で生成されたものを取り消しを行い、
関連するファイルに追記されている内容も消せるのは便利すぎ!

自動テスト!!!

現在の現場でもまだTDD(テスト駆動開発)が行われていないのが現状で、C#で一度私も勉強をした事があり、すごく興味がある分野です。
テスト記述と実行がすごく簡単に行えるのが、優しい。
ちなみに、流れが、まずはテスト(仕様通りに想定した状況で必ず動く)内容を記述して、一度実行して失敗させる(REDの状態)。
その後、そのテストコードを正常に動かすようにコードを記述して実行できる様にする(GREENの状態)。
さらに、動いたコードの処理記述で読みやすさを重視してのコードの書き直し(リファクター)の順で行ました。
私が働いている会社ではこの手段で開発を行うことを教えてもらってないので、今だに行っていないのが不思議です。
(馬鹿にする割には、毎回自動テストとテストケースの実行を手打ちのくせに(笑))

ルーティング

クライアント(今回の場合はHPにアクセスする人のPC)からの要求(今回の場合は他のページを移動する)時に、
サーバーは、要求に応じて(ページごとに割り当てられているURLの末尾)プログラムで処理したHTML等のファイルを送り出す時のコントールする機能です。
クライアントとサーバーはあくまで、役割名なので互いがその役割を担うことを忘れずに!
(恥ずかしながら、私は専用のPC等のコンピュータしかその任された役割しかできないと勘違いしてました=シンクライアント)

最後に

今回もあくまで、概要の内容でした。(まとめの内容もその内容で締め括られておりました。)
ただし、現在の私にとってはまだ点での知識であり、最初の頃に学んだ機会がありましたがその時より理解が深まったのが嬉しかったです。
あとは、個人的にはチュートリアルは難しいとか時間がかかるとかありますが最初からすんなり行くならこういった勉強は必要ありません。
また、学習後の理解を深める好意を行わずにただアプリを作りましただと業務で通じるのか不思議です。
このチュートリアルはあくまでもRailsの理解と使い方の基本とその関連知識を身に付けて欲しいとたった3章まで学習しただけでも感じる内容です。
私はこの学習で不明な点をメモしながらまずは1周して、復習の時間際に調べて内容の理解を他者に説明できる様に深めたいと思います。
また、ポートフォリオ作成時の意欲・開発速度・面接時に説明を受けた場合の対応などの能力向上の機会にしたいと思います。

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

【Rails6】Action mailerでメール送信までを解説してみる。(MailHogも使うよ)

はじめに

今回は、Action mailerによってアプリケーションからメールを送信する流れまでを解説していきます。

またAction mailerを最低限に絞って解説していくので、Railsの他の機能は解説しません?‍♂️

Action mailerでメール送信する

【1】MailHogの導入

MailHogを使うことで開発環境におけるメール送受信の確認をすることができます。

Railsではletter_openerというgemが有名ですがsprockets環境でないと導入できないのです。
つまり、sprockets環境出なかったり、RailsAPIモードの場合は使うことができません。(間違っている場合は、コメントしてください?‍♂️)

そこで、MailHogを採用します。MailHogは開発環境のDocker-composeに下記のように書くことで手軽に導入することができます!!

docker-compose.yml
mailhog:
  image: mailhog/mailhog:v1.0.0
  ports:
    - "8025:8025"

あとは、http://localhost:8025/でUI上でメールが正しく送られているか確認することができます。便利ですね!

【2】設定ファイルを編集

config/environments/development.rbで下記のコードを記述してください。action_mailerに必要な設定です。

とりあえず、開発環境だけしておきます。

config/environments/development.rb
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = { address: 'mailhog', port: 1025 }

【3】メーラーを生成

下記のコマンドでmailerを作成することができます。

rails g mailer UserMailer

mailerとはRailsのコントローラーとほぼ一緒だと考えてもいいかもしれません。

【4】メール送信処理を記述

app/mailers/user_mailer.rbにメールを送信する処理を書いていきます。

app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
  def new_registration_email(user)
    @user = user
    mail subject: '新規アカウント登録されました', to: @user.email
  end
end

今回は、仮に新規会員登録のタイミングでメールを送信することを想定しています。

【5】view以下にメール本文を書いていく。

app/views/user_mailer/new_registration_email.erbに実際に送られるメールの本文を記述していきます。

app/views/user_mailer/new_registration_email.erb
<%= @user.name %> 様

会員登録が完了しました。
URLはこちらです。
<%= user_url(@user) %>

【6】任意の箇所でメソッドを走らせる。

UserMailer.new_registration_email(@user).deliver

上記のように記述することで、メールを送信できるようになります。下記はUserがCreateされるタイミングでメールを送信しています。

app/models/user.rb
class User < ApplicationRecord
  # 略
  after_create :send_email_for_new_registration

  private

  def send_email_for_new_registration
    UserMailer.new_registration_email(self).deliver
  end
end

最後に

駆け足でしたが、以上です!

簡単に実装できてしまいましたね。すごい。。。

ではでは?

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

Neo4jをActiveRecord感覚で扱えるActiveGraphを触ってみた

こんにちは。@mshibuyaです。
グラフデータベースNeo4j向けのActiveModel準拠のOGM(Object Graph Mapping, ORMのグラフ版ですね)であるActiveGraphを触ってみる機会があったのでご紹介します。

なおこの記事はRails Advent Calendar 2020の6日目のエントリーです。

グラフデータベースとは

データ構造としてのグラフを扱うことに最適化されたデータベースシステムです。ノードとエッジから表現され、様々な物事同士の関連関係を効果的に扱うことができます。Amazon Neptuneとしてフルマネージドのグラフデータベースサービスも登場したりしていて、徐々に利用範囲を広げつつあるのではないでしょうか。

とはいえ、このへんの話はあんまり詳しくないので深くは語れないです。なんかグラフ理論ってかっこよさげだしよくない?程度のノリです…

ActiveGraphはグラフデータベースNeo4jをバックエンドとして利用します。もともとNeo4j.rbと呼ばれていたものが最近名前が変わったようですね。

触ってみる

Docker ComposeでNeo4jを立ち上げます。ActiveGraphが対応済みであるバージョン4.0を選択

version: '3'
services:
  neo4j:
    image: neo4j:4.0
    ports:
      - "7474:7474"
      - "7687:7687"
    volumes:
      - ./neo4j:/data

neo4j-ruby-driverに必要なseaboltをinstall

$ brew install michael-simons/homebrew-seabolt/seabolt

rails newする

$ rails new graph_app -T -O -m https://raw.githubusercontent.com/neo4jrb/activegraph/master/docs/activegraph.rb

config/neo4j.ymlを作成

development:
  url: bolt://localhost:7687

test:
  url: neo4j://localhost:7688

モデルを作成

app/model/person.rb

class Person
  include ActiveGraph::Node

  property :name
end

app/model/friendship.rb

class Friendship
  include ActiveGraph::Relationship

  from_class :Person
  to_class :Person

  property :since, type: DateTime
end

このへんで Neo4j::Driver::Exceptions::AuthenticationException (Permission denied) が出て困ったんですが、Neo4j側でパスワードを変更したら出なくなりました。とりあえず深追いはしません。。

rails consoleから遊んでみます

irb(main):001:0> john = Person.create name: 'john'
 CYPHER CREATE (n:`Person`) SET n = $props RETURN n | {:props=>{:uuid=>"ae128a36-4e0b-4879-9213-9d5ec0b0b726", :name=>"john"}}
 BOLT: 0ms
irb(main):002:0> paul = Person.create name: 'paul'
 CYPHER CREATE (n:`Person`) SET n = $props RETURN n | {:props=>{:uuid=>"5c8987da-de09-4673-b366-a002b491be65", :name=>"paul"}}
 BOLT: 0ms
irb(main):003:0> Friendship.create(from_node: john, to_node: paul, since: Time.now)
 BOLT: 0ms
 BOLT: 0ms
 CYPHER
  MATCH
    (from_node),
    (to_node)
  WHERE
    (ID(from_node) = $from_node_id) AND
    (ID(to_node) = $to_node_id)
  CREATE (from_node)-[rel:`FRIENDSHIP` $rel_create_props]->(to_node)
  SET rel.`since` = $setter_rel_since
  RETURN rel | {:from_node_id=>0, :to_node_id=>2, :setter_rel_since=>1607243457, :rel_create_props=>{}}
 BOLT: 0ms
=> #<Friendship since: Sun, 06 Dec 2020 08:30:57 +0000>
irb(main):004:0> people = 1.upto(100).map {|i| Person.create name: "person#{i}" }
...
irb(main):005:0> 300.times.each { Friendship.create from_node: people.sample, to_node: people.sample }
...
irb(main):006:0> Person.query_as(:p).where('size((p)-->()) > 5').count # 5人以上friendのいるPersonの数を取得
 CYPHER
  MATCH (p:`Person`)
  WHERE (size((p)-->()) > 5)
  RETURN count(*)
 BOLT: 0ms
=> 6

ちょっと凝ったクエリをしようとするとNeo4jのクエリ言語であるCypherの知識が求められはするんですが、なかなか面白いです。最短距離を求めるだとか、リコメンデーションに利用したりとか想像は膨らみます…

本当は最近RailsAdminに寄せられたNeo4j対応を試してみるところまで行きたかったのですが、時間がないので今日はここまでで。

よいRailsライフをお過ごしくださいー

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

Rspec 結合テストコードでのSelect要素の取得方法

はじめに

現在、転職活動のポートフォリオとして車のレビューサイトを作成しており、
そこで私自身が詰まった箇所の解決方法をアウトプットしていきたいと思います!

Rspecをつかった結合テストコード

今作成中の車のレビューサイト「Car-Review」にてユーザー登録機能やレビュー投稿機能、いいね機能など実装ができたので下記のように結合テストコードを書いていました。
一部抜粋

spec/system/reviews_spec.rb
require 'rails_helper'

RSpec.describe "レビュー投稿", type: :system do
  before do
    @user = FactoryBot.create(:user)
    @review = FactoryBot.build(:review)
  end

  context 'レビュー投稿できるとき' do
    it 'ログインしたユーザーは新規投稿できる' do
      # ログインする
      visit new_user_session_path
      fill_in 'user[email]', with: @user.email
      fill_in 'user[password]', with: @user.password
      find('input[name="commit"]').click
      expect(current_path).to eq root_path
      # 新規投稿ページへのリンクがあることを確認する
      expect(page).to have_content('新規投稿')
      # 投稿ページに移動する
      visit new_review_path
      # フォームに情報を入力する
      select @review.automaker.name, from: 'review[automaker_id]'
      fill_in 'review[model_of_car]', with: @review.model_of_car
      fill_in 'review[grade]', with: @review.grade
      select @review.era_name.name, from: 'review[era_name_id]'
      fill_in 'review[model_year]', with: @review.model_year
      select '3点', from: 'review[design_id]'
      select '3点', from: 'review[driving_performance_id]'
      select '3点', from: 'review[ride_comfort_id]'
      select '3点', from: 'review[lording_id]'
      select '3点', from: 'review[fuel_economy_id]'
      select '3点', from: 'review[price_id]'
      fill_in 'review[good_point]', with: @review.good_point
      fill_in 'review[bad_point]', with: @review.bad_point
      # 送信するとReviewモデルのカウントが1上がることを確認する
      expect{
        find('input[name="commit"]').click
      }.to change { Review.count }.by(1)
      # トップページに遷移していることを確認する
      expect(current_path).to eq root_path
      # トップページには先ほど投稿した内容のレビューが存在することを確認する(メーカー、車種、投稿者)
      expect(page).to have_content(@review.automaker.name)
      expect(page).to have_content(@review.model_of_car)
      expect(page).to have_content(@user.nickname)
    end

こんな感じで次にReviewモデルの結合テストコードを書いていたら…

選択済みSelect要素の取得

今回の本題で、レビュー編集の結合テストコードを書こうとしたのですが、編集の画面に遷移してそこではすでに投稿済みの内容がフォームに入っていることを確認しなければなりませんでした。

views/reveiws/edit.html.erb
<div class="form-group">
  <label class="control-label">メーカー</label>
  <%= f.collection_select(:automaker_id, Automaker.all, :id, :name, {selected: [@review.automaker_id]}, class:"form-control") %>
<div>
spec/system/reviews_spec.rb
expect(
  find('要素').value
).to eq "#{@review1.automaker_id}"

*viewファイルはActive HashとSelectタグを使いドロップダウンボックスを作ってます

上記のfindメソッドで要素を取得しそのvalue(=id)と、既に投稿してあるレビュー1のautomaker_idが一致すればそのページに投稿した内容があることが確認できます。

この'要素'の取得で躓いてしまいました。

解決方法

色々調べた結果下記の方法で解決することができました!

スクリーンショット 2020-12-06 18.27.13.png

spec/system/reviews_spec.rb
expect(
  find('#review_automaker_id').value
).to eq "#{@review1.automaker_id}"

スクショはデベロッパーツールにて該当箇所を切り取ったものです。
すごく簡単な事だったのですが、'#'をつければidで要素が取得できてしまうみたいです!!
恐らく基本的なやり方だとは思いますが、とても勉強になりました…!

まだまだ勉強を初めて2,3ヶ月のため間違ったことを書いていましたら
コメントにて教えていただけるととても嬉しいです。

次回はいいね機能の実装なんかの記事がかければと思っています!

参考文献

https://stackoverrun.com/ja/q/3065712

こちらの質問の回答を参考にさせていただきました。
ありがとうございました。

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

【Rails】PrimaryキーをUUIDにしてみる。~MySQL~

はじめに

今回はgem(ライブラリ)等を使わずに、PrimaryキーをUUIDにする方法(MySQLの場合)を解説していこうと思います!

また、この記事ではUserモデルを作成する流れで、PrimaryキーにUUIDを設定する流れを実践していきます。

 UserモデルのPrimaryキーをUUIDにする

 【1】Userモデルを作成

ともかく、モデルを作成しましょう。今回は「試し」なので、カラムは何も入れていません。

rails g model user

 【2】マイグレーションファイルを記述する。

create_table "users", id: false, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4" do |t|
  t.string   "id", limit: 36, null: false, primary_key: true

  t.datetime "created_at",   null: false
  t.datetime "updated_at",   null: false
end

ポイントは二つです。

 デフォルトのidfalseにする。

create_table "users", id: false,の部分ですね。ここをfalseにしています。

 uuid用のカラムを追加

t.string "id", limit: 36, null: false, primary_key: trueの部分ですね。

primary_key: trueのオプションをつけているのがポイントです。こうすることで、このカラムがprimary keyにすることができます。

 【3】moduleからuuidを作成

この部分に関しましては、この記事から引用させていただきました?‍♂️

app/models/concerns/id_generator.rbuuid生成用のモジュールを作成してください。

app/models/concerns/id_generator.rb
module IdGenerator
  def self.included(klass)
    klass.before_create :fill_id
  end

  def fill_id
    self.id = loop do
      uuid = SecureRandom.uuid
      break uuid unless self.class.exists?(id: uuid)
    end
  end
end

順番に解説していきます。

 self.included(klass)

def self.included(klass)
  klass.before_create :fill_id
end

このモジュールがインクルードされたタイミングで対象のクラスを引数にしてこのメソッドが呼び出されます

引用元:公式

つまり、このモジュールがインクルードされたタイミングで該当モデルでbefore_create :fill_idが呼び出されます。

 fill_id

def fill_id
  self.id = loop do
    uuid = SecureRandom.uuid
    break uuid unless self.class.exists?(id: uuid)
  end
end

簡単にいうと、該当モデルのidに対して、uuidを重複しないように設定します。

 【4】Userモデルでmoduleをincludeする。

app/models/user.rbで先ほどのmoduleincludeしてください。

app/models/user.rb
class User < ApplicationRecord
  include IdGenerator
end

こうすることにより、before_createのタイミングでfill_idにより、uuidを設定することができます。

 最後に

以上です。これでPrimaryキーをUUIDとして設定することができると思います。

とはいえ、UUIDにはメリデリがあるので考慮してから採用するようにしてください。

ではでは✌️

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

Rails エスケープ

Railsのエスケープとかについて、知識が曖昧だったので調べてみる
また後日、きちんと調べる

XSS(クロスサイトスクリプティング)攻撃

まず、エスケープを知る前にこの攻撃方法を知っとかないといけない

XSS(クロスサイトスクリプティング:Cross Site Scripting)とは、
ユーザーに表示するコンテンツに悪意のあるスクリプト(主にJS)を
仕掛け、そのコンテンツを表示したユーザーにスクリプトを実行させることで
任意の操作をさせる攻撃のこと

Webアプリにおいて、動的にhtmlを出力する時、
そのデータをエスケープしていないと
悪意のあるhtmlやjavascriptが紛れ込む

JSは、ブラウザ上で動作し
Cookieなども更新することができたりするのでセキュリティには気をつける

例)クリックするとセッションIDが盗まれてしまう
任意のメッセージや処理が行われる など

どう対策するか

ユーザーの入力した文字を出力する際に
自動的にHTMLをエスケープする必要がある

デフォルトでエスケープさせる

エスケープとは

スクリプトを実行する対象となる文字列を
無害な文字に置き換えること

& → &amp;
" → &quot;
< → &li;
> → &gt

エスケープしたくないとき

この自動的にHTMLをエスケープしてくれる仕組みは、便利だが
どんなときも文字列をエスケープしたいかというとそうではない

このようなときは、以下のメソッドを使用する

String#html_safe

html_safeメソッドそれ自体は何らエスケープを行なっていないという
安全であるとマーキングしているに過ぎないので注意する

s = "".html_safe
s.html_safe? # => true
s = "<script>...</script>".html_safe
s.html_safe? # => true
s            # => "<script>...</script>"

あくまで、「s」にはまだスクリプトが埋め込まれている状態

特定の文字列に対してhtml_safeメソッドを呼び出す際には、
その文字列が本当に安全であることを確認する義務がある

"<em>#{text}</em>".html_safe
#=> ヘルパーを使う
content_tag :em, text
  • 安全でない文字列をエスケープ無しで出力しない
  • ヘルパーでタグを出力する

sanitizeメソッド

ある程度タグをそのまま出したいものの、危険なタグは
出力しないようにしたいという場合に利用する

出力できるタグをホワイトリスト形式で制限する

sanitizeはフィルタした結果のHTMLに対して
「String#html_safe」を実行して返すので
さらに、「raw」や「String#html_safe」を使う必要がない

<% @comment = "<script>alert('Hello');<script>
<%= sanitize @comment %>

#生成されるHTML
<div>alert('Hello');</div>

参考記事

https://railsguides.jp/active_support_core_extensions.html
https://qiita.com/kamohicokamo/items/571c58f2d6738a7dfe6a
https://techracho.bpsinc.jp/hachi8833/2016_08_31/25326
https://qiita.com/sutetotanuki/items/5eda6bbb5532dd64529a#%E3%82%AF%E3%83%AD%E3%82%B9%E3%82%B5%E3%82%A4%E3%83%88%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0xss
https://railsguides.jp/security.html
https://www.websec-room.com/2013/03/14/567
https://blog.tamesuu.com/2019/10/14/459/
https://yuruli.info/rails5-using-escape-methods/

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

【Rails Google Map】ストリートビュー(Street View)を静的に表示させるには

【Rails Google Map】ストリートビュー(Street View)を静的に表示させるには

この記事でできるようになること

以下の画像のように、自分のアプリ内に場所やお店のストリートビューを静的に表示できるようになります
image.png

ステップ

・GCPでStreet View static APIを追加
・認証用コードをマップの表示をしているViewに記述
・画像表示のコードを記述

GCPでStreet View static APIを追加

GCPのコンソールに移動して頂いて、
APIとサービス>認証情報からご自分のAPI Keyをご選択ください!
image.png
image.png

認証用コードをマップの表示をしているViewに記述

Google Mapのストリートビューは以下のリンクにて取得できます

https://maps.googleapis.com/maps/api/streetview?size=640x480(←任意のサイズでOK)&heading=180&fov=120&location=緯度の値,経度の値&sensor=true&key=ご自身のAPIKey

headingのパラメーターは、方向を決定します。0~360が指定可能。0は北、90は東、180は南、270は西を指します。
fovのパラメーターは、水平方向の視野を決定します。0~120が指定可能。120を指定すると広い範囲の画像が取得できます。
pitchのパラメーターは、カメラ角度(上向き下向き)を決定します。90~-90が指定可能。90は上向き、-90は下向きです。
引用元:https://maps.multisoup.co.jp/blog/1773/

画像表示のコードを記述

Railsで導入する例としては、
addressカラムに住所の投稿を格納しているとき、

index.html.erb
      <% @places.each do |place| %>
        <% results=Geocoder.search(place.address) %>
        <% if results.present? %>
          <% @latlng=results.first.coordinates %>
            <%= image_tag "https://maps.googleapis.com/maps/api/streetview?size=640x480&heading=180&fov=120&location=#{@latlng[0]},#{@latlng[1]}&sensor=true&key=ご自身のAPI Key" %>'

のようなコードで実現できますね
GeocoderのGemの導入はしておいてくださいね?‍♂️

うまくいかないとか、わからないなどあればいつでも
Twitter
などで、ご連絡いただければ幸いです?‍♂️

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

【Ruby】様々な条件分岐について①(ifの使い方)

条件分岐について

条件分岐とは、自分が設定した条件について、値が当てはまっているか(真)そうでないか(偽)を判断し、その結果に応じた出力を呼び出すことができる方法のことです。
使用することが多いので、Rubyの勉強を始めたばかりの方はぜひ読んでみてくださいね!

【内容】
・基本となるifの使い方
・ifを一行でまとめる方法
・条件が複数ある時のifの使い方

【読んで欲しい人】
・条件分岐(if)をマスターしたい方
・Ruby初学者の方

ifの使い方

ifを用いた条件式について解説します。ある特定の条件があり、その条件に当てはまる場合と当てはまらない場合で出力を変更したいときに使用します。

基本となるifの使い方

条件式が1つの場合
if 条件式
  条件式に該当する(真)ときの出力
else(条件式以外の場合)
  条件式に該当しない(偽)であるときの出力
end

実際に例文でも見てみましょう。

例文1
age = 21
if age >= 20
  puts "私は成人です。"
else
  puts "私は未成年です。"
end
例文1:出力結果
私は成人です。

このように、age = 21と定義されているので、ifの条件式に対しては(真)となり、「私は成人です」という値が返ってきます。もしage = 18など、ageの値が20未満であれば、条件式に対して(偽)となるので、「私は未成年です」という値が返ってくることになります。

ifを一行でまとめる方法

実はこのif文をもう少しスマートに記載することができます。

例文2
age = 12
puts age >= 20 ?  "私は成人です。" : "私は未成年です。"
例文2:出力結果
私は未成年です。

このように、三項演算子という手法を使えば、一行でコードを記載することもできます。
条件式? (真)の値 : (偽)の値
と記載することで、スマートに一行でまとめることができます。条件式の後に「?」を入れるのを忘れないようにしてくださいね。慣れてきたらこのように式を簡単にしてコードを書いてみましょう!

条件が複数ある時のifの使い方

では、複数の条件式を使用したい場合はどのようにコードを書けば良いのでしょうか?
基本は下記のような書き方になります。

条件式が複数ある場合
if 条件式①
  条件式①に該当する(真)ときの出力
elsif 条件式②
  条件式②に該当する(真)ときの出力
elsif 条件式③
  条件式③に該当する(真)ときの出力
else
  どの条件式にも該当しない(偽)ときの出力
end

実際に例文でも見てみましょう。

例文3
hobby = "basketball"
if hobby == "baseball"
  puts "私は野球が趣味です。"
elsif hobby == "soccer"
  puts "私はサッカーが趣味です。"
elsif hobby == "basketball"
  puts "私はバスケットボールが趣味です。"
else
  puts "私は無趣味です。"
end
例文3:出力結果
私はバスケットボールが趣味です。

このように、例文2では、hobby = "basketball"と定義されているので、3つ目の条件式hobby == "basketball"に当てはまることがわかります。複数の条件式が必要な場合は、上記のようにelsifで条件式を追加しましょう!くれぐれもelseifと書かないように注意してくださいね。

今回はifの使い方について解説しました。本当は他の条件分岐についても書こうと思ったのですが、あまりにも内容が長くなってしまい、必要な情報を見落としてしまう可能性があるので、別の記事で解説しようと思います!
条件分岐は使用頻度が多いので、ぜひマスターしましょう!

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

【Rails】マイグレーション時にコメントを追加する

マイグレーション時にコメントを追加する方法

Rails 5からこの機能が標準で装備されたそうです。
それ以前ではgemを利用していたそうです。
追加したコメントはデータベース側に保存されます。

コメントの付け方

マイグレーションファイルを生成されたら、
以下のような書式でコメントをマイグレーションファイルに追加します。

class CreateProducts < ActiveRecord::Migration[6.0]
  def change
    create_table :products do |t|
      t.string :name,                      comment: '雑誌名'
      t.integer :z_code, null: false,      comment: '雑誌コード'
      t.integer :num,    null: false,      comment: '取置冊数'
      t.string :release, null: false,      comment: '発売日'
      t.references :customer, null: false, foreign_key: true
      t.timestamps
    end
  end
end

その後、rails db:migrateで完了です!
Sequel Proの「構造」から確認できます。

コメントをつける意味

カラムにコメントをつける機能は「定義」を記録するって事が一番だと思います。
実際、6個程度のモデルしか作っていないのですが、
「name」カラム5つ「date」カラム3つも使っているのですよね・・・。
これからさらに追加で機能をつけていくとしたら、自身の備忘録としても意味がある機能だと思います。
ちなみに、コメントはあくまでメモとして残すものなので、
テーブルの動作的には何も影響はないそうです!

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

https://techracho.bpsinc.jp/hachi8833/2017_02_23/36083
ありがとうございます!!

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

【Rails】データが更新できない時は、バリデーションを確認

1. はじめに

アプリを作成している際に、Userテーブルに追加したカラムのデータが更新できずに困りました。
しかも、エラー文が出ないので何が原因なのかがなかなか分からずあたふたしていました。
最終的には原因を見つけられたのですが、解決に至るまでに思いの外、多くの時間を費やしてしまいました。
同じような現象で、時間を費やしてしまう人が少しでも減るように、ここに備忘録を残します。

2. きっかけ

そもそもエラー文が出ていないのに、なぜデータが更新されていないことに気づいたかというと、
更新されたはずのデータを元に検索機能を実装しようとしたときに、
登録したはずのデータで検索結果が返ってくるはずが、なぜかデフォルト値で返ってきたので、
「あれ?おかしいな」と思ったのが始まりでした。

rails cでテーブルの中身を確認したらやっぱり更新されていない...。
コンソールを見ると、データが更新される段階でRollbackされていました。

コンソール
  ↳ app/controllers/users_controller.rb:11
   (0.2ms)  ROLLBACK

3. 原因

結論から言うと、パスワードにかけていたバリデーションが原因でした。
ユーザーのデータを更新する際に、パスワードの入力が必要である設定になっていたのですが、
パスワードなしに、@user.updateをしようとしていたので、結果的にデータが更新されなかったようです。

app/
def show
  @user.update (
    marriage: @post.marriage,
    childcare: @post.childcare,
   )
end

と言うことで、バリデーションの設定を変更します。
ユーザー情報更新の場合、パスワードのバリデーションを外すように設定するのは、

user.rb(変更前)
validates :password, format: { with: password_format }, length: { in: 8..32 }

ここにon: :createを追加します。
こうすることでユーザー情報を登録する際のみにパスワードのバリデーションがかかります。

user.rb(変更後)
validates :password, format: { with: password_format }, length: { in: 8..32 }, on: :create

ユーザー情報更新の際に、パスワードのバリデーションがかからなくなったので、無事データが登録されるようになりました。

4. 最後に

原因は意外と単純でした。自分でバリデーションをかけておきながら忘れる始末。
灯台下暗しってやつですね...。今後は気をつけようと反省した次第です。

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

Ruby attr_accessorってなんぞぉ??

attr_accessorっなんすか?

rails チュートリアルのsessionあたり?トークン発行してのあたりで少し詰まったので

attr_accessorって何ぞってなったから調べたことをここに残しておこうと思う。

initialize クラスインスタンス生成 俗に言うnewされた際に1度だけ実行されるメソッド
Javaで言うコンストラクタと同じ意味っすね

sample.rb
 def initialize(name)

    # インスタンス変数@usernameに引数を代入
    @name = name
  end

本題

ゲッターとセッターを同時に定義してくれるメソッドです。

test.rb
class User
  def initialize(name)
    @name = name
  end
end

user  = User.new('Alice')
user.name


# => 当然エラーですよねメソッド定義してないっすもいんね・・・・

#def name
#
#end

test2.rb
class User
  def initialize(name)
    @name = name
  end

  def name # ゲッターメソッド
    @name
  end

  def name=(name) # セッターメソッド
    @name = name
  end

end


user = User.new('Alice')

user.name # => Alice

getter setter

getter,setterって言葉耳にしたことあるかもしれないですが
railsで書くとこんな感じです。
getter : attr_reader :name
setter : attr_writer :name

test3.rb
class User
  attr_reader :name # @name ゲッターメソッド
  attr_writer :name # @name セッターメソッド

  def initialize(name)
    @name = name
  end
end

user = User.new('Alice')

user.name # => Alice

実は更に短くなるんすよね・・・・

attr_accessor

test4.rb
class User
  attr_accessor :name

  def initialize(name)
    @name = name
  end
end

user = User.new('Alice')

user.name # => Alice

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

[Rails] コントローラー作成方法

コントローラーの役割は「受け取ったリクエストを、モデル・ビューと連携しながらレスポンスとして返す」です。

作成

rails g controller コントローラー名 

rails g(generate)コマンドで、コントローラーと付随するファイルを一度に生成します。
命名規則は複数形を使用するです。
例えば、商品の情報を処理する場合はproductsと書きます。

アクションを定義する

コントローラーは、リクエストに対応する処理を記述する場所です。実際に処理を用意しましょう。

7つのアクション

アクション名     役割

index         一覧表示ページを表示するリクエストに対応して動く
new         新規投稿ページを表示するリクエストに対応して動く
create         データの投稿を行うリクエストに対応して動く
show         個別詳細ページを表示するリクエストに対応して動く
edit         投稿編集ページを表示するリクエストに対応して動く
update         データの編集を行うリクエストに対応して動く
destroy         データの削除を行うリクエストに対応して動く

アクションとは、コントローラー内における処理のカテゴリーのことです。
コントローラーに、インスタンスメソッドとして定義します。

インスタンスメソッドは下記のように書きます。

products_controller.rb
class ProductsController < ApplicationController

  def index      # indexアクションを定義した
  end

end

削除

作成したファイル、もしくはコントローラー丸ごとを削除したい場合は下記のコマンドを実行します。

rails d ファイルの種類 削除するファイル名

rails d controller コントローラー名

rails d(destroy)コマンドは、rails gで作成したファイル一式を全て削除するコマンドです。

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

MySQLが起動しない(Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2))

開発環境

  • Ruby 2.5.8
  • Rails 5.2.1
  • MySQL 8.0.22

新規開発をしようと「rails db:create」をした時のこと・・・

ポートフォリオの大方の設計が出来上がってきたので、アプリの大枠だけでも作成しようとrails newをして新規アプリを作成し、rails db:createでDBを作成しようとしたところ、エラーで止まった。

rails db:create

Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
Couldn't create 'myPF_development' database. Please check your configuration.
rails aborted!
Mysql2::Error::ConnectionError: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

1週間ほど前に、実際の開発工程に入ってから躓くのは嫌だと思い、同じバージョンのRuby,Rails,MySQLで確りとテスト開発して確認したのになぜなのか…


1週間前は動いたmysql -u root -pを打っても、

mysql -u root -p

Enter password:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

となるばかりでまるで反応はなく…。またか…先週MySQL周りの設定で2日潰れたというのにまたなのか…MySQL君…、といった気持ちで調べてみるとやはりこの状況になる方は多いようで様々な記事が見つかりました。
その中でも、今回解決に導いてくれた記事を以下に貼っておきます。この記事のお陰で無事MySQLが動いてくれました。とても助かりました。

■ 参考にした記事
mysqlが起動できない(Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2))

解決はしましたが、今後もちょくちょくMySQL周りのエラーは起きそうな気がするので、Qiita記事を書く練習も兼ねてまとめておきます。上の記事と殆ど同内容にはなってしまいますがご容赦下さい。

mysql.sockファイルを作成する

エラー文にも書いてあるとおり、mysql.sockというファイルを通してローカルのMySQLサーバーに接続しているらしいのですが、そのmysql.sockファイルがないと言われています。
そして厄介なことに、このファイルがなんらかの原因で消えることがあるらしいと。なので、以下のコマンドを通してmysql.sockファイルを作成します。

sudo touch /tmp/mysql.sock

MySQLの再起動をする

mysql.sockファイルを作成したら、MySQLを起動し直します。

sudo mysql.server restart

Starting MySQL
... SUCCESS!

やった!

再度rails db:createしてみる

rails db:create

Created database 'myPF_development'
Created database 'myPF_test'

いけた!よかった!

おわりに

これからもMySQL関連を触る時はお祈りしながらコマンドを打つことになりそうです…笑
先人のQiita記事に大感謝。



おまけ(個人的メモ)
MySQLの起動:mysql.server start
MySQLへの接続:mysql -u root -p

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

LaravelでRailsみたいなデバックがしたい。(スクール卒業生向け)

概要

巷にあふれる某スクール卒業生。
彼らがスクールで学ぶのはRuby on Railsなのだが他人との差別化を図る上でLaravelを用いてポートフォリオを作成する方々を散見する。

彼らがスクールで学んだ、デバック方法は「binding.pry」ほぼ一択。

Laraveでよく見かけるデバック方法は,var_dump(); や dd(); でちょっとモヤモヤしてる方向けの記事になります。

結論

「binding.pry」みたいなことはLaravelでも出来る!!

eval(\Psy\sh());

処理を止めたいところに「binding.pry」のように書いて、ターミナルで確認するだけです。

恐らく、この説明でスクール卒業生は使いこなせると思います。
「大金払ってRuby on Railsを学び、実務で使うのはLaravelなんですか?」
という意見もあると思うのですが、個人的には自分が卒業生でlaravelエンジニアというのもあり応援したい気持ちです。

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

duplicate key value violates unique constraint "XXXXXX"の解決方法

ruby "2.6.4
rails", "~> 6.0.0"
postgressql

bin/rails db:drop
bin/rails db:create
bin/rails db:migrate
bin/rails db:seed

あとは
ファイル名、英語のスペルが間違えていないか確認

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

Railsで検索機能を導入してみた

はじめに

RailsでWebサービスを作っていく際、データベース内を検索する機能をつくるのに一工夫が必要でした。
そこで、どのようにして検索機能を搭載したかを記していきます。

環境

MacOS Catalina 10.15.7
Rails 5.2.4.4

手順

ヘッダー部分に検索機能のバーを搭載していきます。

header.html.erb
<div class="search-menu">
 <%= form_with url: "/search", method: "get", local: true do |form| %>
  <%= form.search_field :keyword, placeholder: "作品・ユーザーを検索", value: @keyword, size: "30" %>
  <button id="search-btn" type="submit"><i class="fa fa-search"></i></button>
 <% end %>
</div>

スクリーンショット 2020-12-06 8.32.27.png

上記のような検索窓が出来上がります。
「作品・ユーザーを検索」の文字列は好きなように変えましょう。
これで、大枠の部分は完成。
次は、中身の部分について解説していきます。

search_controllerを作成し、以下のように記述します。

search_controller.rb
class SearchController < ApplicationController
  only: %i[show]

  def show
    @keyword = params[:keyword] || ''
    @keyword == '' ? (@digest = '全件の検索結果') : (@digest = "「#{@keyword}」の検索結果")
    @type = params[:type] || 'item'

    @items = Item.search(@keyword)
    @users = User.search(@keyword).where(admin: false)

    return (@results = @items) if @type == 'item'
    return (@results = @users) if @type == 'user'
  end
end

合わせて、検索結果の画面を作成していきます。

show.html.erb
<div class="container">
  <div class="search-digest">
    <%= "#{@digest}:#{@results.count}件" %>
    <% if @keyword != "" %>
      <h6 class="search-no-option"><%= link_to "全件検索を行う", "/search" %></h6>
    <% end %>
  </div>

  <ul class="user-tabs">
    <li class="<%= @type %>-" id="item"><%= link_to "作品(#{@items.count})", "/search?type=item&keyword=#{@keyword}", remote: true %></li>
    <li class="<%= @type %>-" id="user"><%= link_to "ユーザー(#{@users.count})", "/search?type=user&keyword=#{@keyword}", remote: true %></li>
  </ul>

  <div class="search-result">
    <%= render partial: "search/#{@type}", collection: @results %>
  </div>
</div>
item.html.erb
<div class="search-index-item">
  <div class="search-show-item">
    <%= link_to "/items/#{item.id}" do %>
      <%= image_tag item.image.url, alt: "作品の画像" %>
    <% end %>
  </div>

  <div class="search-item-wrapper">
    <div class="search-item-title">
      <%= link_to item.title, "/items/#{item.id}" %>
    </div>

    <div class="search-item-description">
      <%= item.story %>
    </div>

    <%= render "shared/evaluation", item: item, division: false %>
  </div>
</div>
user.html.erb
<div class="search-index-item">
  <div class="search-show-item">
    <div class="search-show-userimage">
      <%= link_to "/users/#{user.id}", alt: "ユーザーの画像" do %>
        <%= image_tag user.image.url %>
      <% end %>
    </div>
  </div>

  <div class="search-item-wrapper search-user">
    <div class="search-item-title">
      <%= link_to(user.name, "/users/#{user.id}") %>
    </div>

    <div class="search-item-description">
    </div>
  </div>
</div>

スクリーンショット 2020-12-06 8.50.36.png

このような検索結果のタブが出来上がります。
(別途CSSを適用しています。)

気をつけること

対象となるデータベースはそれぞれ違うと思いますので、適宜変更してください。

おわりに

Railsで検索結果を取得するための方法に関する記事が少なかったので、作成してみました。
検索機能をつけると、Webサービスとして骨格が出来上がってきた感じがするので、オススメです。

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

Docker開発環境でdocker-compose run web bundle exec erb2slim app/views/layouts/ --deletを実行したらエラーが出た

Docker開発環境で構築したアプリにSlimを導入したのでRails newした時にできた.erbファイルをSlimに変更しようと思い、docker-compose run web bundle exec erb2slim app/views/layouts/ --deletを実行したところ下記のエラーがでた

bundler: command not found: erb2slim Install missing gem executables with `bundle install`

何をわけわからんこと言ってんねん!いれたやろがい!!!ってキレそうになりながら冷静になってみるとDockerのビルド?をしていないことに気づいたので下記を実行

docker-compose up --build
無事にDockerが起動したらDockerをもう一度止めて、
docker-compose run web bundle exec erb2slim app/views/layouts/ --deletを実行!!

そしたら無事にerbファイルがSlimに置き換わっていた!!やったぜ!!!

Dockerで開発環境を作ってるので、Dockerにしっかり更新したよ〜!っていう旨を伝えなくちゃいけないっぽいわね。勉強不足であってるかわからんけど、そんな感じでやったらとりあえずできたのでヨシ!ということでひとつ

おわり!!!!!!

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