rails 技術ブログ

rails 技術ブログ

勉強したことをアウトプットしていきます

【CSS】CSS設計BEMについて

BEMとは?
  • Block(かたまり)
  • Element(要素)
  • Modifier(修飾) この頭文字をとったCSS設計の一つ

Block

ヘッダー、メイン、フッターなどのかたまりをBlockといい、BlockはBlockを含めることができる
例えばコメントブロックがあったとして、BEMで定義するとこのようになる

<div class="comment"> <!-- Block -->
  <input class="comment__form"> <!-- Element -->
  <input class="comment__btn"> <!-- Element -->
</div>


Element

Blockを構成する要素
ElementはBlockに属しているので、必ずBlock__(アンダースコア2つ)Element=>comment__formこのような書き方になる

Modifier

既存のBlockやElementの一部の見た目のみを変えたい時にModifierを使用する
Modifierを使用するときは--(ハイフン2つ)で表現する

<div class="comment"> <!-- Block -->
  <input class="comment__form"> <!-- Element -->
  <input class="comment__btn"> <!-- Element -->
</div>

<!-- 基本スタイルは同じだが、色をブルーにしたい -->
<div class="comment comment--blue"> <!-- Modifier -->
  <input class="comment__form"> <!-- Element -->
  <input class="comment__btn"> <!-- Element -->
</div>



◆参考にしたサイト・書籍

一番詳しいCSS設計規則BEMのマニュアル - Qiita

【HTML5・CSS3】CSS設計のBEMを1から理解してマスターしよ | Pikawaka - ピカ1わかりやすいプログラミング用語サイト

www.amazon.co.jp

【CSS】詳細度について

詳細度(高い順)
!important
インライン記法(style属性)
IDセレクタ
クラスセレクタ・属性セレクタ・擬似クラス
要素セレクタ・擬似要素
ユニバーサルセレクタ
!importantの使い方

プロパティの値の後ろに半角スペースを空けて!importantと記述する

.title {
  color: red !important;
}

※基本的には!importantの使用は避ける。
(どの宣言も上書きしてしまうため、!importantを多用してしまうとメンテナンスが難しくなる)

使用を想定する場面:
外部のCSS (ブートストラップなど) を上書きする場合など

インライン記法の使い方

HTMLのstyle属性で指定する

<div style="color: red;">Hello World</div>

!importantと同じ理由で、基本的には使用せずにスタイルを適用できないかを考える


IDセレクタ
#title {
  color: red;
}

IDはページの中で一度のみ使うことができる。
(同一ページ内の違う要素に同じIDを指定することはできない)

CSSセレクタとしては最も高い詳細度になるため、よほどの理由がない限りIDセレクタでスタイルを当てるのはNG


クラスセレクタ、属性セレクタ、擬似クラス
// クラスセレクタ
.title {
  color: red;
}

// 属性セレクタ(↓class属性を持っているpタグにのみ適用される)
p[class] {
  color: red;
}

// 擬似クラス(:hoverのこと。aタグにカーソルが当たっているときに適用される)
a:hover{
  color: red;
}

クラス属性はIDとは異なり、同一ページで何度でも使うことができる

要素セレクタ
p {
 color: red;
}


クラスセレクタよりも詳細度は低くなる。
HTMLの構造へ依存するため(例えば、pタグをh1に変更したらcssの表記も変えなくてはならない)、基本的にはあまり使わない

<p>Hello world</p>
<!-- このpタグをdivに変えたらcssも変更する必要がある --><h1>Hello world</h1>
p {
 color: red;
}h1 {
   color: red;
}


クラス指定していれば変更する必要がない

<p class="title">Hello world</p><h1 class="title">Hello world</h1>
.title {
 color: red;
}



◆参考にしたサイト・書籍

詳細度 - CSS: カスケーディングスタイルシート | MDN

www.amazon.co.jp

【javascript】continue,breakで処理をスキップ、終了させる

continueを使うとその条件に当てはまる時は処理がスキップされる。

for(let i = 1; i <= 10; i++){
  if(i % 3 === 0) {
    continue;
  }
  console.log(i);
}

Image from Gyazo

breakを使うと条件に当てはまると処理が実行されず、その後の処理も実行されない。

for(let i = 1; i <= 10; i++){
  if(i % 3 === 0) {
    break;
  }
  console.log(i);
}

Image from Gyazo

【SQL】コマンド一覧

コマンド 意味
SELECT どのカラムのデータを取得するかを選ぶ
(複数データを取得したい場合はカンマで区切る)
SELECT name,age
(全てが対象の場合は*)
FROM どのテーブルのカラムかを選ぶ FROM users;
WHERE どこのレコード(横の行)を取得するか WHERE name="aina";
LIKE %をつけることで○○を含むデータを取得する WHERE name LIKE "%aina%";
NOT ○○を含まないデータを取得する WHERE NOT name LIKE "%aina%";
IS NULL 指定したカラムがNULLのデータを取得する WHERE age IS NULL;
IS NOT NULL 指定したカラムがNULLでないデータを取得する WHERE age IS NOT NULL;
AND WHEREに複数の条件を指定する
(どちらも満たすデータを取得する)
WHERE name="aina"
AND age=27;
OR WHEREに複数の条件を指定する
(どちらかを満たすデータを取得する)
WHER name="aina"
OR age=27;
ORDER BY データの並べ方を指定する
(WHEREと併用できる)
ORDER BY age ASC;(昇順)
OREDER BY age DESC;(降順)
LIMIT 取得するデータの件数を指定する
(WHEREと併用できる)
LIMIT 10;
DISTINCT 重複したカラムを省略する SELECT DISTINCT(name)
+ - * / 四則演算
(取得したデータに足し引き割り掛けをする)
SELECT age - 5

【Rails×LIFF】でデートサポートサービス『Date me』を作りました!【個人開発】

Qiitaの記事もご覧いただけたら嬉しいです

qiita.com

サービス概要

LINE botを使ったサービスなので、スマホからご確認ください!

love-dateme.com

ちょっとマンネリしてきた夫婦・カップルに久しぶりのドキドキを提供してくれる、デートサポートサービスです。

  • デート日を決めてもらえれば、あとはアプリがデートのお誘い、当日のアクションのアドバイスをしてくれます。
  • 当日のアクションは、「ミッション」という形でLINEで通知が届くため、リアル体験型ゲームのような感覚で楽しむことができます。

ミッション例:「手をつないでみる」「今日一番素敵だと思うところを伝えてみる」など

使いかた

事前に『Date me』を友達追加しておきます

※パートナーにも必ず友達登録してもらってください!
友達登録されていないと当日のミッションが届きません

M.png
友だち追加

  1. 友達追加したらDate meのLINEを開いて「デートにお誘いする」ボタンをタップ

howto1.png


2. 日程を決めてパートナーに送信

howto2.png


3.パートナーにお誘いが届きます。パートナーが「確認しました!」ボタンを押したら、あとはデート当日を待つだけ

howto3.png


4.デートが始まるとお互いのLINEにミッションが届きます。ミッションをクリアして素敵なデートにしましょう!

howto4.png


このサービスを作った背景

もっと夫婦間のコミュニケーションが活発な世の中になり、今よりさらに「家族で過ごすことが幸せな時間」と思う人が増えたら良いな、という思いから開発しました。

使用技術と主に使用したgem

  • Ruby 2.6.6
  • Rails 6.1.2
  • MYSQL
  • Nginx
  • Puma
  • Capistrano
  • AWS
  • RSpec(テスト)
  • TailwindCSS(CSS)
  • line-bot-api(プッシュ通知)
  • whenever(定期実行)
  • lack-notifier(エラー通知)
  • exception_notification(エラー通知)

工夫した点

デザイン

女性に気に入ってもらえれば男性側には友達追加するよう無理矢理促してくれるはず!ということで(笑)、
開発者の私が女性である視点を活かし、同じ女性に第一印象で「可愛い!使ってみたい!」と思ってもらえるような世界観にすることを意識しました。

例:ランディングページ

Image from Gyazo

ユーザーの目線を取り入れる

ターゲットに近い人(知人や、Twitterのフォロワーさんなど)に実際に使ってもらい、いただいたフィードバックを元に、より使いやすいアプリになるよう改善を繰り返しました。

◆いただいたフィードバックと改善例:

  • パートナーがデートのOKの回答をした後、もう一度同じページを開いた時に404ページにレンダリング
    (回答を変更できないようにするため)
    →この段階ではまだデートが始まってないから、予定確認できた方がありがたい

改善後:スケジュールを確認する導線はリッチメニューからの確認のみでしたが、デートのお誘い確認ページで回答した後も引き続き、内容が確認できるようにしました
(回答後は回答ボタンのみ見えなくなるように実装)

※リッチメニューとは、LINEのトーク画面下部に表示されるメニューのことです↓

richmenu.jpg

  • ミッションのハードルが高い
    →デート時に使うものということで外で使ってみると、周りの目が気になってしまって実行できないものがあった

改善後:改めてミッションの内容を精査し、なるべく多くの人が抵抗なく(もしくはちょっと頑張れば)挑戦できるようなミッション内容に絞りました

ログイン処理をせずに使うことができる

デート中にページを開いてもらうことを考えた時に、いちいちネットで検索してログインし、ページを見てもらうことは難しいと思っていました。
そこで思い浮かんだのが、LINEを使って実装することです。

LINEのLIFFを使いユーザー情報を取得することで、ユーザーにログイン処理をさせることなくユーザーを識別できるようになりました。

ただ、ユーザーにログインしてもらう必要がないからこその問題点もありました。
ユーザー情報の取得はjavascript⇨controllerの順番で処理を行うため、ページを開く瞬間にユーザーを識別する必要のあるページは、ユーザー情報の取得が完了する前にページを開こうとしてエラーになってしまいます。

解決策としては、一度ログインさせるためだけのページに飛ばし、ユーザー情報を取得してから目的のページにリダイレクトさせるようにしました。

Image from Gyazo

今後追加してみたい機能など

  • デートのシチュエーションごと、もしくは難易度別で届くミッションを変えられるようにしたい

現状「恥ずかしくて実行できなかった」という声もあれば「楽しかった」という声もあり、人によってミッションを実行できるレベルはさまざまです。
そこで、難易度別などで分けられればユーザーに合わせたサービスが提供できるため、実装方法を考えていきたいと思っています。

  • Date meからミッションが送られてくる以外に、前日のリマインドや当日デート終了後に「デートはどうでしたか?」のようなメッセージが送られてくるようにしたい

今は最低限の機能を実装しただけの状態なので、よりデートのワクワク感を盛り上げられるような仕掛けを追加していくためのアップデートを考えています。

「自分が作れるもの」ではなく、より良いものを作りたい

去年の10月からRailsを勉強し始め、私にとって初めてのアプリ制作でした。

最初からLINEを使ってアプリを作ろうと考えていたわけではありませんが、『Date me』のサービスを思いつき、今の自分が持っている知識の中で作れるものではなく、よりユーザーにとって使いやすいを優先して考えたときに「LINEの機能を使ってみよう」と決めました。

ありがたいことに、既に様々なユーザーさんに使っていただき、フィードバックもたくさんいただいています。
今後も引き続き、改善できることは常に改善し、よりデートをワクワクさせるような機能も追加していく予定です。

このアプリを使って、パートナーと楽しい時間を過ごす人がさらに増えていったら嬉しいです!

AWSデプロイ時にAn error occurred while installing sassc (2.4.0), and Bundler cannot continue. Make sure that `gem install sassc -v '2.4.0' --source 'https://rubygems.org/'` succeeds before bundling.というエラーが出てきたら

capistranoを使ってAWSへのデプロイをしようと$ bundle exec cap production deploy を実行したところ、以下のエラーと遭遇しました。

cc1plus: out of memory allocating 1085312 bytes after a total of 18100224 bytes
make: *** [parser.o] エラー 1
make failed, exit code 2
Gem files will remain installed in
/var/www/Date_me/shared/bundle/ruby/2.6.0/gems/sassc-2.4.0 for inspection.
Results logged to
/var/www/Date_me/shared/bundle/ruby/2.6.0/extensions/x86_64-linux/2.6.0/sassc-2.4.0/gem_make.out
An error occurred while installing sassc (2.4.0), and Bundler cannot continue.
Make sure that `gem install sassc -v '2.4.0' --source 'https://rubygems.org/'`
succeeds before bundling.

検索しても解決方法が見つけられなかったため、備忘録として残しておきます。

①まず試したこと
エラメッセージの中に「 gem install sassc -v '2.4.0' --source 'https://rubygems.org/'を試してみてください」と書かれているので、まずはそれを実行

$ gem install sassc -v '2.4.0' --source 'https://rubygems.org/'

インストールが成功していることを確認し、再度$ bundle exec cap production deployを実行。

cc1plus: out of memory allocating 1085312 bytes after a total of 18100224 bytes
make: *** [parser.o] エラー 1
make failed, exit code 2
Gem files will remain installed in
/var/www/Date_me/shared/bundle/ruby/2.6.0/gems/sassc-2.4.0 for inspection.
Results logged to
/var/www/Date_me/shared/bundle/ruby/2.6.0/extensions/x86_64-linux/2.6.0/sassc-2.4.0/gem_make.out
An error occurred while installing sassc (2.4.0), and Bundler cannot continue.
Make sure that `gem install sassc -v '2.4.0' --source 'https://rubygems.org/'`
succeeds before bundling.

結果は変わらず…


考えられる原因としては「デプロイ時のsassコンパイルのタイミングでメモリが足りなくなり、落ちてしまっている」ことらしい。


②そこで次に実行したこと
足りないメモリの量を増やすためにインスタンスタイプを増やす

AWSにログインし、EC2のインスタンスをクリックする

f:id:terakura-aina:20210227154341p:plain

該当のインスタンスにチェックを入れ、「インスタンスの状態」をクリックし「インスタンスを停止」に変更

f:id:terakura-aina:20210227154515p:plain

停止したのが確認できたら、「インスタンスの状態」の隣にある「アクション」をクリックし、「インスタンスの設定」→「インスタンスタイプを変更」をクリックする
(インスタンスを停止していないとインスタンスタイプの変更ができないようになっています)

f:id:terakura-aina:20210227154704p:plain

そこで2段階ほど上のメモリを選択し、変更。
私の場合はmicroだったので、smallに変更しました。
インスタンスの状態」→「インスタンスを開始」ボタンを押し、インスタンスを起動させる。

ターミナルで$ bundle exec cap production deployを実行

これで出ていたエラーは消えました!

【rails】登録フォームで日時を15分感覚で選択できるようにする

登録フォームで日時を登録してもらう箇所があり、datetime_fieldでフォームを作っていました。


f:id:terakura-aina:20210209182123p:plain

= form_with(model: @schedule, id: 'form', local: false) do |f|
  = f.label :start_planned_day_at, :開始時間, class: 'control-label'
  = f.datetime_field :start_planned_day_at, class: 'form-control'


ただ、これだと1分単位で時間が選べてしまうため、15分単位で選べるようなフォームにしたくて調べていたところ、datetime_select:minute_stepを使って間隔をしてあげれば良いらしいです。


= form_with(model: @schedule, id: 'form', local: false) do |f|
  = f.label :start_planned_day_at, :開始時間, class: 'control-label'
  = f.datetime_select :start_planned_day_at, class: 'form-control', :minute_step => 15
# ":minute_step => 15" => 15分単位で選択できるようにしてくれる

こんな感じです。
f:id:terakura-aina:20210209182539p:plain

■参考にしたサイト

Railsで簡単に日時選択ができるdatetime_selectメソッドの使い方をまとめてみました - (゚∀゚)o彡 sasata299's blog