20200630のRailsに関する記事は16件です。

JavaScript/jQuery初心者が、アコーディオンメニューの開閉に伴って回転する矢印アイコンをなんとか実装したときの記録

はじめに

JavaScript/jQuery初心者が、コンテンツの開閉状態と連動する矢印アニメーションを、jQueryで実装するまでにやったことの記録です。

3行で

  • thisでクリックした要素にだけ処理を行う
  • アニメーション用のCSSを書く
  • toggleClassでアニメーション用クラスの付け替えをする

環境 + 前提

Rails 5.2.4.3
Ruby 2.6.5
Bootstrap 4.5.0
jquery-rails 4.4.0
sass-rails 5.1.0

このポートフォリオに実装
YWT Quest

Bootstrapのカードを使用。
カードコンポーネントによるアコーディオンを実装していて、card-headerをクリックすると開閉する。

やりたいこと

  1. このようなカードが並んでいて、開閉可能なものには矢印がついている。 スクリーンショット 2020-06-30 0.12.14.png
  2. カードのヘッダー部分をクリックすることで開閉。
  3. カードが開いた時に矢印も回転(アニメーション)する。
  4. カードが閉じる時に矢印が回転(アニメーション)し元の状態に戻す

実装に必要そうなこと

  • card-headerをJavaScriptで指定し、クリックされた時にクラス名を追加する。
  • 追加したクラスに、アイコンの表示を変えるCSSを書く。
  • もう1度クリックされた時には上で追加されたクラスを削除する。

実際にやったこと

1. viewファイルに直書きではなく、JavaScriptを読み込んで使う

まず、assets/javascripts/logs/index.jsを読み込む設定をする。

rails 任意のviewのみで、特定のjsを読み込む方法 - Qiita
logs/index.jsviews/logs/index.slim.htmlに対してだけ読み込ませたいので、上記を参考にviewファイルの下部に以下を記述。

views/logs/index.slim.html
<%= javascript_include_tag 'logs/index.js' %>

2. jQueryでクリックイベントを追加する

card-header部分をクリックすることで開閉可能で、カードが開いた時に矢印も回転するのであれば、card-headerをクリックした時に、矢印が回転するような処理 を書かないといけない。

card-headerはココ

スクリーンショット 2020-06-29 22.32.08.png

card-headerをクリックした、とJavaScript側に分かってもらえてるかどうかをまずチェック。

logs/index.js
$(function(){
  $('.card-header').click(function(){
    alert("click event")
  });
});

card-headerをクリックしてアラートが出ればOK

click-event.gif

どうやらうまくいってるみたい。

3. カードの開閉状態で条件分岐させる

次に、クリックしたカードが開くかどうかをチェック。
現在はcontentカラム(詳細文)が空でなければ開くし、card-headerの文字の右側に矢印が表示される。

つまり矢印の有無でカードが開くかどうかをチェックできる、と考えた。
クリックしたcard-headerfa-chevron-downというクラスが存在すれば開く、しなければ開かない。

jQueryにfindという子孫要素を取得できるメソッドがあったので使ってみる。

【jQuery入門】find()で子要素を取得する手法まとめ! | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト
find(expr) - jQuery 日本語リファレンス

以下のようなコードを書いた。まずは条件分岐が成功するかどうかをチェックする。

logs/index.js
$(function(){
  $('.card-header').click(function(){
    var icon = $(this).find('.fa-chevron-down');
    // 本文がなく、アイコンがないcard-headerをクリックした時はundefinedが返されることを利用した
    if(icon[0] !== undefined) {
      console.log("true");
    } else {
      console.log("false");
    }
  });
});

最初はicon[0] == "<i class=\"fas fa-chevron-down\"></i>"と、icon[0]に入っている情報そのものと照らし合わせたり
icon[0].toString();として文字列に変換してから比較したり
indexOfを使って前方一致(<i classだけ等)で検索をかけてみたりしたが、全て失敗。

どうしよう?とconsole.logを見ていると、開閉できないカードを押したときundefinedが返ってきているのを発見。

「じゃあ、undefinedが返ってきていないときにアニメーション用の処理をすればいいのでは……?」

と考えて、ifの中身をif(icon[0] !== undefined)と書き換えることで、開くカードのcard-headerをクリックしたときにはtrueが、開かないカードのcard-headerをクリックしたときにはfalseが返ってくるようになった。

4. 矢印をアニメーションさせる処理を書く

rotate() - CSS: カスケーディングスタイルシート | MDN

矢印を回転させるにはrotate()プロパティでアイコンを回転させれば良いと考えた。
しかし、肝心のアニメーションの実装は……?

jQueryでCSSのtransform: rotate()を使った回転アニメーションする際のメモ ‹ jQuery ‹ JavaScript ‹ emwaiblog

この記事では、回転用のクラス名を追加することで、回転を実装している。
また、transitionを使うことでtransformをアニメーション化している。

transitionのオプションやプロパティについてはここを参考にした。

【CSS3】Transition(変化)関連のまとめ

まず、開閉に伴ってクラスを付けたり外したりする処理をjQueryで書く。

assets/javascripts/logs/index.js
$(function(){
  $('.card-header').click(function(){
    var icon = $(this).find('.fa-chevron-down');
    // 本文がなく、アイコンがないcard-headerをクリックした時はundefinedが返されることを利用した
    if(icon[0] !== undefined) {
      $('.fa-chevron-down').toggleClass("spined-icon")
    }
    // else以下を削除
  });
});

toggleClassで、fa-chevron-downクラスを持つ要素にspined-iconクラスがついてなければ追加、ついてたら削除する。

これも検証ツールで確認する。

class-toggle.gif

<i class="fas fa-chevron-down>"の横にspined-iconが追加されているのが確認できた。

CSSでspined-iconに矢印を回転させる処理を書く。

assets/stylesheets/logs/index.scss
.spined-icon {
  transform: rotate(90deg);
  transition-duration: 0.5s;
}

transform: rotate(90deg);で要素を90度回転、それが始まってから終わるまでの時間をtransition-duration: 0.5sで設定している。

「0.5秒かけて要素を90度回転させてください」ということ。実際の動きを見てみる。

ohno.gif

閉じるときのアニメーションがない。それはともかく……

クリックしてないカードの矢印も動いちゃってる……

何がいけなかったのか?

コードをもう一度見てみる。

assets/javascripts/logs/index.js
$(function(){
  // 'card-header'クラスを持つ要素をクリックしたとき、
  $('.card-header').click(function(){
    // 'card-header'クラスの子孫要素の中から'fa-chevron-down'クラスを持つ要素を探し、変数iconに格納する
    var icon = $(this).find('.fa-chevron-down');
    if(icon[0] !== undefined) {
      // 'fa-chevron-down'クラスを持つ要素に'.spined-icon'クラスを追加(既にある場合は削除)
      $('.fa-chevron-down').toggleClass("spined-icon")
    }
  });
});

このコード$('.fa-chevron-down').toggleClass("spined-icon")では、fa-chevron-downクラスを持つ全てのi要素にspined-iconクラスを付与することになってしまい、全ての矢印が回転してしまう。

「クリックした要素のみ」「クリックした要素 jQuery」等で検索していると、この記事を見つけた。
jQueryの$(this)の使い方(どこを指してるのか?)

ここに、thisを使ってクリックした要素にのみ処理を行っている例と、thisではなく要素(記事中ではp)を指定してしまった時の例があり、後者では自分の失敗例と同じで全てのp要素に処理が行われてしまっている。

これを参考に、クリックしたcard-headeriにのみクラスを追加/削除する処理を行うコードを考える。
また、クリックしたcard-headeriに処理を行うため、再びfindを使った。

jQueryで子要素を取得するいくつかの方法〜children,find,contents

完成形

icon-animation-kansei.gif

logs/index.js
$(function(){
  $('.card-header').click(function(){
    var icon = $(this).find('.fa-chevron-down');
    // 詳細文がなく、アイコンがないcard-headerをクリックした時はundefinedが返されることを利用した
    if(icon[0] !== undefined) { 
      // thisをつけてクリックした要素にだけ効かせる。そうしないと全部の矢印にtoggleClassが効いてアニメーションしてしまう
      // findで.fa-chevron-downのついた要素を見つけ、そこにクラスを追加している
      // spined-iconというクラスでアニメーションをつけている
      $(this).find('.fa-chevron-down').toggleClass("spined-icon")
    }
  });
});

また、spined-icontoggleClassによって削除されても、fa-cheveron-downtransition-durationを設定することでアニメーションがうまくいった。

logs/index.scss
// ywtのカードヘッダーに、開閉可能な場合つける矢印
@mixin ywt-header-angle($anglecolor: $second-color) {
  i.fa-chevron-down {
    color: darken($anglecolor, 30%);
    // アイコンのクラスに、transitionをつけることで、閉じる際にもアニメーションを有効化している
    transition-duration: 0.5s;
  }
}

// 矢印のアニメーション用
.spined-icon {
  transform: rotate(90deg);
  transition-duration: 0.5s;
}

おわりに

JavaScriptやjQueryへの苦手意識はまだまだ消えないが、console.logで処理や戻り値を追いながら、1つずつ進めていくことで、なんとか実装。
心残りとしては、カードの開閉が可能かどうかをチェックするためのif(icon[0] !== undefined)について。
if(icon[0] == "<i class=\"fas fa-chevron-down\"></i>")じゃなぜダメだったのか?
indexOfが使えなかったのはなぜか?
iconの中の情報はどのように使うのが正解だったのか?

ここらへんに対してしっかり調べて解決することが出来なかったこと。
学習が進み、分かり次第追記予定。

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

TurbolinksでpushStateするには

JavaScriptでURLを変更し、ブラウザーではページ遷移しないようにするには、history.pushStateを使います。Turbolinksが動いている環境でpushStateを使うと、ブラウザーの進む/戻るで挙動がおかしくなります。Turbolinks以外がpushStateしたときページでは、popstateイベントをTurbolinksが処理しないからです。

Aページ -(pushState)-> Bページ -(リンク)-> Cページ -(戻るボタン)-> URLはBだけど画面が変わらない

Turbolinksを使っているときは、次のようにします。/users?name=Taro に戻ると、turbolinks:load イベントが発火するようになります。

let path = "/users?name=Taro";
Turbolinks.controller.
  pushHistoryWithLocationAndRestorationIdentifier(path, Turbolinks.uuid());

参考: Manage browser history manually for one part of my Turbolinks-enabled Rails 5 app - Stack Overflow

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

【Rails】lightbox2を用いて画像拡大機能の実装

目標

ezgif.com-video-to-gif.gif

開発環境

・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina

前提

下記実装済み。

Slim導入
投稿機能実装

実装

1.application.html.slimを編集

application.html.slim
doctype html
html
  head
    title
      | Bookers2
    = csrf_meta_tags
    = csp_meta_tag
    = stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload'
    / 追記
    link href='https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.7.1/css/lightbox.css' rel='stylesheet'
    = javascript_include_tag 'application', 'data-turbolinks-track': 'reload'
    / 追記
    script src='https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.7.1/js/lightbox.min.js' type='text/javascript'

2.image_tagを編集

books/show.html.slim
= link_to @book.image.url, 'data-lightbox': @book.image do
  = image_tag @book.image.to_s
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

link_toに情報を付随する方法

前提

  • ruby on rails 6.0.0 を使用。
  • ファイルの拡張子はhtml.erbである。(haml等を使用している場合は適宜読み替える)

やりたいこと

  • link_toメソッドでページを偏移すると同時に偏移先へ情報を受け渡す。

方法

link_toの偏移先情報(urlやpath、モデル等)に渡したい情報を付随する。

index.html.erb
<% @tags.each do |tag| %>
  <%= link_to movies_path(tag_id: tag.id) do %>
    <%= tag.name %>
  <% end %>
<% end %>

上記の二行目にある通り、偏移先情報の後ろに()で渡したい情報を追記すると、ハッシュの形式で情報を付随することができる。

movies_controller.rb
def index
  @tag = Tag.find(params[:tag_id])
end

といったように、偏移先のコントローラではparam[]の形でパラムとして受け取ることで、渡された情報を扱うことができる。

終わりに

基礎中の基礎ではあるが、それゆえに重要になってくる部分でもあるのでしっかりと使いこなしていきたい。

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

link_toに情報を付随する

前提

  • ruby on rails 6.0.0 を使用。
  • ファイルの拡張子はhtml.erbである。(haml等を使用している場合は適宜読み替える)

やりたいこと

  • link_toメソッドでページを偏移すると同時に偏移先へ情報を受け渡す。

方法

link_toの偏移先情報(urlやpath、モデル等)に渡したい情報を付随する。

index.html.erb
<% @tags.each do |tag| %>
  <%= link_to movies_path(tag_id: tag.id) do %>
    <%= tag.name %>
  <% end %>
<% end %>

上記の二行目にある通り、偏移先情報の後ろに()で渡したい情報を追記すると、ハッシュの形式で情報を付随することができる。

movies_controller.rb
def index
  @tag = Tag.find(params[:tag_id])
end

といったように、偏移先のコントローラではparams[ ]の形でパラムとして受け取ることで、渡された情報を扱うことができる。

終わりに

基礎中の基礎ではあるが、それゆえに重要になってくる部分でもあるのでしっかりと使いこなしていきたい。

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

Rust は流行りそうもないので、Go を使う。

最近、暇で以下のサービスを作った。
https://deau-project.herokuapp.com/

バックエンドには仕事で使ったことがない、Go にした。
勉強してたのは、Rust で、仕事のCSVを分析するシステムを Rust で作ったけど、
この先、使うことがないのでは? と思っている。

以前、Haskell が流行りそうで、だいぶ勉強したけど、今では話題にすらならない。
関数型も、いまいち浸透していない。

流行る言語は、何かしらの手間を無くす。
Ruby が流行ったのは、Rails がフレームワーク使用時の共通作業を無くしたから。
PHP が未だに廃れないのは、WordPress が共通作業を無くしてるから。

Go は流行る。もう流行っている?
理由は学習コストを減らしたから。

今回、Go Gin を使用した、そして、簡単に実装できた。
情報も充分にあった。

Rust でも、情報に関しては充分にある。
ただ、実装時に面倒だなと感じることが多い。
私のように趣味で実装するなら、尚更、面倒に感じる。

Rust が流行るには、組込み系にターゲットを絞るか、
当時の Rails のような手間を省く何かが必要だと思う。
組込み系で考えれば、C++でよくあるミスを防げる。確認の手間を省ける。

今回、サーバーサイドに Go を使用したが、この先はどうかわからない。
趣味でならいいが、仕事で使うとなると、関数型である必要がある。
もし、今から新しいシステムを作るとして、サーバーサイドに何を使用すればいいのか。

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

MySQLの稼働が安定しない…Railsアプリが起動していない。

発生した背景

MySQLサービスがまたもやエラー。何回も発生すると、流石に時間の浪費に怯えてしまいます。以下エラー内容になります。

Can't connect to local MySQL server through socket '/tmp/mysql.sock' 

環境

項目 内容
OS.Catalina v10.15.4
Ruby v2.5.1
Ruby On Rails v5.2.4.3
MySQL v5.6

対応手順

【調査1】MySQLが起動しているか。
僕は「SequelPro」を使っているので、接続してみる。→接続エラー

プロセスの稼働状況を確認
CMD>ps -ef | grep mysql
  501  1287     1   0 11:45AM ??         0:00.06 /bin/sh /usr/local/opt/mysql@5.6/bin/mysqld_safe --datadir=/usr/local/var/mysql
  501  6400  1287   0 11:55AM ??         0:00.51 /usr/local/opt/mysql@5.6/bin/mysqld --basedir=/usr/local/opt/mysql@5.6 --datadir=/usr/local/var/mysql --plugin-dir=/usr/local/opt/mysql@5.6/lib/plugin --log-error=ichikawadaisukenoMacBook-Air.local.err --pid-file=ichikawadaisukenoMacBook-Air.local.pid
  501  6402   804   0 11:55AM ttys000    0:00.01 grep mysql

!?稼働しているようには見える!?

【調査2】まずはエラー内容から。ソケットファイルがないと言われているので、以下のコマンドで対応してみました。

ソケットファイルを試しに作成してみる。
CMD>cd アプリケーションフォルダ
CMD>touch /tmp/mysql.sock

→結果、改善せず。

【調査3】ログを確認してみる。

MySQLのログを確認
CMD>more /usr/local/var/mysql/ichikawadaisukenoMacBook-Air.local.err
(一部省略)
mysqld_safe A mysqld process already exists

※この後再起動するも、改善ならず。

対応

プロセスが多重起動している様子。既存の稼働中のプロセスを停止する。

プロセスの停止
CMD>kill -9 対象のサービスプロセス

今回はこれだけで改善しました。しかし、まだ以下のエラーメッセージが出力されたままです。

200616 16:04:42 mysqld_safe A mysqld process already exists

対応は後日にしようと思います。

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

モノリスはクラピカ

Reactを学習中のRailsエンジニアです。学習していて思うのは、Reactは(サービス開発全体のことを考えると)Railsよりはるか学習コストが高いということ。似たようなサービスを作るために必要な手数も、考えなければいけないこともかなり多いです。

正直最初は「技術が大好きなエンジニアの自己満だろ」「Railsに飽きた奴らがやってるだけだろ」くらいに思っていたのですが、そうとも限らないことが腹落ちして理解できるようになったので、現在の考えをまとめてみようと思います。

おことわり

この記事の中で登場するSPAという単語はフロントエンドとバックエンドを明確に分けて開発されるアプリケーションくらいの意味として解釈してください。フロントエンドのロジックをNuxt.jsで作ってNetlifyにデプロイして、Goで作ったAPIをAWSで動かす、みたいな構成のやつです。乱暴ですみません。他に良い表現があればコメントください。

モノリスはRailsやLarabelでviewファイルの生成まで行っているアプリケーションを指します。

SPA⇄MPA
マイクロサービス⇄モノリス
で比較しろよ、って話ですが、マイクロサービスについて語れるほどの知識はないし、MPAというよりモノリスの話がしたかったので、雰囲気で読んでください。

SPAが台頭した理由

よりリッチな表現ができる(UXの向上)

ページ遷移が高速、DOMを色々動かしてもコードがカオスになりにくいなど。SPAのメリットとして真っ先にあげられることが多いので、みなさんもよくご存知かと思います。

フロントエンドとバックエンドが疎結合になる

疎結合になると、新技術を部分的に採用することが容易になります。またサービスの規模が大きくなっても、コードがカオスになりづらいです。Railsエンジニアをやっていると、成長し大規模化したRailsアプリ開発者がつらそうにしている記事をよく見かけます。

クロスプラットフォーム対応

SPAを採用すると、web、iOS、Android、macOS用アプリ、windows用アプリで同じAPIを使うことができます。
元々web以外のプラットフォームでは、表示周りやページ切り替え等のロジックを先にインストールして、他に必要なデータのやりとりだけをAPIを使って行う、というスタイルで統一されていました。webも同じスタイルに揃うと構成がキレイになってすっきりしますね。

マネージドサービスの充実

この記事を書くに至った理由です。この視点を得て、SPAが普及したことの必然性を理解しました。
2020年現在、ざっと思いつくだけでも以下のようなマネージドサービスが存在します。

認証: Firebase Auth, Auth0, Cognito
決済: Stripe
検索: Algolia
サーバーレスコンピューティング: Lambda, Cloud Functions
NoSQL: CloudFirestore, DynamoDB
ストレージ: S3
メール送信: SendGrid

ここで言えるのは、バックエンドで自前で実装しなければいけない機能が大幅に減ったということです。
「外部サービスをどれだけ有効に活用できるか」が重要になってくると、モノリスの魅力は相対的に薄れていきます。

そもそもRuby on Railsが登場した2004年にはAWSすら存在しておらず、モノリスがwebアプリ開発のど真ん中に鎮座していた2010年代前半にも、上記で紹介したサービスの多くは存在していませんでした。

いくらRuby on Railsも進化しているとはいえ、これだけ状況が変わってしまえば、開発のメインストリームから外れてしまうのは仕方のないことだと感じます。

また余談ですが、Rubyの認証ライブラリで1番人気があるDeviseを使っている人は、全員つらそうな顔をしています。

その他

  • コンポーネント単位で分割することで保守性や再利用性が高くなったり、デザイナーとの協業がしやすくなる
  • TypeScriptとVSCodeの連携がすごい

などなど他にもSPAのメリットは色々とありそうですが、これらはどちらかというと副産物に近く、SPAが台頭したメインの理由では無いと考えています。

モノリスは用済みになったのか

全くそんなことは無いと考えています。
以下の条件を満たすアプリケーション開発では、今でもモノリスがファーストチョイスです。
「モノリスでも問題ない」ではなく、「モノリスの方が圧倒的に良い」です。

  • webだけで良い
  • 関わる開発者が少ない
  • UXの要件がそれほど厳しくない

具体的な場面としては

  • 多くのwebアプリののプロトタイプ
  • リリース後の修正が少ないと予想されるシステム
    • 機能要件が指定された受託開発など
    • 「この機能を削ればこの予算で実現できます」など仕様をモノリスに寄せることで双方が得をする場面は必ず存在する
  • 小~中規模のwebアプリの一部
    • 必要な要件や、想定されるユーザー数などから技術選定。モノリスの方が効率良く開発できるサービスは、今後もそこそこの割合で残り続けるはず。

などが考えられます。

モノリスの最大の弱点とされる密結合は、必ずしも悪ではないのです。
分割は短期的な生産性を下げます。
密結合は短期的な生産性を上げます。
この点を考慮して技術選定をするべきです。

結論

特定の制約の上で、モノリスはもの凄い力を発揮します。

参考

Next.js,、Nuxt.jsが次世代のRailsになるという話についてどう思いますか? - Quora

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

レコードの新規追加時に登録データにMAX+1のIDを付与する方法

Railsでレコードの新規追加をする際に、自動的に独自IDの付与をしたいケースがあると思います。
例えば、my_idフィールドの最大値+1を付与するなど。

部屋(room)の名前を登録したときに、独自id = my_id を付与するサンプルを書いてみました。

成功例

  def assign
    my_id = -1
    room = Room.find_by(room: params[:room])
    if !room.nil?
      my_id = room.my_id
    else
      Room.connection.execute(
        "INSERT INTO rooms (my_id, room, created_at, updated_at) SELECT COALESCE(max(my_id), 0)+1, '#{params[:room]}', '#{Time.now}', '#{Time.now}' from rooms"
      )
      my_id = Room.find_by(roomr: params[:room]).my_id
    end
    redirect_to("/rooms/#{my_id}")
  end

ポイントは

  • my_idの最大値検索をINSERT文のサブクエリで行い、一回のクエリ発行になるようにすること (排他)
  • created_at, update_atに現在時刻を設定すること
  • COALESCEでnull対策をすること

失敗例

  def assign
    my_id = -1
    room = Room.find_by(room: params[:room])
    if !room.nil?
      my_id = room.my_id
    else
      new_room = Room.create(
        my_id: Room.max(my_id) + 1,
        room: params[:room]
      )
      my_id = new_room.my_id
    end
    redirect_to("/rooms/#{my_id}")
  end

失敗例のほうでは、begin transaction ~ commit transaction の間に

  1. SELECT文 --> Room.max(my_id)の検索のため
  2. INSERT文 --> Room.createのため

が発行されるのですが、
複数のクライアントから同時にassignを呼ばれた際に排他が十分でなく
my_idが重複してしまいます

本当は

本当は生SQLは発行せずにActiveRecordで記述したいのですが、
いい方法ないですかね?

参考URL

INSERT時にカラムの最大値+1を持ってくる
INSERT文と同時にMAX+1を行いたいです。
INSERT時にデータ登録とmaxの発番がしたい
ActiveRecord の find_or_create_by を確実に実行するには

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

Ruby on Railsでfont awesomeを使う方法

gemfileに追記する

下記をgemfileに追加する。

# font awesome
gem 'font-awesome-rails'
bundle install

application.cssへ追記する

下記をapplication.cssのコメントの中に追記する。

application.css
*= require font-awesome

sassのかたは、普通にコメント外のコードを書くところに下記のように記載。

application.scss
@import "font-awesome";

viewファイルにタグを追加

<i class="fa fa-アイコン名"></i>

参考記事

https://pikawaka.com/rails/font_awesome_rails

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

【整理】render&redirect_toが、ごっちゃになってしまうあなたへ

対象者

なんかredirect_toとかrenderとかそれぞれどんな違いあるんだっけ?使い方は?と、知ってるけど頭の中で整理できていない方

前提知識

Railsのコントローラにおけるアクションでは、最終的にrenderされてビューを返す仕組みになっている。
つまり、1アクションにつき、1renderが必ず起こる。

def index
end

これは、render 'index'が発動していることと同じことである。

エラー例

renderが2回処理されてしまう時

def show
  ~~
    if ~~
      ~~
      render 'index'
    end
  render 'show'
end

解決策としては、returnをしてあげる

def show
  ~~
    if ~~
      ~~
      render 'index'
      return
    end
  render 'show'
end

render

アクション内で、呼び出すビューを指定するメソッド。
つまり、デフォルトで呼び出されるビュー以外のものを呼び出すことができる。
呼び出すビューの形式は、RHTML形式(.html / html.erb等)

  • 同じコントローラの別アクションビューを呼び出す時
microposts_controller.rb
def index
  render 'edit'
  render :edit
end
  • 別コントローラのアクションビューを呼び出す時
microposts_controller.rb
def index
  render "users/show"
  render template: "users/show"
end
  • 別ディレクトリや別アプリのアクションビューを呼び出す時
microposts_controller.rb
def index
  render "/warehouse_app/app/views/products/show"
  render file: "/warehouse_app/app/views/products/show"
end

redirect_to

指定したURLへGETリクエストを送信するメソッド。
つまり、アクション内で発動すれば、再度RCVを呼び出すことになる。

  • 指定のページに飛ばす
microposts_controller.rb
def index
  redirect_to root_url
end
  • 直前のページに戻す
microposts_controller.rb
def index
  redirect_back(fallback_location: root_path)
end

参考にさせていただきました

Railsガイドライン
https://railsguides.jp/layouts_and_rendering.html#render%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B

@1ulce様
https://qiita.com/1ulce/items/282cccba1e44158489c8

@morikuma709様
https://qiita.com/morikuma709/items/e9146465df2d8a094d78

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

[�個人アプリ開発]フロント実装の事前準備

はじめに

今回、開発工程のアウトプットはフロント実装の事前準備です。
①hamlの導入、②ルーティングの設定、③コントローラーの設定、④ビューの設定、⑤scssの設定、⑥リセットcssの設定をアウトプットしていきます。

hamlの導入

今回開発するアプリのフロント実装にはhamlを使います。(個人的にerbより断然haml派)
まずhamlの使用を可能にする為にgemをインストールします。

gem 'haml-rails'

その後ターミナルにてbundle installを実行し、ローカルホスト3000を再起動。
#ここで再起動を忘れるとhamlファイルを更新してもエラーが発生するので注意

ルーティングの設定

ローカルホスト3000へのリクエストに対してルーティングを設定します。

routes.rb
Rails.application.routes.draw do
  root "goals#index"
end

今回はgoalsテーブルを作成しており、goalsコントローラーのindexアクションを設定しています。

コントローラーの設定とビューの作成

続いてコントローラーを作成します。
ターミナルにてrails g controllerを実行。

rails g controller goals index

これでgoalsコントローラーのindexアクションが設定されました。
この時に以下の2点が追加作成されているかを確認▼

①goalsコントローラーにindexアクションが作られている
②viewsのgoalsフォルダにindex.html.hamlファイルが作られている
(#bundle install後に再起動を忘れている場合は、index.html.erbが作成される)

この後アプリが正しく動作する為には、予めDBが作成されていないとエラーが発生するので、
以下のコマンドを実行▼

rails db:create

これでローカルホスト3000にアクセスするとデフォルトビューが表示されているはずです。
確認しておきましょう。

scssの設定

ファイルの拡張子が違うと設定が反映されない為、以下のファイルを編集▼

①app/assets/stylesheets/application.cssの中身を全て消す
②application.cssの拡張子を変更して「application.scss」に変更

これから追加する全てのスタイルシートはapplication.scssから@import(パーシャル)を使って読み込みます。

リセットcssの設定

ブラウザによってデフォルトで設定されたcssによって、予期せぬ誤作動を防ぐ為にリセットcssを設定します。
手順は以下の通り▼

①app/assets/styleseetsディレクトリにreset.scssファイルを作成しましょう
②application.scssに以下の記述を行い、
reset.scssを読み込むようにしましょう。

application.scss
@import "reset";

③リセットcssはYUI 3を使用します。以下のコードを先程作成した_reset.scssに記述します。

_reset.scss
/*!
 * YUI 3.5.0 - reset.css (http://developer.yahoo.com/yui/3/cssreset/)
 * http://cssreset.com
 * Copyright 2012 Yahoo! Inc. All rights reserved.
 * http://yuilibrary.com/license/
 */
/*
    TODO will need to remove settings on HTML since we can't namespace it.
    TODO with the prefix, should I group by selector or property for weight savings?
*/
html{
    color:#000;
    background:#FFF;
}
/*
    TODO remove settings on BODY since we can't namespace it.
*/
/*
    TODO test putting a class on HEAD.
        - Fails on FF.
*/
body,
div,
dl,
dt,
dd,
ul,
ol,
li,
h1,
h2,
h3,
h4,
h5,
h6,
pre,
code,
form,
fieldset,
legend,
input,
textarea,
p,
blockquote,
th,
td {
    margin:0;
    padding:0;
}
table {
    border-collapse:collapse;
    border-spacing:0;
}
fieldset,
img {
    border:0;
}
/*
    TODO think about hanlding inheritence differently, maybe letting IE6 fail a bit...
*/
address,
caption,
cite,
code,
dfn,
em,
strong,
th,
var {
    font-style:normal;
    font-weight:normal;
}

ol,
ul {
    list-style:none;
}

caption,
th {
    text-align:left;
}
h1,
h2,
h3,
h4,
h5,
h6 {
    font-size:100%;
    font-weight:normal;
}
q:before,
q:after {
    content:'';
}
abbr,
acronym {
    border:0;
    font-variant:normal;
}
/* to preserve line-height and selector appearance */
sup {
    vertical-align:text-top;
}
sub {
    vertical-align:text-bottom;
}
input,
textarea,
select {
    font-family:inherit;
    font-size:inherit;
    font-weight:inherit;
}
/*to enable resizing for IE*/
input,
textarea,
select {
    *font-size:100%;
}
/*because legend doesn't inherit in IE */
legend {
    color:#000;
}
/* YUI CSS Detection Stamp */
#yui3-css-stamp.cssreset { display: none; }

これでリセットcssの設定は完了です。

最後に

事前準備は以上です。
今後も個人開発アプリの作業工程をアウトプットしていくので、参考にして下さい!

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

Rails requireメソッドとpermitメソッドについて

※間違いなどありましたらコメントください。

ストロングパラメーター

意図しないデータの登録・更新を防ぐため、特定のキーしか受け取れないようにするもの。
ユーザーに関係するパスワードや名前などの重要な情報を悪意ある変更から守ってくれます。
privateメソッド内に記述するのが一般的です。

requireメソッド・permitメソッド

user.controller.rb
private
def user_params
  params.require(:キー).permit(:カラム名1,:カラム名2,・・・)
end

・requireメソッド
params内の特定のキーに紐づく値を抽出

・permitメソッド
指定したカラム名の値を取得することができる

user.controller.rb
private
def user_params
  params.require(:user).permit(:name,:email)
end

上のケースでは、Userモデルに存在するnameカラムとemailカラムの値を受け取ります。

参考サイト

【Ruby on Rails】ストロングパラメータって何なの?
https://qiita.com/ozackiee/items/f100fd51f4839b3fdca8
【Rails】requireとpermitメソッド
https://qiita.com/morikuma709/items/2dc20d922409ae7ce216

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

[個人アプリ開発]データベース設計

はじめに

6/29データベース設計を行いました。その際に取り入れた作業をアウトプットします。

データベース設計流れ

①機能の洗い出し▼
開発アプリの機能を箇条書きで洗い出します。(先日READMEに記述済み)
次に、洗い出した機能にはどういったカラムが必要であるのか選定を行い、各カラムに必要な制約を決める。

②アソシエーションを把握▼
ER図を自分なりに書き出し、アソシエーションを把握しておく。

③READMEへ記述
最後にマークダウン記法を使用しREADMEへ記述します。

#マークダウン記法についてわからない方はこちらのURLを参考にしてください▼
https://www.asobou.co.jp/blog/bussiness/markdown#:~:text=Markdown%EF%BC%88%E3%83%9E%E3%83%BC%E3%82%AF%E3%83%80%E3%82%A6%E3%83%B3%EF%BC%89%E3%81%AF%E6%96%87%E7%AB%A0,%E3%81%AB%E3%82%88%E3%81%A3%E3%81%A6%E9%96%8B%E7%99%BA%E3%81%95%E3%82%8C%E3%81%BE%E3%81%97%E3%81%9F%E3%80%82

④データベース設計の記述例

<!-- ユーザー管理機能 -->
<!-- usersテーブル -->
|Column|Type|Options|
|------|----|-------|
|id|integer|null: false|
|name|string|null: false|
|mail|string|null: false, unique: true|
|pass|string|null: false, unique: true|
<!-- アソシエーション -->
has_many :messages

マークダウン記法が反映されると以下のようになります▼

Column Type Options
id integer null: false
name string null: false
mail string null: false, unique: true
pass string null: false, unique: true

has_many :goals

最後に

ここまででデータベース設計は完了です。
次回作業工程はフロント実装の事前準備としてルーティング、コントローラー、ビューの設定を行い、Hamlを導入します。

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

消せいないプロセスID(PID)の消去方法!(Vim、Viでの操作不能の対処)

$ sudo visudoのコマンド入力できなくなり凄く困ったので解決方法を記載します!

 何かの不具合で、.ssh %の状態もしくは[ec2-user@ip-xx-x-x-xxx] $から強制終了されるとターミナルでのコマンド入力ができなくなる時があります。

 私も、過去に似たような経験をしたことがあり、多分プロセスIDが正常に切られなかったため、ec2-userにログインした際、$ sudo visudoが入力できないと予測しました。
発生したエラーは下記です

エラー文
visudo: /etc/sudoers がビジー状態です。後で再試行してください

 この問題を可決するのに凄く時間を費やしたので、プロセスID(PID)の一般的な消去方法プロセスID(PID)が無限に増殖する際の消去方法について記載したいと思います。

1. 基本のプロセスID(PID)の消去方法!

1. ターミナルでルートディレクトリーに移動する。または、.ssh %の状態もしくは[ec2-user@ip-xx-x-x-xxx] $にする。

ターミナルの初期画面の状態
xxxxxxxxx@xxxxxxxxxxMacBook-xxx ~ % (例です)

2.psを入力する

ルートディレクトリー
xxxxxxxxx@xxxxxxxxxxMacBook-xxx ~ % ps
.ssh
xxxxxxxxx@xxxxxxxxxxMacBook-xxx ~ .ssh % ps
ec2-use
[ec2-user@ip-xx-xx-xx-xxx ~]$ ps

3.PID(プロセスID)が表示されるのを確認する

psを入力すると下記の図のような画面が表示されると思います。
スクリーンショット 2020-06-30 1.07.29.png

4.PID(プロセスID)をkillorkill -9 で削除する

(私はec2-userの状態でエラーが発生したため、ec2-user状態での記載例を載せる)

[ec2-user@ip-xx-xx-xx-xxx ~]$ kill PIDの数値 or kill -9 PIDの数値
[           入力例  ~] $ kill *** or kill -9 *** (*** = PID)

kill -9 (PID番号) で入力すると強制的に終了させる事ができる。

5.PID(プロセスID)が消去できれば、問題なく動作可能

私の場合、この手順ではPID(プロセスID)の消去ができませんでした。実際に起きていた問題は、PID(プロセスID)を消去しても無限に再生される状態でした。

2. PID(プロセスID)の無限出現の消去方法

ここからが本題です!
私を苦しめたPID(プロセスID)の無限出現です。消し方が分かればすごく簡単に直せます!

1. ターミナルでルートディレクトリーに移動する。または、.ssh %の状態もしくは[ec2-user@ip-xx-x-x-xxx] $にする。

ec2-use
[ec2-user@ip-xx-xx-xx-xxx ~]$ (例です)

私は、ec2-user内で発生したので、上記の状態で説明を続ける

2.ps l を入力する

ec2-use
[ec2-user@ip-xx-xx-xx-xxx ~]$ ps l

3.プロセスごとの実行状態を確認する

  • 下記のような画面が表示されると思います スクリーンショット 2020-06-30 0.29.24.png

4.WCHANの列にあるwait_wのPID(プロセスID)をkillで消去する

詳細画面を載せておきます スクリーンショット 2020-06-30 0.29.35.png

killやり方
[ec2-user@ip-xx-xx-xx-xxx ~]$ kill PIDの数値 or kill -9 PIDの数値
[           入力例  ~] $ kill *** or kill -9 *** (*** = PID)

5.無限増殖するプロセスID(PID)の消去ができたため、無事に入力可能となる!

参考資料

psのコマンドの種類は下記のps コマンド集に記載されてます。
もし、ご興味がありましたら見て下さい!
ps コマンド集

最後に

以上で、消せいないプロセスID(PID)の消去方法(プロセスID無限増殖)の説明を終わりたいと思います。間違っているてん、不明点があればご指摘頂けると助かります。

最後までご覧いただき、ありがとうございました。

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

消せないプロセスID(PID)の消去方法!(Vim、Viでの操作不能の対処)

$ sudo visudoのコマンド入力できなくなり凄く困ったので解決方法を記載します!

 何かの不具合で、.ssh %の状態もしくは[ec2-user@ip-xx-x-x-xxx] $から強制終了されるとターミナルでのコマンド入力ができなくなる時があります。

 私も、過去に似たような経験をしたことがあり、多分プロセスIDが正常に切られなかったため、ec2-userにログインした際、$ sudo visudoが入力できないと予測しました。
発生したエラーは下記です

エラー文
visudo: /etc/sudoers がビジー状態です。後で再試行してください

 この問題を可決するのに凄く時間を費やしたので、プロセスID(PID)の一般的な消去方法プロセスID(PID)が無限に増殖する際の消去方法について記載したいと思います。

1. 基本のプロセスID(PID)の消去方法!

1. ターミナルでルートディレクトリーに移動する。または、.ssh %の状態もしくは[ec2-user@ip-xx-x-x-xxx] $にする。

ターミナルの初期画面の状態
xxxxxxxxx@xxxxxxxxxxMacBook-xxx ~ % (例です)

2.psを入力する

ルートディレクトリー
xxxxxxxxx@xxxxxxxxxxMacBook-xxx ~ % ps
.ssh
xxxxxxxxx@xxxxxxxxxxMacBook-xxx ~ .ssh % ps
ec2-use
[ec2-user@ip-xx-xx-xx-xxx ~]$ ps

3.PID(プロセスID)が表示されるのを確認する

psを入力すると下記の図のような画面が表示されると思います。
スクリーンショット 2020-06-30 1.07.29.png

4.PID(プロセスID)をkillorkill -9 で削除する
(私はec2-userの状態でエラーが発生したため、ec2-user状態での記載例を記載します)

[ec2-user@ip-xx-xx-xx-xxx ~]$ kill PIDの数値 or kill -9 PIDの数値
[           入力例  ~] $ kill *** or kill -9 *** (*** = PID)

kill -9 (PID番号) で入力すると強制的に終了させる事ができる。

5.PID(プロセスID)が消去できれば、問題なく動作可能

私の場合、この手順ではPID(プロセスID)の消去ができませんでした。実際に起きていた問題は、PID(プロセスID)を消去しても無限に再生される状態でした。

2. PID(プロセスID)の無限増殖の消去方法!

ここからが本題です!
私を苦しめたPID(プロセスID)の無限増殖です。消し方が分かればすごく簡単に直せます!

1. ターミナルでルートディレクトリーに移動する。または、.ssh %の状態もしくは[ec2-user@ip-xx-x-x-xxx] $にする。

ec2-use
[ec2-user@ip-xx-xx-xx-xxx ~]$ (例です)

私は、ec2-user内で発生したので、上記の状態で説明を続けます。

2.ps l を入力する

ec2-use
[ec2-user@ip-xx-xx-xx-xxx ~]$ ps l

3.プロセスごとの実行状態を確認する
下記のような画面が表示されると思います
スクリーンショット 2020-06-30 0.29.24.png

4.WCHANの列にあるwait_wのPID(プロセスID)をkillで消去する

詳細画面を載せておきます 
スクリーンショット 2020-06-30 0.29.35.png

killやり方
[ec2-user@ip-xx-xx-xx-xxx ~]$ kill PIDの数値 or kill -9 PIDの数値
[           入力例  ~] $ kill *** or kill -9 *** (*** = PID)

5.無限増殖するプロセスID(PID)の消去ができたため、無事に入力可能となる!

参考資料

psのコマンドの種類は下記のps コマンド集に記載されてます。
もし、ご興味がありましたら見て下さい!
ps コマンド集

最後に

以上で、消せないプロセスID(PID)の消去方法(プロセスID無限増殖)の説明を終わりたいと思います。間違っている点がありましたらご指摘頂けると助かります。

最後までご覧いただき、ありがとうございました。

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